keycloak / kc-sig-fapi

Apache License 2.0
76 stars 52 forks source link

Refresh Token #422

Open evertongodoi opened 1 year ago

evertongodoi commented 1 year ago

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 commented 1 year ago

@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 commented 1 year ago

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 commented 1 year ago

@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 commented 1 year ago

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 commented 1 year ago

@evertongodoi Hello, You might to do the followings:

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

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