Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

required_scope of authenticator validate only scope claim and not scp claim #138

Closed
einret opened this issue Nov 28, 2018 · 7 comments
Closed

Comments

@einret
Copy link

einret commented Nov 28, 2018

Describe the bug
When oathkeeper authenticator handler is set to "jwt", the "required_scope" parameter check the "scope" claim. However, when hydra server is configured to generate jwt as access token, it set the different scopes inside the "scp" claim.

Then all request through oathkeeper are denied

To Reproduce

Run the https://github.com/ory/examples full-stack example and configure :

  • Hydra to generate jwt as access token, modify the full-stack/docker-compose.yml file and add in hydra/environnement the line OAUTH2_ACCESS_TOKEN_STRATEGY=jwt
  • Oathkeeper to be able to validate the signature by pointing the public key used to sign jwt by adding the line AUTHENTICATOR_JWT_JWKS_URL= http://hydra:4444/.well-known/jwks.json in the oathkeeper-api/environnement and oathkeeper-proxy/environnement
  • Modify the rules of oathkeeper by changing the file full-stack/config/oathkeeper/rules/resource-server.json and replacing the line "handler": "oauth2_introspection" by "handler": "jwt"

Expected behavior
The configuration of "required_scope" should parse the "scp" claim and not "scope" claim http://self-issued.info/docs/draft-ietf-oauth-token-exchange-03.html#scopes

it seems that the claim "scope" is parsed in https://github.com/ory/oathkeeper/blob/master/proxy/authenticator_jwt.go line 131

