oauth-2.0on-behalf-of

OAuth 2.0 OBO flow with multiple middle-tier APIs


I have 2 applications where the user is set up for SSO using SAML. I'll call these apps "App 1" and "App 2". The user interacts with App 1 through a UI. I have been developing an API (which I'll call "the API") that App 1 will make requests to. The API will sometimes make requests to App 2. I want to use the OAuth On-Behalf-Of (OBO) flow so that I can maintain user context from App 1 to the API to App 2.

Exchanging a SAML assertion for an OAuth token for API 1 is pretty straightforward, as is exchanging that token for a new one via the OBO flow to access the API. I also understand how to exchange that token for another to access App 2 from the API. However, how do I manage the set of access tokens for making requests to App 2 from the API when there are multiple concurrent users? Should I be constantly requesting a new token for each request from App 1? Should I cache these tokens with a session ID as key? App 1 to the API is simple since the user provides their own access token. However, it seems like the API would need to decide on a token to use since it is the same entity making requests each time.

I haven't been working with OAuth for long, so any advice on best practices (or even a better approach) would be much appreciated! Please do note that there is a requirement that the API exist between App 1 and App 2. I also am not able to make changes to APIs exposed by App 1 and App 2.


Solution

  • It is common for OAuth secured APIs to use caching to improve efficiency when working with tokens, claims and authorization data. Consider the following steps within an API.

    Use a thread-safe memory cache for your API technology stack that supports caching items with a time to live. Read the incoming token's exp claim. Cache any data for a time to live that does not exceed that value.

    cache.set(accessTokenHash, myData, secondsToCache);
    

    In your case, myData would be the exchanged access token. On subsequent requests with the same incoming access token, recalculate the hash of the incoming access token and write code like this:

    var myDataOrNull = cache.get<MyData>(accessTokenHash);
    

    Using memory caching is preferred over a distributed cache that would need its own security solution. In clustered environments, each API instance would cache distinct exchanged tokens for the same incoming access token, but this technique should mean your API performs well enough.