directus
directus copied to clipboard
SSO: Keycloak refresh token not working
Describe the Bug
We use Directus Seamless SSO with Keycloak in "session" mode. Authentication works great, auth/refresh works as well.
However, Directus is not able to use the Keycloak refresh token after the Keycloak session expires. You can see in the logs that it first tries to use the session token and then tries to use the refresh token.
2024-04-22 11:05:39 [09:05:39] POST /auth/refresh 403 15ms
2024-04-22 11:05:39 [09:05:39.463] WARN: [OpenID] Invalid grant
2024-04-22 11:05:39 err: {
2024-04-22 11:05:39 "type": "OPError",
2024-04-22 11:05:39 "message": "invalid_grant (Token is not active)",
2024-04-22 11:05:39 "stack":
2024-04-22 11:05:39 OPError: invalid_grant (Token is not active)
2024-04-22 11:05:39 at processResponse (/directus/node_modules/.pnpm/[email protected]/node_modules/openid-client/lib/helpers/process_response.js:38:13)
2024-04-22 11:05:39 at Client.grant (/directus/node_modules/.pnpm/[email protected]/node_modules/openid-client/lib/client.js:1354:22)
2024-04-22 11:05:39 at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
2024-04-22 11:05:39 at async Client.refresh (/directus/node_modules/.pnpm/[email protected]/node_modules/openid-client/lib/client.js:1098:22)
2024-04-22 11:05:39 at async OpenIDAuthDriver.refresh (file:///directus/node_modules/.pnpm/file+api_@[email protected][email protected][email protected][email protected]/node_modules/@directus/api/dist/auth/drivers/openid.js:200:34)
2024-04-22 11:05:39 at async AuthenticationService.refresh (file:///directus/node_modules/.pnpm/file+api_@[email protected][email protected][email protected][email protected]/node_modules/@directus/api/dist/services/authentication.js:261:13)
2024-04-22 11:05:39 at async file:///directus/node_modules/.pnpm/file+api_@[email protected][email protected][email protected][email protected]/node_modules/@directus/api/dist/controllers/auth.js:94:52
2024-04-22 11:05:39 "error": "invalid_grant",
2024-04-22 11:05:39 "error_description": "Token is not active",
2024-04-22 11:05:39 "name": "OPError"
2024-04-22 11:05:39 }
2024-04-22 11:05:39 [09:05:39.463] DEBUG: Invalid token.
2024-04-22 11:05:39 err: {
2024-04-22 11:05:39 "type": "",
2024-04-22 11:05:39 "message": "Invalid token.",
2024-04-22 11:05:39 "stack":
2024-04-22 11:05:39 DirectusError: Invalid token.
2024-04-22 11:05:39 at handleError (file:///directus/node_modules/.pnpm/file+api_@[email protected][email protected][email protected][email protected]/node_modules/@directus/api/dist/auth/drivers/openid.js:220:20)
2024-04-22 11:05:39 at OpenIDAuthDriver.refresh (file:///directus/node_modules/.pnpm/file+api_@[email protected][email protected][email protected][email protected]/node_modules/@directus/api/dist/auth/drivers/openid.js:209:23)
2024-04-22 11:05:39 at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
2024-04-22 11:05:39 at async AuthenticationService.refresh (file:///directus/node_modules/.pnpm/file+api_@[email protected][email protected][email protected][email protected]/node_modules/@directus/api/dist/services/authentication.js:261:13)
2024-04-22 11:05:39 at async file:///directus/node_modules/.pnpm/file+api_@[email protected][email protected][email protected][email protected]/node_modules/@directus/api/dist/controllers/auth.js:94:52
2024-04-22 11:05:39 "name": "DirectusError",
2024-04-22 11:05:39 "code": "INVALID_TOKEN",
2024-04-22 11:05:39 "status": 403
2024-04-22 11:05:39 }
On Keycloak's side:
2024-04-22 11:05:39 2024-04-22 09:05:39,462 WARN [org.keycloak.events] (executor-thread-20) type="REFRESH_TOKEN_ERROR", realmId="<MYID>", clientId="directus", userId="null", ipAddress="<MYIP>", error="invalid_token", grant_type="refresh_token", client_auth_method="client-secret"
This affects the user refresh token as well as the client refresh token (the latter logging out all users once it expired).
To Reproduce
I use the Directus Docker Image v10.10.7 with the following env vars for authentication:
AUTH_PROVIDERS: "keycloak"
AUTH_KEYCLOAK_MODE: "session"
AUTH_KEYCLOAK_DRIVER: "openid"
AUTH_KEYCLOAK_CLIENT_ID: ${KEYCLOAK_DIRECTUS_CLIENT}
AUTH_KEYCLOAK_CLIENT_SECRET: ${KEYCLOAK_DIRECTUS_SECRET}
AUTH_KEYCLOAK_ISSUER_URL: "${KEYCLOAK_URL}/realms/collectivo/.well-known/openid-configuration"
AUTH_KEYCLOAK_IDENTIFIER_KEY: "email"
AUTH_KEYCLOAK_ALLOW_PUBLIC_REGISTRATION: "true"
And Keycloak 23.0. (quay.io/keycloak/keycloak:23.0) with the following OIDC settings:
To reproduce the error, log in to the data studio and wait until the Keycloak session expires, then refresh the page.
The Keycloak session expiration time can be set in the Keycloak Admin console under realm settings -> sessions -> SSO session idle.
Directus Version
v10.10.7
Hosting Strategy
Self-Hosted (Docker Image)
Maybe helpful. I see in my storage that there are two cookies:
- directus_session_token, which has a value
- directus_refresh_token, which is empty
Could it be that the Keycloak refresh token is not stored at all?
Also, when I switch the "AUTH_KEYCLOAK_MODE" back to "cookie", the "Login with Keycloak" Button in Directus Studio disappears.
Maybe helpful. I see in my storage that there are two cookies:
* directus_session_token, which has a value * directus_refresh_token, which is emptyCould it be that the Keycloak refresh token is not stored at all?
directus_refresh_token is not applicable here, directus_session_token is your "session token" which covers both access and refresh.
Also, when I switch the "AUTH_KEYCLOAK_MODE" back to "cookie", the "Login with Keycloak" Button in Directus Studio disappears.
That is by design since you cannot use cookie mode to log into the app.
facing the same, directus version 10.12