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

THREESCALE-10591 token instrospection field removed #1438

Merged
merged 4 commits into from
Jan 23, 2024

Conversation

eguzki
Copy link
Member

@eguzki eguzki commented Jan 19, 2024

What

Fix https://issues.redhat.com/browse/THREESCALE-10591

From RH-SSO 7.5 doc

In previous versions, Red Hat Single Sign-On advertised two introspection endpoints: token_introspection_endpoint and introspection_endpoint. 

The latter is the one defined by [RFC-8414](https://datatracker.ietf.org/doc/html/rfc8414#section-2). The former was deprecated and is now removed.

The implementation is backward compatible with OIDC configuration services returning deprecated token_introspection_endpoint. When both token_introspection_endpoint and introspection_endpoint fields are in the response of the OIDC configuration service, the latter takes preference as it is the one defined by RFC-8414.

[BREAKING CHANGE] When the introspection URL is not found for whatever reason, the request is rejected with 403 Forbidden. Before this change, the request was allowed by the introspection policy. IMO. if the introspection policy is added to the chain, it is expected that the token is inspected. If checking the token is not done because the URL is missing, the request is rejected. There were some tests that were passing (IMO unexpectedly) because of this issue. I have fixed them as well.

  • Added unittests for the token introspection for the use_3scale_oidc_issuer_endpoint auth type (they were never implemented)
  • Added e2e tests for the token introspection for the use_3scale_oidc_issuer_endpoint auth type.

Verification Steps

curl https://keycloak.example.com/auth/realms/basic/.well-known/openid-configuration 2>/dev/null | yq e '.introspection_endpoint'
https://keycloak.example.com/auth/realms/basic/protocol/openid-connect/token/introspect

And the token_introspection_endpoint is gone

curl https://keycloak.example.com/auth/realms/basic/.well-known/openid-configuration 2>/dev/null | yq e '.token_introspection_endpoint'
null
  • Configure a single Product A with an OpenID Provider + realm basic and deployment type as APIcast self-managed
  • Create 3scale application App01 for product A. That will generate Client ID and Client Secret.
  • Create mapping rule for Product A GET /foo
  • Configure a Token Introspection policy with auth_type set to use_3scale_oidc_issuer_endpoint
{
  "name": "apicast.policy.token_introspection",
  "configuration": {
      "auth_type": "use_3scale_oidc_issuer_endpoint"
  }
},  
  • Start dev environment
make development
make dependencies
  • Run apicast locally
THREESCALE_DEPLOYMENT_ENV=staging APICAST_LOG_LEVEL=debug APICAST_WORKER=1 APICAST_CONFIGURATION_LOADER=lazy APICAST_CONFIGURATION_CACHE=0 THREESCALE_PORTAL_ENDPOINT=https://token@3scale-admin.example.com ./bin/apicast
  • Generate token from a realm basic using client credentials from the application App01
curl -v -k -H "Content-Type: application/x-www-form-urlencoded" \
        -d 'grant_type=password' \
        -d 'client_id=${CLIENT_ID_FROM_3SCALE_APPLICATION}' \
        -d 'client_secret=${CLIENT_SECRET_FROM_3SCALE_APPLICATION}' \
        -d 'username=${USER_CREATED_IN_KEYCLOAK}' \
        -d 'password=***' "https://keycloak.example.com/auth/realms/basic/protocol/openid-connect/token"

# capture access token
ACCESS_TOKEN=eyJhb...
  • Run query with the valid jwt
# capture apicast IP
APICAST_IP=$(docker inspect apicast_build_0-development-1 | yq e -P '.[0].NetworkSettings.Networks.apicast_build_0_default.IPAddress' -)

curl -i -k -H "Host: example.com:443" -H "Accept: application/json" -H "Authorization: Bearer ${ACCESS_TOKEN}" "http://${APICAST_IP}:8080/foo"

The response should be HTTP/1.1 200 OK

HTTP/1.1 200 OK
Server: openresty
Date: Fri, 19 Jan 2024 23:36:32 GMT
Content-Type: application/json
Content-Length: 2008
Connection: keep-alive
x-3scale-echo-api: echo-api/1.0.3
vary: Origin
x-content-type-options: nosniff
x-envoy-upstream-service-time: 0
  • Revoke token.

Go to Red Hat Single Sign-On admin application, and revoke the session (token) from the user menu. It's Log out in RH SSO site. Try to be fast so the token does not expire.

Run the same request, it should get 403 Forbidden.

curl -v -k -H "Host: example.com:443" -H "Accept: application/json" -H "Authorization: Bearer ${ACCESS_TOKEN}" "http://${APICAST_IP}:8080/foo"
HTTP/1.1 403 Forbidden
Server: openresty
Date: Fri, 19 Jan 2024 23:35:10 GMT
Content-Type: text/plain; charset=us-ascii
Transfer-Encoding: chunked
Connection: keep-alive

Authentication failed

APIcast logs should show something like "token introspection for access token ***** : token not active

If the token has expired, the request is rejected at the rewrite phase, while the token introspection policy is executed at the access phase (which is after the rewrite phase).

@eguzki eguzki requested review from a team and removed request for a team January 19, 2024 15:27
@eguzki eguzki marked this pull request as ready for review January 19, 2024 23:42
@eguzki eguzki requested a review from a team as a code owner January 19, 2024 23:42
@eguzki eguzki requested a review from tkan145 January 19, 2024 23:43
return ngx.exit(ngx.status)
if introspect_token(self, access_token).active == true then
-- access granted
return
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also output an error when self.introspection_url is nil? So in case self.introspection url is nil then at least we know what happened just by checking the log instead of guessing why the APIcast returned 403 (context.service.error auth_failed)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 👍

Log level in WARN, as I consider this as an edge case. When the introspection policy is added, the endpoint should be available

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, adding the log line here might be misleading, if self.introspection_url is valid but introspect_token(self, access_token).active == false then it will first log the token introspection for the token.. line then output token instropection cannot be performed..... Perhaps wrap it in the else statement?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch!

Fixed

@eguzki eguzki requested a review from tkan145 January 22, 2024 09:41
@eguzki eguzki force-pushed the THREESCALE-10591-token-introspection-deprecated-api branch from 1a0be6a to ed8ba2a Compare January 22, 2024 13:07
@tkan145
Copy link
Contributor

tkan145 commented Jan 22, 2024

LGTM!

@eguzki eguzki merged commit dd4c3c6 into master Jan 23, 2024
11 checks passed
@eguzki eguzki deleted the THREESCALE-10591-token-introspection-deprecated-api branch January 23, 2024 11:48
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

Successfully merging this pull request may close these issues.

2 participants