0
votes

I am working on creating an OpenID Connect (OIDC) Provider based around django-oidc-provider. I have been reading up on the OpenID Connect Spec, and I cannot figure out how access tokens are unique for a certain application.

Consider the following example with a user, Bob:

Bob wants to login to application A, so he goes to its interface and is redirected to the OIDC Provider. After authentication he is redirected (implicit flow) back to Application A with an ID token and an access token. He then makes a request at "/image/1" to A's API with his access token. The API uses the access token to reach out to the OIDC Provider to assert the user's identity as Bob. The API then returns the data at "/image/1" for user Bob, assuming that info exists. Bob continues to send his access token to A's API for any subsequent requests.

Then, Bob decides he wants to access application B's API. He sends B's API the same access token that he used with A's API. B's API reaches out to the OIDC Provider with the token and asserts the user's identity as Bob. B's API then returns the requested info for Bob.

What prevents this from happening? I see at least two possible solutions to this:

  1. When reaching out to Google's token validation endpoint the "aud" parameter is returned. Application B's API would have to check this parameter to decide that the token is not valid for it's own API?
  2. An additional scope must be added when requesting the token that is specific to the resource provider say "app-A-api". Then when an API is validating a token, the API would ensure the token contains the needed scope.

Which of these methods, or others, are in line with the OIDC spec? If one of the above should be used, am I correct in assuming I should add a new /tokeninfo endpoint that returns the scope or aud, rather than add that info to the info returned at the /userinfo endpoint?

Any input is appreciated. I think a lot of my confusion comes from not seeing the "scope" param being used to delegate access to a resource provider in any OIDC examples.

1

1 Answers

1
votes

I think the thing you are missing is that the application A and its API are two separate applications. So the tokens are issued for the application A. If the app-A-api uses the access token just for the user authentication, it's better to use an ID token - it can be validated without accessing the OAuth2 server. In this scenario, the app-A-api manages its user permissions by itself.

If the app-A-api needs the token to get a list of scopes (permissions) of its client, then use the access token. But in this scenario, the app-A-api (and app-B-api) are just accepting the access token - they are not the target audience (aud attribute) of the token. The application A is the audience of the tokens.

The APIs just check whether the access token contains scopes relevant for them. They trust the token issuer and it's up to the users to decide whether they trust the application A to perform actions on their behalf.

As an example, if a JavaScript application C (app-C) uses just Google Drive and Google Plus for its actions, then app-C will ask its user for an access token with scopes belonging to Google Drive and Google Plus. It will be just one token and both Google APIs will accept it.

And about the tokeninfo endpoint, it has it's own RFC called OAuth 2.0 Token Introspection, so you can check it.