I am tying to understand this authentication-example with OAuth2.0 and am stuck at the scopes part: https://github.com/zalando/connexion/tree/master/examples/swagger2/oauth2
In app.yaml, we define 'uid' to be the necessary scope for our application:
/secret:
get:
summary: Return secret string
operationId: app.get_secret
responses:
200:
description: secret response
schema:
type: string
security:
# enable authentication and require the "uid" scope for this endpoint
- oauth2: ['uid']
In the security-definitions of app.yaml, the "uid" is again in the scopes section and is required as an answer from the x-tokenInfoUrl (which I need).
securityDefinitions:
oauth2:
type: oauth2
flow: implicit
authorizationUrl: https://example.com/oauth2/dialog
x-tokenInfoUrl: http://localhost:7979/tokeninfo
scopes:
uid: Unique identifier of the user accessing the service.
In our mock application for tokeninfo (mock_tokeninfo.yaml), we see that "uid" is returned and that the scope is actually "uid", which we wanted.
return {'uid': uid, 'scope': ['uid']}
And finally in mock_tokeninfo.yaml, we have the "uid" and the scope in the response:
responses:
200:
description: Token info object
schema:
type: object
properties:
uid:
type: string
scope:
type: array
items:
type: string
So what I understand now is that when app.py starts on port 8080 and I call localhost on port 8080 with "/secret", the security-part checks what is required and sees "uid". It follows the x-tokenInfoUrl on localhost:7979, where we started our mock_tokeninfo application and it returns to us a "uid" and the scope "uid".
Now my question is the following: I have now an own identity provider and would like to access the userinfo from there. I changed the x-tokenInfoUrl to something like this:
https://<my_idp>/<some_paths>/userinfo
and when I make curl like this: curl -H 'Authorization: Bearer <access_token>‘ https://<IDP>/<some_paths>/userinfo
, it works and I get a response that looks like this:
{"mail":"<my_email>",
"name":"<my_name>"}
Now as far as I understand, I would only need to change "uid" to e.g. "mail" and it should return my email to me, but no: I get
403 - forbidden
provided token does not have the required scope
Content-Type: application/problem+json
I don't understand why I don't have the required scope - it simply does not make sense to me. Can somebody please explain, how can I get my information out of my identity provider? I also checked and in my authorization email with my id and secret, it says that scope is <some_keyword>, but this keyword also results in 403 like everything else.
Ps: I've already passed my certificate to the identity provider, so this should not be the problem.
EDIT:
Please - help me you intelligent ppl of StackOverflow :(
I found those "MUST naming conventions for scopes": https://opensource.zalando.com/restful-api-guidelines/ But it did not help as well.
I checked, if the header is actually redirected and it was.
I found this statement: "However, to make this explicit you should assign the uid pseudo permission in this case. It is the user id and always available as OAuth2 default scope", but again - if this is a pseudo-permission, how do I do a normal scope?
In every example that I find (the pet-read/write example is the most common one), the scope-variables seem to have custom names... (https://swagger.io/docs/specification/authentication/oauth2/)
Here the documentation for the "security"-section, maybe I misunderstand something: https://connexion.readthedocs.io/en/latest/security.html
So the solution is finally found. The problem is that the documentation was not updated. This is the link to the documentation:
https://connexion.readthedocs.io/en/latest/security.html#oauth-2-authentication-and-authorization
And it says that:
The sub property of the Token Info response will be passed in the user argument to the handler function.
Further investigation resulted in finding this commit message of the connexion-package:
https://github.com/mnylen/connexion/commit/1818c34ecbdd6833a6c8cde61021ece38b59d978
Which updates the insufficient description by that phrase:
The Token Info response will be passed in the
token_info
argument to the handler function. Thesub
property of the Token Info response will be passed in theuser
argument to the handler function.
So putting the information about "No Scopes" from here:
https://swagger.io/docs/specification/authentication/oauth2/
together with the information from the commit-message, we can change our example like following:
app.yaml:
security:
# enable authentication and require the "uid" scope for this endpoint
- oauth2: []
securityDefinitions:
oauth2:
type: oauth2
x-tokenInfoUrl: https://<my_idp>/<some_paths>/userinfo
scopes: {}
And instead of using "user", we use "token_info" in our function:
app.py:
get_secret(token_info):
return token_info
This way, I got all the information that was passed by our identity-provider.
Thank you all for thinking with me :) Hope, you find this useful.