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:
- 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?
- 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.