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

jwk: anonymous request can't read public keys #253

Closed
janekolszak opened this issue Sep 18, 2016 · 9 comments
Closed

jwk: anonymous request can't read public keys #253

janekolszak opened this issue Sep 18, 2016 · 9 comments
Assignees
Labels
bug Something is not working.
Milestone

Comments

@janekolszak
Copy link

Hi,
I can't get a public key for varifying id_tokens with a freshly created Client.

Key endpoint

https://hydra/keys/hydra.openid.connect/public

Policy

{
    "description": "Allow everyone including anonymous users to read JSON Web Keys having Key ID *public*.",
    "subjects": ["<.*>"],
    "effect": "allow",
    "resources": [
      "rn:hydra:keys:<[^:]+>:public"
    ],
    "actions": [
      "get"
    ]
}

Client's configuration:

{
  "id": "wta-site",
  "owner": "[email protected]",
  "scope": "hydra.keys.get openid all",
  "client_name": "Example",
  "redirect_uris": [
    "https://localhost/overview"
  ],
  "grant_types": [
    "implicit"
  ],
  "response_types": [
    "code",
    "token",
    "id_token"
  ],
  "policy_uri": "https://localhost/policy",
  "tos_uri": "https://localhost/terms",
  "client_uri": "https://localhost",
  "logo_uri": "https://localhost/logo.png",
  "contacts": [
    "[email protected]"
  ]
}

Client requests

  • id_token token
  • same scopes: hydra.keys.get openid all

Hydra's logs:

