ch4mpy / spring-addons

Ease spring OAuth2 resource-servers configuration and testing
Apache License 2.0
501 stars 80 forks source link

After 7.3.0 authentication for web mvc client against keycloak ends in endless redirect #174

Closed yennor closed 6 months ago

yennor commented 6 months ago

Describe the bug I use a webmvc client authenticating against keycloak. It works perfectly up to and with version 7.2.0. From 7.3.0 on it doesn't work anymore. The client always throws a

org.springframework.security.oauth2.core.OAuth2AuthenticationException: [invalid_grant] Incorrect redirect_uri 
exception.

Keycloak shows me a

type=CODE_TO_TOKEN_ERROR,  error=invalid_code, grant_type=authorization_code,  client_auth_method=client-secret
error.

I think I had a similar error in the past once. As far as I remember the problem was using different redirect_uri for the code and the token or something like that (long time ago). I've tried to look through the changes from 7.2.0 to 7.3.0 but I don't understand them 100%. But something changed with the redirect_uri, as far as i can see.

But the whole thing ends in an endless redirect from keycloak, to localhost, back to keycloak, ...

config looks like:

issuer: https://example.com/realms/example
client-id: example
client-secret: secret
client-uri: http://localhost:8080

spring:
  security:
    oauth2:
      client:
        provider:
          keycloak:
            issuer-uri: ${issuer}
        registration:
          keycloak-user:
            authorization-grant-type: authorization_code
            client-name: My Keycloak instance
            client-id: ${client-id}
            client-secret: ${client-secret}
            provider: keycloak
            scope: openid,profile,email,offline_access

