Warm tip: This article is reproduced from serverfault.com, please click

How to change "scopes" with Auth2.0 (Connexion, Swagger)

发布于 2020-11-26 08:17:33

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

Questioner
Nin4ikP
Viewed
0
Nin4ikP 2020-12-04 19:20:28

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. The sub property of the Token Info response will be passed in the user 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.