time="2016-09-18T15:34:16Z" level=info msg="started handling request" method=GET remote=172.23.0.1 request="/oauth2/auth?client_id=wta-site&redirect_uri=https%3A%2F%2Flocalhost%2Foverview&response_type=id_token%20token&scope=hydra.keys.get%20openid%20all&state=6b16e413dda24b3bafd925d9f9a7746b&nonce=16a81b371ef7429b8e45d821a888895d&consent=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ3dGEtc2l0ZSIsImV4cCI6MTQ3NDIxMzA5NiwiaWF0IjoxNDc0MjEyODU2LCJzY3AiOlsiaHlkcmEua2V5cy5nZXQiLCJvcGVuaWQiLCJhbGwiXSwic3ViIjoiOTZlNzUyNGItNjRmZC00NDk2LTk0ZTUtNGI5ODRkOTc4YmEzIn0.I-nDdBvah0vpcAHRerAMF1Po1wKG8qHr36JHk8uWuB_ekQ56smsBk6g0DFWTypKghvWGVGj8ALRfVUHGHC_K3Njw2I7jzUHtbCkvomvMXG4EusitzIPA2CfnXxYt_u5cJ3XY2ju1hsh98Vf7BIzhqbEr6HLR00wI5r55nn1CllBJL2-YB0ej1P1roTCsT2ghvbgolYQgmD3IvnPaujGg38hAzFmulpGIo9CHkpnYbUYQKSMMlkwqKhkuDSF0c61qeWIHUNAoRcyNeMyRhgbtHWZmXZsbnkiTt1dBAN-wLczB3k_6IjbIBZHcw_-ERByKHuiKeE2dK3bR1tUnQhG7eNGWCBbZRPFM4Sz-ab8ovyAQ0716h428NvXvKtZk_6PocpsIsYp0-yhzSOUnJn5vlbPrq9xNGexBHc95YiSofZ8YJwghpriaM9Hy5esGbvfaM296glvEQ2T_-_hL3RN5R7ZHjefkE-nFnSxwJNTVnb99Vt4FpyZTH3lqXd20DEptj5crwV3J6I4h6cuKt-eexefId6Ci0QKRVMoLKp6NDwHFL43jPl6ycRT-cViYoNRJjG1NHt_58Iws-Ksda_1UpujCWw45_ElgnxWdUJePTDROtnTPTY8VJeXdT-8m6jVmakWTXopr0uLlL5xMT8QxWe8PejohqU-tnZrTamc6yhE" 
time="2016-09-18T15:34:17Z" level=info msg="completed handling request" measure#web.latency=307574696 method=GET remote=172.23.0.1 request="/oauth2/auth?client_id=wta-site&redirect_uri=https%3A%2F%2Flocalhost%2Foverview&response_type=id_token%20token&scope=hydra.keys.get%20openid%20all&state=6b16e413dda24b3bafd925d9f9a7746b&nonce=16a81b371ef7429b8e45d821a888895d&consent=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ3dGEtc2l0ZSIsImV4cCI6MTQ3NDIxMzA5NiwiaWF0IjoxNDc0MjEyODU2LCJzY3AiOlsiaHlkcmEua2V5cy5nZXQiLCJvcGVuaWQiLCJhbGwiXSwic3ViIjoiOTZlNzUyNGItNjRmZC00NDk2LTk0ZTUtNGI5ODRkOTc4YmEzIn0.I-nDdBvah0vpcAHRerAMF1Po1wKG8qHr36JHk8uWuB_ekQ56smsBk6g0DFWTypKghvWGVGj8ALRfVUHGHC_K3Njw2I7jzUHtbCkvomvMXG4EusitzIPA2CfnXxYt_u5cJ3XY2ju1hsh98Vf7BIzhqbEr6HLR00wI5r55nn1CllBJL2-YB0ej1P1roTCsT2ghvbgolYQgmD3IvnPaujGg38hAzFmulpGIo9CHkpnYbUYQKSMMlkwqKhkuDSF0c61qeWIHUNAoRcyNeMyRhgbtHWZmXZsbnkiTt1dBAN-wLczB3k_6IjbIBZHcw_-ERByKHuiKeE2dK3bR1tUnQhG7eNGWCBbZRPFM4Sz-ab8ovyAQ0716h428NvXvKtZk_6PocpsIsYp0-yhzSOUnJn5vlbPrq9xNGexBHc95YiSofZ8YJwghpriaM9Hy5esGbvfaM296glvEQ2T_-_hL3RN5R7ZHjefkE-nFnSxwJNTVnb99Vt4FpyZTH3lqXd20DEptj5crwV3J6I4h6cuKt-eexefId6Ci0QKRVMoLKp6NDwHFL43jPl6ycRT-cViYoNRJjG1NHt_58Iws-Ksda_1UpujCWw45_ElgnxWdUJePTDROtnTPTY8VJeXdT-8m6jVmakWTXopr0uLlL5xMT8QxWe8PejohqU-tnZrTamc6yhE" status=302 text_status=Found took=307.574696ms 
time="2016-09-18T15:34:17Z" level=info msg="started handling request" method=GET remote=172.23.0.1 request="/keys/hydra.openid.connect/public" 
time="2016-09-18T15:34:17Z" level=info msg="Access denied" error="An error occurred: The request could not be authorized" reason="token could not be validated" request=&{rn:hydra:keys:hydra.openid.connect:public get  map[]} subject= 
time="2016-09-18T15:34:17Z" level=info msg="Got error." error="An error occurred: The request could not be authorized" request_id=cbe32083-ed4d-4c79-ac5b-771204858cb7 stack="*errors.withStack An error occurred: The request could not be authorized\n/go/src/github.com/ory-am/hydra/herodot/error.go:44 (0x6747e2)\n\tToError: Err: errors.New(err),\n/go/src/github.com/ory-am/hydra/herodot/json.go:49 (0x674e85)\n\t(*JSON).WriteError: e := ToError(err)\n/go/src/github.com/ory-am/hydra/jwk/handler.go:206 (0x67c67d)\n\t(*Handler).GetKey: h.H.WriteError(ctx, w, r, err)\n/go/src/github.com/ory-am/hydra/jwk/handler.go:44 (0x68279c)\n\t(*Handler).GetKey-fm: r.GET(\"/keys/:set/:key\", h.GetKey)\n/go/src/github.com/ory-am/hydra/vendor/github.com/julienschmidt/httprouter/router.go:299 (0x5ea793)\n\t(*Router).ServeHTTP: handle(w, req, ps)\n/go/src/github.com/ory-am/hydra/vendor/github.com/urfave/negroni/negroni.go:41 (0x699a60)\n\tWrap.func1: handler.ServeHTTP(rw, r)\n/go/src/github.com/ory-am/hydra/vendor/github.com/urfave/negroni/negroni.go:24 (0x698484)\n\tHandlerFunc.ServeHTTP: h(rw, r, next)\n/go/src/github.com/ory-am/hydra/vendor/github.com/urfave/negroni/negroni.go:33 (0x69853a)\n\tmiddleware.ServeHTTP: m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)\n/go/src/github.com/ory-am/hydra/vendor/github.com/urfave/negroni/negroni.go:33 (0x699a03)\n\t(middleware).ServeHTTP-fm: m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)\n/usr/local/go/src/net/http/server.go:1618 (0x5b16ea)\n\tHandlerFunc.ServeHTTP: f(w, r)\n/go/src/github.com/ory-am/hydra/cmd/server/handler.go:118 (0x5017e5)\n\t(*Handler).rejectInsecureRequests: next.ServeHTTP(rw, r)\n/go/src/github.com/ory-am/hydra/cmd/server/handler.go:41 (0x509a98)\n\trejectInsecureRequests)-fm: n.UseFunc(serverHandler.rejectInsecureRequests)\n/go/src/github.com/ory-am/hydra/vendor/github.com/urfave/negroni/negroni.go:24 (0x698484)\n\tHandlerFunc.ServeHTTP: h(rw, r, next)\n/go/src/github.com/ory-am/hydra/vendor/github.com/urfave/negroni/negroni.go:33 (0x69853a)\n\tmiddleware.ServeHTTP: m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)\n/go/src/github.com/ory-am/hydra/vendor/github.com/urfave/negroni/negroni.go:33 (0x699a03)\n\t(middleware).ServeHTTP-fm: m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)\n/go/src/github.com/ory-am/hydra/vendor/github.com/meatballhat/negroni-logrus/middleware.go:135 (0x666d9d)\n\t(*Middleware).ServeHTTP: next(rw, r)\n/go/src/github.com/ory-am/hydra/vendor/github.com/urfave/negroni/negroni.go:33 (0x69853a)\n\tmiddleware.ServeHTTP: m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)\n/go/src/github.com/ory-am/hydra/vendor/github.com/urfave/negroni/negroni.go:73 (0x698842)\n\t(*Negroni).ServeHTTP: n.middleware.ServeHTTP(NewResponseWriter(rw), r)\n/usr/local/go/src/net/http/server.go:2081 (0x5b397e)\n\tserverHandler.ServeHTTP: handler.ServeHTTP(rw, req)\n/usr/local/go/src/net/http/server.go:1472 (0x5b044e)\n\t(*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)\n/usr/local/go/src/runtime/asm_amd64.s:1998 (0x45f7f1)\n\tgoexit: BYTE\t$0x90\t// NOP\n" status=0 
time="2016-09-18T15:34:17Z" level=info msg="completed handling request" measure#web.latency=2518920 method=GET remote=172.23.0.1 request="/keys/hydra.openid.connect/public" status=500 text_status="Internal Server Error" took=2.51892ms 
time="2016-09-18T15:34:17Z" level=info msg="started handling request" method=GET remote=172.23.0.1 request="/oauth2/auth/?client_id=wta-site&redirect_uri=https%3A%2F%2Flocalhost%2Foverview&response_type=id_token%20token&scope=hydra.keys.get%20openid%20all&state=0efd30468a4941ed80266090d9303090&nonce=3c993f81846a47cdabd157dd2d2bf182" 
time="2016-09-18T15:34:17Z" level=info msg="completed handling request" measure#web.latency=87488 method=GET remote=172.23.0.1 request="/oauth2/auth/?client_id=wta-site&redirect_uri=https%3A%2F%2Flocalhost%2Foverview&response_type=id_token%20token&scope=hydra.keys.get%20openid%20all&state=0efd30468a4941ed80266090d9303090&nonce=3c993f81846a47cdabd157dd2d2bf182" status=301 text_status="Moved Permanently" took=87.488µs 
time="2016-09-18T15:34:17Z" level=info msg="started handling request" method=GET remote=172.23.0.1 request="/oauth2/auth?client_id=wta-site&redirect_uri=https%3A%2F%2Flocalhost%2Foverview&response_type=id_token%20token&scope=hydra.keys.get%20openid%20all&state=0efd30468a4941ed80266090d9303090&nonce=3c993f81846a47cdabd157dd2d2bf182" 
time="2016-09-18T15:34:17Z" level=info msg="completed handling request" measure#web.latency=79482700 method=GET remote=172.23.0.1 request="/oauth2/auth?client_id=wta-site&redirect_uri=https%3A%2F%2Flocalhost%2Foverview&response_type=id_token%20token&scope=hydra.keys.get%20openid%20all&state=0efd30468a4941ed80266090d9303090&nonce=3c993f81846a47cdabd157dd2d2bf182" status=302 text_status=Found took=79.4827ms 
time="2016-09-18T15:34:17Z" level=info msg="started handling request" method=GET remote="172.23.0.6:44746" request="/clients/wta-site" 
time="2016-09-18T15:34:17Z" level=info msg="Access granted" audience=9c8e47a1-fafd-4c1e-9e98-cc640cbe19cb subject=9c8e47a1-fafd-4c1e-9e98-cc640cbe19cb 
time="2016-09-18T15:34:17Z" level=info msg="completed handling request" measure#web.latency=628454 method=GET remote="172.23.0.6:44746" request="/clients/wta-site" status=200 text_status=OK took=628.454µs

