3scale / APIcast

3scale API Gateway
Apache License 2.0
305 stars 170 forks source link

Token introspection policy is not working for RHSSO 7.2 #848

Closed pestanko closed 6 years ago

pestanko commented 6 years ago

Token introspection policy is not working for token introspection policy with RHSSO 7.2.

Manual request to RHSSO testing endpoint works correctly.

Version

The current build of the apicast.

Steps To Reproduce
  1. Configure the Introspection policy
  2. Create RHSSO realm, client.
  3. Enable Introspection policy and try to create request
Current Result

RHSSO LOG:

13:08:23,964 WARN  [org.keycloak.events] (default task-44) type=INTROSPECT_TOKEN_ERROR, realmId=20104744-6026-492e-a193-34c1571feaae, clientId=introspection-client-f-dklc5q, userId=null, ipAddress=<IP>, error=invalid_request, detail='Token not provided.', client_auth_method=client-secret
Additional Information

As Authorization header we have used the: base64(<rhsso_client_id>:<rhsso_client_secret>)

Manual CURL request to introspect token:

curl -X POST \
  http://unsecure-sso-testing-sso.apps.<RHSSO>.com/auth/realms/introspection-realm-2dinmqr2/protocol/openid-connect/token/introspect \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'token=<ACCESS_TOKEN>&client_id=introspection-client-bccn-gi0&client_secret=4e235d87-0c81-44ec-994d-0dfb3fcc7d19'
davidor commented 6 years ago

@tmogi001 , @y-tabata Can you tell us the RHSSO version that you are using? Thanks.

y-tabata commented 6 years ago

@davidor we use version 7.2. And we confirmed again that the current token introspection policy was working in our environment. We checked both the "use_3scale_oidc_issuer_endpoint" and the "client_id+client_secret"

pestanko commented 6 years ago

@y-tabata Ok, so I have a question - how are you sending the access_token to the apicast?

Are you sending it in authorization header? or as a param? access_token?

Because when I send the request like:

https://apicast.example.com/get?access_token=<access_token>

RHSSO will get me an error:

07:14:46,986 WARN  [org.keycloak.events] (default task-55) type=INTROSPECT_TOKEN_ERROR, realmId=8145444a-ffed-4b20-a183-66a8ee3a5d8e, clientId=introspection-client-xojepd7, userId=null, ipAddress=10.8.47.51, error=invalid_request, detail='Token not provided.', client_auth_method=client-secret
y-tabata commented 6 years ago

@pestanko

Are you sending it in authorization header? or as a param? access_token?

I sent it in authorization header like "Authorization: Bearer ".

davidor commented 6 years ago

@pestanko has been debugging this. The problem is that while the APIcast policy looks for credentials in the query and headers (https://github.com/3scale/apicast/blob/34ed827454d83f02aec610ca47b33997eb1a0ddd/gateway/src/apicast/configuration/service.lua#L75), the token introspection only checks the Authorization header (https://github.com/3scale/apicast/blob/34ed827454d83f02aec610ca47b33997eb1a0ddd/gateway/src/apicast/policy/token_introspection/token_introspection.lua#L101).

This is not really consistent. Possible fix: the policy should check first if the credentials have already been stored in the context, and if not, then check the Authorization header.

mikz commented 6 years ago

When using OIDC/OAuth2.0 the access token can be transmitted only as the Authorization Bearer.

And token introspection policy makes sense for OIDC/OAuth2.0. So the only allowed way how to transfer the access token is Authorization: Bearer ....

davidor commented 6 years ago

OK. If the standard says it needs to be in the Authorization header, then there's nothing else to do.

mikz commented 6 years ago

https://tools.ietf.org/html/rfc6750#section-2 Bearer is the only required method, the other two are discouraged.

pestanko commented 6 years ago

@mikz Would it make sense to use only Authorization header for OpenID connect? It means for all the use cases?

It means deprecate the usage of the access_token query parameter

mikz commented 6 years ago

@pestanko Yes. When using OAuth2.0/OIDC only Authorization header makes sense.

If for some reason passing access_token in the request path works it is discouraged per spec, but we should not break current behaviour. For the token introspection policy it makes sense to support only the authorization header.