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

Refresh Token #422

Open
evertongodoi opened this issue Aug 22, 2023 · 5 comments
Open

Refresh Token #422

evertongodoi opened this issue Aug 22, 2023 · 5 comments

Comments

@evertongodoi
Copy link

Describe the bug

Hi @tnorimat ,

We are currently using Keycloak v20.0.1 along with the client 'ob-br-fapi-1-advanced-id3', which incorporates the 'suppress-refresh-token-rotation' executor. The purpose of this executor is to suppress the rotation of the refresh token. However, we are facing issues during production testing of Open Finance Brazil, specifically in the refresh token verification step. The test involves performing a token exchange to obtain both the access token and the refresh token from the token endpoint. Subsequently, a new request is made at the same token endpoint (using grant_type: refresh_token). However, we have observed that Keycloak is returning a different refresh token than the one received during the token exchange step. This raises the questions:

Was the current implementation designed to operate this way due to the refresh token being formatted as a JWT?
Would it be possible to correct this behavior so that the returned refresh token value is the same as the one obtained during the token exchange?
Refresh token response samples:

Refresh Token Value - First time
{ "alg": "HS256", "typ": "JWT", "kid": "04dcdd70-63b9-4a4d-becb-bcdccf564623" }. { "exp": 1692035094, "iat": 1692033294, "jti": "4b55ea01-7796-42aa-9a9d-b7d759043213", "iss": "https://ofb-auth.conformance.com/auth/realms/test", "aud": "https://ofb-auth.conformance.com/auth/realms/test", "sub": "c2669692-5e5c-46a8-b5d0-b37b8fbd438e", "typ": "Refresh", "azp": "de302d3f-525c-446a-bfc8-740a081f9c02", "nonce": "WnVfVhZLru", "session_state": "8b389e6c-d32e-4c17-a7a3-dc467ea64c88", "scope": "payments consent:urn:ofb:payment:b9d53881-2f5e-4da5-8037-f0b9871c3859 openid", "sid": "8b389e6c-d32e-4c17-a7a3-dc467ea64c88" }

Refresh Token Value - Second time
{ "alg": "HS256", "typ": "JWT", "kid": "04dcdd70-63b9-4a4d-becb-bcdccf564623" }. { "exp": 1692035097, "iat": 1692033297, "jti": "e2aa3ccf-3946-44b5-92bf-b5c0e177fc7c", "iss": "https://ofb-auth.conformance.com/auth/realms/test", "aud": "https://ofb-auth.conformance.com/auth/realms/test", "sub": "c2669692-5e5c-46a8-b5d0-b37b8fbd438e", "typ": "Refresh", "azp": "de302d3f-525c-446a-bfc8-740a081f9c02", "nonce": "WnVfVhZLru", "session_state": "8b389e6c-d32e-4c17-a7a3-dc467ea64c88", "scope": "payments consent:urn:ofb:payment:b9d53881-2f5e-4da5-8037-f0b9871c3859 openid", "sid": "8b389e6c-d32e-4c17-a7a3-dc467ea64c88" }

Thank you for your assistance and insights regarding this matter.

Version

20.0.1

Expected behavior

No response

Actual behavior

No response

How to Reproduce?

No response

Anything else?

No response

@tnorimat
Copy link
Contributor

tnorimat commented Aug 23, 2023

@evertongodoi Hello. You said that

The test involves performing a token exchange to obtain both the access token and the refresh token from the token endpoint.

Does this token exchange means RFC 8693 OAuth 2.0 Token Exchange ?

It seems that Open Banking Brazil FAPI 1.0 security profile was deprecated and could not find anymore, and it was replaced with Open Finance Brazil FAPI 1.0 security profile. It that Right? If so, could you tell me when Open Banking Brazil FAPI 1.0 security profile was replaced with Open Finance Brazil FAPI 1.0 security profile?

Also, the conformance test tool of this OAuth SIG checked and confimed that keycloak can pass conformance tests of Open Finance Brazil FAPI 1.0 security profile Implementer's Draft version 3. The realm setting for the test might be helpful.

@tnorimat
Copy link
Contributor

To execute SuppressRefreshTokenRotationExecutor executor, ClientAccessTypeCondition or ClientRolesCondition built-in conditions can be used. Of course, such the conditon that is evaluated when returning a token response by token refresh can be implemented by yourself.

@evertongodoi
Copy link
Author

@tnorimat I apologize for the previous misunderstanding. I would like to correct the information regarding "Token exchange". In reality, it is the "Proof Key for Code Exchange," as detailed in https://datatracker.ietf.org/doc/html/rfc7636#section-4.3.

After obtaining the consent authorization, the test proceeds to request an access_token using the parameter grant_type=authorization_code. The Keycloak server responds by providing the access_token along with the values "refresh_token" and "refresh_expires_in" value greater than 0.

Subsequently, an attempt is made to obtain a new access_token using the previously acquired "refresh_token," employing the parameter grant_type=refresh_token. However, the test execution fails, as the value of the provided "refresh_token" differs from the value of the "refresh_token" obtained in the previous step.

It is worth mentioning that while the test has received approval in the compliance tests of the Open Finance Brazil FAPI 1.0 specification, it seems to me that the comparison of the "refresh_token" values is not performed in this specific test.

refresh_token

authorization_code

@evertongodoi
Copy link
Author

Hi @tnorimat , how are you? are you understood my question ? The refresh_token is not staying the same after access_token requests, exist the some configuration to staying the same refresh_token ?

@tnorimat
Copy link
Contributor

@evertongodoi Hello,
You might to do the followings:

  • On token refresh, the refresh token is also returned (you do not use SuppressRefreshTokenRotationExecutor).
  • The returned refresh token be the same as the original refresh token on token refresh

AFAIK, there is no way for doing them. Just one idea is as follows (not sure it works well..)

  • Implement an executor that hooks the event ClientPolicyEvent.TOKEN_REFRESH_RESPONSE
  • In the executor, the original refresh token is extracted from the token endpoint's form parameters.
  • In the executor, TokenManager.AccessTokenResponseBuilder's refresh is replaced with the original refresh token.
  • In the executor, TokenManager.AccessTokenResponseBuilder's build() is called.

However, the feature that enables above procedures is included in the main branch of keycloak. No version of keycloak has not yet included it.

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

2 participants