I think the problem is here:

msg="Access denied" error="An error occurred: The request could not be authorized" reason="token could not be validated" request=&{rn:hydra:keys:hydra.openid.connect:public get  map[]} subject=```
@janekolszak janekolszak changed the title Can Can't read keys/hydra.openid.connect/public Sep 18, 2016
@aeneasr
Copy link
Member

aeneasr commented Sep 18, 2016

Which version are you running? How did you get the token - did you use hydra token client or some other way?

@janekolszak
Copy link
Author

Used the oidc-client-js library (that I used before) https://github.com/IdentityModel/oidc-client-js

$ hydra token client --skip-tls-verify
Warning: Skipping TLS Certificate Verification.
VCudVUydX2SlSPYXzIZGlmSNumTeWvVFBOmbIgMFmys.gbDLk1SF_hz0Iaj3eEmJGnjyswKEnqSyynAmOJpmr_c

@mfzl
Copy link
Contributor

mfzl commented Sep 18, 2016

Are you using a different client to request for token here (different from the one above)?
$ hydra token client --skip-tls-verify

Because the above requires grant_type client_credentials and hydra in scope. no?

Maybe I'm missing something, I'm trying If I can reproduce.

@aeneasr
Copy link
Member

aeneasr commented Sep 18, 2016

@faxal thanks for investigating :)

@janekolszak are you by any chance using a token that was issued on behalf of a user instead of on behalf of the client?

I tried reproducing your issue with the client_credentials grant but was not able to:

# create policy
$ hydra policies create -f docs/access-control/policies/everyone-can-read-public-keys.json

# create client
$ hydra clients create -c=[http://localhost/cb] -g [client_credentials] -a [hydra] -r [code,token]

# get access token
$ curl -X POST -H "Authorization: Basic ZTllYWMzNjAtYjA5Zi00NmY4LWIwNDktODlkMjZhZWNkYWFmOlNqbj1DMXktc19RVEcscHoxPlctckM5ZElv" -H "Cache-Control: no-cache" -H "Postman-Token: d472a862-943c-3596-fc13-f71ee34d37f1" -H "Content-Type: application/x-www-form-urlencoded" -d 'grant_type=client_credentials&scope=hydra.keys' "http://localhost:4444/oauth2/token"

{
  "access_token": "9wHkwSg_jThB1sPnt8tX-9tukrXwJymTU9UZCUThB5M.DMVw60sQ8gbh6x29079_fO987_ktHqQT8R4uSD_CGng",
  "expires_in": "3600",
  "scope": "hydra.keys",
  "token_type": "bearer"
}

# request key
$ curl -X GET -H "Authorization: bearer 9wHkwSg_jThB1sPnt8tX-9tukrXwJymTU9UZCUThB5M.DMVw60sQ8gbh6x29079_fO987_ktHqQT8R4uSD_CGng" -H "Cache-Control: no-cache" -H "Postman-Token: e2851819-8240-6ce3-5017-6fc573fc1943" "http://localhost:4444/keys/hydra.openid.connect/public"

{"keys":[{"kty":"RSA","kid":"public","n":"7wV6myGPv4XL3v7X3FVwWzQvjnFMOh7t0_Ua-d6AtOA6NcY1b2OnYqpDiYUCp5I3vtq5G9YZPLK7XcuNLTtO2TCf_ycmu0AIX3NMkKSIUpmR5tJEGdRPzG6umMZ5DWNBeERsHGJzNCJyzAyStQ_kI-DfCZEn3iHuL9jsZCb5pYptqESpkvpqzLFfa3R5EXdGrzxrKrALIHCSyTocGoFWQ7ogjcOjdlq0f69cvTrIH5Dia7aRmfmYGXZ6BzXehKPCjGYuexKTUQAmvJov9UWb8jWS8rLf1by-aibwCxsx6aZwYz7_dI7XQSkQ6fzOrqB-9ktcISztc9Act7AUwovg2zZaMJlTojcz1IIBxhSCQ4ZY6quY7skgwTfGpYivhWWnwb0mTjxbph0Ck_za-R6H53U7AGj60H1AgpZRG6bQu06oGY7cTfjKxTGd8_beaFCAVuQaf09_808mkvfSsnPU5EcfNrBjTukiQUxgdyyRljPvSRgJ8JJfZ0_D712JJ-9aXKAVwyLxqhnOWE008tTSNOiyIblgjrSp0Wcjh90eGO2EKpzvJfF7te6FvoBK1cEtl7SiF6oeh9KQvmFJVug4KDRYeGjWFN-iHJHCPgYue3LE1S72q6-zZ4kATSZZceC-SXocpORVgyT1hljEEvc0YoQc4lsjjwSLDeyIQZPj2VU","e":"AQAB"}]}

where policy.json is:

{
  "description": "Allow everyone including anonymous users to read JSON Web Keys having Key ID *public*.",
  "subjects": [
    "<.*>"
  ],
  "effect": "allow",
  "resources": [
    "rn:hydra:keys:<[^:]+>:public"
  ],
  "actions": [
    "get"
  ]
}

@janekolszak
Copy link
Author

@faxal No, clients are different.

Getting keys from hydra has to work with client credentials, the idp library uses it.

@aeneasr
Copy link
Member

aeneasr commented Sep 19, 2016

I believe that the issue is that the idp library is accessing the endpoint without passing along an access token, which is iirc the way the JWKS URI is working in OpenID Connect. So the issue here is that, even though you allowed all subjects to access the endpoint, it still requires a valid access token. As that token isn't passed, the keys endpoint rejects the request.

To resolve this, we need to add a way to let anonymous requests pass through, when all subjects are allowed.

@aeneasr aeneasr added bug Something is not working. documentation labels Sep 19, 2016
@aeneasr aeneasr changed the title Can't read keys/hydra.openid.connect/public jwk: anonymous request can't read public keys Sep 19, 2016
@aeneasr aeneasr added this to the 0.5.0 milestone Sep 19, 2016
@aeneasr aeneasr self-assigned this Sep 19, 2016
@aeneasr
Copy link
Member

aeneasr commented Sep 19, 2016

I will address this in #243

@janekolszak
Copy link
Author

Confirmed. Temporary solution is to serve the unprotected key from RP, e.g.:

    jwk, err := model.HydraClient.JWK.GetKey("hydra.openid.connect", "public")
    if err != nil {
        // ...
    }

    c.JSON(http.StatusOK, jwk)

@aeneasr
Copy link
Member

aeneasr commented Sep 21, 2016

You can now allow keys to be publicy available with this policy:

{
  "description": "Allow everyone including anonymous users to read JSON Web Keys having Key ID *public*.",
  "subjects": [
    "<^$>"
  ],
  "effect": "allow",
  "resources": [
    "rn:hydra:keys:<[^:]+>:public"
  ],
  "actions": [
    "get"
  ]
}

alternatively, you can also achieve this by setting "subjects": ["<.*>"] or "subjects": [""]

@aeneasr aeneasr closed this as completed Sep 21, 2016
aeneasr pushed a commit that referenced this issue Sep 22, 2016
* cmd: hydra token user should show id token in browser - closes #224
* cli: hydra clients import doesn't print client's secret - closes #221
* travis: ld flags are wrong - closes #242
* all: resolve naming inconsistencies in jwk set names used in hydra - closes #239
* sdk: resolve naming inconsistencies - closes #226
* docs: resolve gitbook issue with image assets
* jwk: anonymous request can't read public keys - closes #253
* client: add ability to update client - closes #250
* core: document hard-wired JWK sets - closes #247
* docs: fix images in readme - closes #261
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is not working.
Projects
None yet
Development

No branches or pull requests

3 participants