com:
  c4-soft:
    springaddons:
      oidc:
        ops:
        - iss: ${issuer}
          username-claim: $.preferred_username
          authorities:
          - path: $.realm_access.roles
          - path: $.resource_access.*.roles
        client:
          security-matchers: /**
          permit-all:
          - /login/**
          - /logout/**
          - /oauth2/**
          - /public/**
          - /webjars/**
          - /npm/**
          - /images/**
          client-uri: ${client-uri}
          post-login-redirect-path: /
          post-logout-redirect-path: /
          csrf: session
ch4mpy commented 6 months ago

This error is thrown by Keycloak.

Have you changed one of:

The last two points lead to a new authorization-code callback that could possibly not be allowed in Keycloak.

But according to the little log you join, it seems that you have an issue with the authorization-code itself.

Please attach more Keycloak logs.

Please also add your security conf (SecurityFilterChain if you defined one and any other @Bean injected into it or into spring-addons one).

What is the version of Keycloak you are using?

Can you setup a minimal reproducer? I don't have this kind of error with my OAuth2 clients authenticating users on Keycloak 23.0.1

yennor commented 6 months ago
ch4mpy commented 6 months ago

Could you please join the complete URI for the authorization-code flow (with scheme, authority and params). Something like:

yennor commented 6 months ago

here we go. I'll prepare a minimal setup and provide the link here in a moment..

GET http://localhost:8080/ => 302 http://localhost:8080/oauth2/authorization/keycloak-user

GET http://localhost:8080/oauth2/authorization/keycloak-user => 302 Location: https://auth.intranet.example.com/realms/example.com/protocol/openid-connect/auth?response_type=code&client_id=hotline-thurgau-dev&scope=openid%20profile%20email%20offline_access&state=2GoZQboLNYpOvEuyJE4WUgs8HMhM1ajJmEIZeyHMraY%3D&redirect_uri=http://localhost:8080/login/oauth2/code/keycloak-user&nonce=6dQBt6IKShPGPgBYKJHLk1j3vmBTXoV_732RCFaw5UM

GET https://auth.intranet.example.com/realms/example.com/protocol/openid-connect/auth?response_type=code&client_id=hotline-thurgau-dev&scope=openid%20profile%20email%20offline_access&state=2GoZQboLNYpOvEuyJE4WUgs8HMhM1ajJmEIZeyHMraY%3D&redirect_uri=http://localhost:8080/login/oauth2/code/keycloak-user&nonce=6dQBt6IKShPGPgBYKJHLk1j3vmBTXoV_732RCFaw5UM => 200

POST https://auth.intranet.example.com/realms/example.com/login-actions/authenticate?session_code=ezx_VSj1RRrmYqnbS6D95XZVO1NxHNxfVhL0D4Q3xeQ&execution=d89c4380-50ef-4a97-a4cc-1a76df1d11a9&client_id=hotline-thurgau-dev&tab_id=WbntdJBVkh0 => 302 http://localhost:8080/login/oauth2/code/keycloak-user?state=2GoZQboLNYpOvEuyJE4WUgs8HMhM1ajJmEIZeyHMraY%3D&session_state=393fd19d-2163-40d6-880f-c9f94b6ca567&code=138186ac-15de-49c1-9977-4f75b493086a.393fd19d-2163-40d6-880f-c9f94b6ca567.d0d36e71-da18-474d-95d6-a58a3af492fd

GET http://localhost:8080/login/oauth2/code/keycloak-user?state=2GoZQboLNYpOvEuyJE4WUgs8HMhM1ajJmEIZeyHMraY%3D&session_state=393fd19d-2163-40d6-880f-c9f94b6ca567&code=138186ac-15de-49c1-9977-4f75b493086a.393fd19d-2163-40d6-880f-c9f94b6ca567.d0d36e71-da18-474d-95d6-a58a3af492fd => 302 http://localhost:8080/

GET http://localhost:8080/ => 302 http://localhost:8080/oauth2/authorization/keycloak-user

GET http://localhost:8080/oauth2/authorization/keycloak-user => 302 https://auth.intranet.example.com/realms/example.com/protocol/openid-connect/auth?response_type=code&client_id=hotline-thurgau-dev&scope=openid%20profile%20email%20offline_access&state=fHDCCU8sji8AHZkkw8HWanZfWVVoxoJA18ImNhwcFa8%3D&redirect_uri=http://localhost:8080/login/oauth2/code/keycloak-user&nonce=8xIWLJckGPv2oEFg8ssoISG3nmexWqCks5bo0_kkLDg

GET https://auth.intranet.example.com/realms/example.com/protocol/openid-connect/auth?response_type=code&client_id=hotline-thurgau-dev&scope=openid%20profile%20email%20offline_access&state=fHDCCU8sji8AHZkkw8HWanZfWVVoxoJA18ImNhwcFa8%3D&redirect_uri=http://localhost:8080/login/oauth2/code/keycloak-user&nonce=8xIWLJckGPv2oEFg8ssoISG3nmexWqCks5bo0_kkLDg => 302 http://localhost:8080/login/oauth2/code/keycloak-user?state=fHDCCU8sji8AHZkkw8HWanZfWVVoxoJA18ImNhwcFa8%3D&session_state=393fd19d-2163-40d6-880f-c9f94b6ca567&code=ddeb1751-5710-455d-b986-cd7811ceeda9.393fd19d-2163-40d6-880f-c9f94b6ca567.d0d36e71-da18-474d-95d6-a58a3af492fd

GET http://localhost:8080/login/oauth2/code/keycloak-user?state=fHDCCU8sji8AHZkkw8HWanZfWVVoxoJA18ImNhwcFa8%3D&session_state=393fd19d-2163-40d6-880f-c9f94b6ca567&code=ddeb1751-5710-455d-b986-cd7811ceeda9.393fd19d-2163-40d6-880f-c9f94b6ca567.d0d36e71-da18-474d-95d6-a58a3af492fd => 302 http://localhost:8080/

etc...

yennor commented 6 months ago

here i've added a minimal projekt https://github.com/yennor/springaddonsmin

ch4mpy commented 6 months ago

@yennor thank you for the reproducer, it is of great help for investigations.

What I spotted so far is that inside DefaultAuthorizationCodeTokenResponseClient::getTokenResponse, when inspecting the body of the request, the value of the redirect_uri has changed from https://localhost:7080/login/oauth2/code/keycloak-user to https://localhost:7080/oauth2/authorization/keycloak-user (which is wrong as we gave https://localhost:7080/login/oauth2/code/keycloak-user to Keycloak as redirect_uri in the authorization request).

This is a regression I'll fix (haven't found why yet and have limited time today, but will do soon).

ch4mpy commented 6 months ago

@yennor I published a 7.3.2 which should fix this issue. Please confirm and close.

This issue was specific to synchronized apps (servlets).

yennor commented 6 months ago

works like a charm. thanks a lot :-)