Screenshots
Request with a valid Access Token
You already performed an OAuth 2.0 Token. Therefore, this consumer application has an access token (it's eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzoxMWY5Y2M5YS0zZGM5LTQ3OTEtOTkwNS1iYTI2MDVhN2FlZDkiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOltdLCJjbGllbnRfaWQiOiJjb25zdW1lci1hcHAiLCJleHAiOjE1NDMzNzMwMzUsImlhdCI6MTU0MzM2OTQzNSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo0NDQ0LyIsImp0aSI6ImU0YTAwN2IyLWRlYzQtNDNiYS1iNjk3LWRhZDEwZTNlZmFmNyIsIm5iZiI6MTU0MzM2OTQzNSwic2NwIjpbIm9mZmxpbmUiLCJvcGVuaWQiLCJhcnRpY2xlcy5yZWFkIl0sInN1YiI6ImZvb0BiYXIuY29tIn0.Eygkne9ByXEOvHoKwsL3_6Tnz0NoZS4eU1sKIEQXEDS2bWx5nV-JNGCpBZe8YcUQicd_W2YWNKDt-SY7E1ZuJIc7jU-jPrBoR_8OW-h3IoEhkRET3CvcI912RYuNzonMCty5z-mxmRiY-XPFhh4b36UUEK6DtIkVgRKOIrGTMEaRCvIY2qrNjFWlZ7B6vSasLhlJ0rRc4oyxCpz1dnQcGGvNe9GiuRGrwRRwpsiST7oxLSkWtP0ZOlLxkMdMLyAIQ7VaVz86p1y1LLgTEt27nYC5Fzi0iQNQhDCfrLzYvFF5QZm5aMydRMr5Igkyd0qx7FD4F6xJw4xspciI8eS2aoz2ZXWCUPGLYaDUepvVKfnM4XjP3sZQkY-7scsrVjqCv-0hAeGFNWjGHm6YADOU8_RzFd8NtMWT6tmCkcEJk4MCRjfB8cKXjzFJJbCWT6N6TNoLxGsjwjVAmAdDAiUBFiWtdKoN0TfUXjDuXm3JDM6qg5r8-gDIet6ooZWRcE2bpOlzGQWca6FBzG-s_GxFPFe24G_CeM3Ac6gmcTGUjiChYyML1KHRRQlx-B0SthrMaBu53bCYzveuTirehBWj3PG59TpASbNBWaayP9132LG0r8On5tnwpJJLh4rTwz0INO34u2V3iJBjqpW4xgT6BPAvhKRz52u3S2n-pBe1bTg). We're making a request to the backend and are including the token in the HTTP request header:
{
"alg": "RS256",
"kid": "public:11f9cc9a-3dc9-4791-9905-ba2605a7aed9",
"typ": "JWT"
}
{
"aud": [],
"client_id": "consumer-app",
"exp": 1543373035,
"iat": 1543369435,
"iss": "http://localhost:4444/",
"jti": "e4a007b2-dec4-43ba-b697-dad10e3efaf7",
"nbf": 1543369435,
"scp": [
"offline",
"openid",
"articles.read"
],
"sub": "foo@bar.com"
}

HTTP Response Body
{"error":{"code":403,"status":"Forbidden","reason":"Token is missing required scope articles.read.","message":"Access credentials are not sufficient to access this resource"}}

When you changed the consent app to add the claim "scope" we get :

You already performed an OAuth 2.0 Token. Therefore, this consumer application has an access token (it's eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzoyNDFhOGFmZi04OGQ1LTQ4NTctYWI5OS01MDFiZGVhMzkyMzUiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOltdLCJjbGllbnRfaWQiOiJjb25zdW1lci1hcHAiLCJleHAiOjE1NDMzNzk2MTgsImlhdCI6MTU0MzM3NjAxOCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo0NDQ0LyIsImp0aSI6IjQ1MGFlOTI1LWUyN2YtNDVhYy1hNTVkLWE5YmJlOGY2MmViZiIsIm5iZiI6MTU0MzM3NjAxOCwic2NvcGUiOlsib3BlbmlkIiwiYXJ0aWNsZXMucmVhZCJdLCJzY3AiOlsib3BlbmlkIiwiYXJ0aWNsZXMucmVhZCJdLCJzdWIiOiJmb29AYmFyLmNvbSJ9.CPowFDgN2RhD9IWxu4OCGFnqnRT3Z7Q7tNiIA0m4cq10bU6JyMbo804UADwzroe4ssGKk_Ptjy1EfObIo0ne4IOMwPsHM_9rmLNYD93XYWTKPa3DqTW5_OiUtCQWpt9U5Dstnjf-eKOOeB9dEYjyulFydRPlqagY9jw4SJmmoyfSyJ-wqiYQSIWgHIGuNRMr_6ul7aplhpEUKzFivVVEVvKOtTCUsSsaC7fdMcqJekhrVE0GnWZoyK-d-DwZGBr8NeKV6KDu3l7Vemt1Wtd0vf_LcNL9AFbBK4CevGFi1cAxDsSPvuAAoIGhAxTKSCkbP53lh87gf-maLO6EVrFOy721uZvHnJJddvWqvb5ge-IYRrAUTL56-xPresEPAYpTSOs2cxxz-JdEXMoUlm8CDt8pAejDvXrl69VpfmHmAf7VOe80En0J7bEq-MvGO0KrRYSvdjOnp-wVIPNOYH9PlInLfuM7qnZ5_J727pWqfm8CQwHR0aUXgvB4x90En8dSvYU-_a1Sqg6wWxv7L11CIkT65nY1Lw-NBLvkCSqAZO9KOQyiwL3lfyMUn7qsJsDkBm_lP75c31tCRh2xecddLtP2K30IUKqp6zBcGud0AYODj86OUBEy5D_N6SQo7S0ZRZoQABm6IZxQeWqmUF8bejbbsRJv3ikwsto2cYKANw4). We're making a request to the backend and are including the token in the HTTP request header:
{
"alg": "RS256",
"kid": "public:66c5e53a-4c79-4b32-b625-a2ed940e9d7c",
"typ": "JWT"
}
{
"aud": [],
"client_id": "consumer-app",
"exp": 1543379463,
"iat": 1543375863,
"iss": "http://localhost:4444/",
"jti": "2cf61755-75c0-49a5-91da-7db8561f16cd",
"nbf": 1543375863,
"scope": [
"articles.read"
],

"scp": [
"articles.read"
],
"sub": "foo@bar.com"
}

HTTP Response Body
{
"message": "Congratulations, you gained access to this endpoint!",
"tokenClaims": {
"client_id": "consumer-app",
"exp": 1543379619,
"iat": 1543376019,
"iss": "http://oathkeeper-api:4456",
"jti": "580c44ae-5bf8-4027-b87d-cb436941ace7",
"nbf": 1543376019,
"scope": "openid articles.read",
"sub": "foo@bar.com",
"username": ""
}
}

Version:
docker version
Client:
Version: 18.09.0
API version: 1.39
Go version: go1.10.4
Git commit: 4d60db4
Built: Wed Nov 7 00:49:01 2018
OS/Arch: linux/amd64
Experimental: false

Server: Docker Engine - Community
Engine:
Version: 18.09.0
API version: 1.39 (minimum version 1.12)
Go version: go1.10.4
Git commit: 4d60db4
Built: Wed Nov 7 00:16:44 2018
OS/Arch: linux/amd64
Experimental: false

Thank you in advance for your return

@aeneasr
Copy link
Member

aeneasr commented Nov 29, 2018

Yeah, the scope field should be configurable in oathkeeper. This is the second time this came up!

@ProMPT120
Copy link

ProMPT120 commented Feb 25, 2019

Was going to prepare a PR about this (and already modified line 132 for internal use). According to the RFC and in practice multiple IdP such as Okta, Microsoft and even hydra use the scp field to specify the oauth2 scope to be validated. Do we need to pass the scope field as an environment variable, in order not to break the current use with "scope" ? It is a pretty big deal to differ from the RFC as mentionned http://self-issued.info/docs/draft-ietf-oauth-token-exchange-03.html#scopes and some big jwt implementation providers (https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens, OKTA access token scp https://developer.okta.com/docs/api/resources/oidc).

@aeneasr
Copy link
Member

aeneasr commented Feb 27, 2019

Hm, I think we could probably default to scp and have a configuration setting in the route which sets the key, for example:

    "authenticators": [{
        "handler": "oauth2_client_credentials",
        "config": {
            "required_scope": ["scope-a", "scope-b"],
            "scope_keys": ["scp", "scope"]
        }
    }],

What do you think about that?

@ProMPT120
Copy link

ProMPT120 commented Feb 28, 2019

Handler : "jwt" in our usecase, but this fix clearly allows for multiple scope headers including "scp" as you mentionned earlier (if other people want to differ from ietf). Will you keep "scp" or "scope" as default one in order not to break previous oathkeeper implementations ?

@aeneasr
Copy link
Member

aeneasr commented Feb 28, 2019

Oh yeah right, I mixed that up - but I think the same configuration would work there too :) Regarding BC, that's a good question. I think it makes sense to default to something that is being used more commonly and have a BC break here. Would you be open to PR this?

@ProMPT120
Copy link

ProMPT120 commented Feb 28, 2019

Done on default values and test cases. Working on scope_keys feature.

@ngrigoriev
Copy link
Contributor

+1 - I have just hit this issue. It is a bit ironic that ORY Oathkeeper is not compatible with the tokens issued by ORY Hydra. I've been building the prototype with Hydra, Ambassador and Oathkeeper and ended up having this problem "Token is missing required scope...". Digged the code and found exactly that problem.

aeneasr added a commit that referenced this issue Apr 5, 2019
Previously, the JWT authenticator only used the "scope" claim to retrieve scope values from a JWT. Now, "scp", "scope", "scopes" are supported as string arrays and strings separated by spaces.

Closes #138

Signed-off-by: aeneasr <aeneas@ory.sh>
aeneasr added a commit that referenced this issue Apr 5, 2019
Previously, the JWT authenticator only used the "scope" claim to retrieve scope values from a JWT. Now, "scp", "scope", "scopes" are supported as string arrays and strings separated by spaces.

Closes #138

Signed-off-by: aeneasr <aeneas@ory.sh>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants