3

I'm accessing an API where you authorize first, and you get an access token back, which you use in successive calls. At some point (hours later), the access token expires. So I'm caching the token on the server so any users using the web app will initiate API calls using that token.

But when it expires, I do a recursive call after updating the access token. So, for example (in pseudo-JS):

function getDetails (id) {
  data = HTTP.get(url, {params: ...});

  if (!data.success) {
    updateToken(function () {
      return getDetails(id);
    });
  } else { /*.. we're good*/ }
}

There would also be a recursion depth check in there too. If there's a better way to do this, I'd love to hear it. Basically:

  1. Call API
  2. (failure)
  3. Update token
  4. Call API again
royhowie
  • 11,075
  • 14
  • 50
  • 67
CaptSaltyJack
  • 15,283
  • 17
  • 70
  • 99
  • 1
    What happens if they don't have permission to use the API? Will your function cause a stack overflow? (Perhaps you should only perform the recursion once.) – royhowie Jul 15 '15 at 22:59
  • I see what you did there! ;) For the sake of argument, let's assume they have permission. The original access token is valid because the Node.js server authorized with a secret key/password. And yes, my recursion checker only allows for one level of recursion. – CaptSaltyJack Jul 15 '15 at 23:00
  • i had to use api like this too, reddit's api. Basically upon message from api if there is error you check what error is and if it's that you aren't authenticated like it will happen eventually you ask for new token and update the existing token to this new token and then continue from where you left off. So you have the right idea, i dont think there is another way apis are designed like that. – Muhammad Umer Jul 15 '15 at 23:03
  • @MuhammadUmer Yes, it's the "continue from where you left off" part I'm asking about. If the token was valid at one point, then it expires, we have to get a new token, then try the API call again that just failed. I was just wondering if there was a better or cleaner way than recursion. – CaptSaltyJack Jul 15 '15 at 23:04

2 Answers2

1

That is exactly how I set it up. However, if you have access to promises (e.g., bluebird or babel.js), it becomes even nicer syntactically. Here's your code rewritten with promises and es6:

function getDetails (id) {
    // the return is optional; return the promise if you want to chain to `getDetails`
    return HTTP.get(URL, id, params)
    .catch((err) => {
        if (err.VALIDATION_ERROR) {
            return updateToken().then(() => HTTP.get(URL, id, params))
        } else {
            throw err
        }
    }).then((yourRequest) => {
        // data here
    }).catch((err) => {
        // handle fatal error
    })
}
royhowie
  • 11,075
  • 14
  • 50
  • 67
  • Nice! I'm using Meteor, so I can add the Babel package to get ES6 support. I don't know why I was recursing when I could've simply called `HTTP.get` again. – CaptSaltyJack Jul 15 '15 at 23:29
  • 1
    Do note, though, that `return getDetails(id)` in your original code would not work, since it'd return the result to the anonymous function passed to `updateToken`. – royhowie Jul 15 '15 at 23:35
  • Guilty as charged. I always make that mistake. – CaptSaltyJack Jul 15 '15 at 23:38
  • @CaptSaltyJack [if you plan on using callbacks](http://stackoverflow.com/q/14220321/2476755) – royhowie Jul 15 '15 at 23:39
  • Going with this answer. Matthew Herbst's is good too (about the timer), but I don't like the idea of trusting a timer. The server running the API could reboot. Or they could change the expiration time at some point. Too many unknowns. Reacting to an invalid token error and fetching a new one seems the way to go. – CaptSaltyJack Jul 15 '15 at 23:48
0

The best way would be to keep a timer, since you know how long the session lasts for. That was you can preemptively ask for a new token before your current token/session expires. Using this method also ensures that you never have an interruption of service (unless your request for a new token fails of course). Other than that, you seem to have the rest.

Of course, you will still need to implement the code you have shown us to deal with unexpected session expiration (maybe the API owners decide to invalidate all sessions because of a data breach, etc).

Matthew Herbst
  • 29,477
  • 23
  • 85
  • 128
  • I like that idea. But unfortunately I don't always know the session timeout. And even if I do, if I were to restart the Node.js server and it re-authorizes, it will still be the same token returned (like with Salesforce), then the server will have no idea when the expiration is. – CaptSaltyJack Jul 15 '15 at 23:23
  • How could you not know the timeout? Unless the API code is constantly changing, the session length should remain fairly constant. If the server restarts, you can by default ask for a new token rather than using an old one. – Matthew Herbst Jul 15 '15 at 23:29
  • How would I not know the timeout? Poor API documentation, for one. – CaptSaltyJack Jul 15 '15 at 23:31
  • Hmm, that always sucks. Have you checked the response/headers returned by a successful auth? They might give you session information somewhere in there. – Matthew Herbst Jul 15 '15 at 23:32