oidc-client-ts
oidc-client-ts copied to clipboard
AWS Cognito logout endpoint
I am trying to implement sign-out against an AWS Cognito user pool.
I followed some of the hints here https://github.com/authts/oidc-client-ts/issues/802
const cognito = "xxxxxxxx";
const userPool = "xxxxxxxxxxxxx";
const clientId = "xxxxxxxxxxxxxxxxx";
const redirectUri = "http://localhost:3000";
const logoutUri = "http://localhost:3000";
const authorizationEndpoint = `https://${cognito}.auth.eu-west-2.amazoncognito.com/oauth2/authorize?response_type=code&client_id=${encodeURIComponent(clientId)}&redirect_uri=${encodeURIComponent(redirectUri)}`;
const endSessionEndpoint = `https://${cognito}.auth.eu-west-2.amazoncognito.com/logout?client_id=${encodeURIComponent(clientId)}&logout_uri=${encodeURIComponent(logoutUri)}&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=code`;
const userManager = new UserManager({
authority: `https://cognito-idp.us-east-1.amazonaws.com/${userPool}`,
client_id: clientId,
redirect_uri: "http://localhost:3000",
metadata: {
authorization_endpoint: authorizationEndpoint,
end_session_endpoint: endSessionEndpoint,
revocation_endpoint: `https://${cognito}.auth.us-east-1.amazoncognito.com/oauth2/revoke`,
},
// no revoke of "access token" (https://github.com/authts/oidc-client-ts/issues/262)
revokeTokenTypes: [ "refresh_token" ],
// no silent renew via "prompt=none" (https://github.com/authts/oidc-client-ts/issues/366)
automaticSilentRenew: false,
});
However, when I call userManager.signoutRedirect()
, I get sent to the login screen hosted by AWS Cognito.
If I ignore the screen and navigate to http://localhost:3000/
, then I find that I am still signed in (userManager.getUser()
resolves to a user).
I can get sign-out like behaviour by calling userManager.removeUser()
instead, but this seems wrong.
- Will the
removeUser
approach lead to issues? - How should
oidc-client-ts
be configured to work with the Cognito logout endpoint?
You will need to configure the post_logout_redirect_uri
in your oidc application and on IDP side, this and a valid session will make the IDP to call back into your application. In that callback you can call mgr.signoutCallback
and navigate where you want.
Thanks, I followed those steps and was able to make progress.
However, it still seems to not actually sign-out.
Here is the sign-out logic:
if (window.document.location.pathname === "/logout") {
console.log("signoutCallback...");
await userManager.signoutCallback();
console.log("signoutCallback done.");
const maybeUser = await userManager.getUser();
const hasUser = !!maybeUser;
console.log({ maybeUser });
}
And the output:
signoutCallback...
signoutCallback done.
[UserManager] getUser: user loaded
Object { hasUser: true }
Is it expected that getUser
will return a user after the signoutCallback
has completed?
Is it expected that
getUser
will return a user after thesignoutCallback
has completed?
No after the signout process its expected, that you have no user. You will need to debug that. BTW: Which version of this library do you have? 3.0.0 is here different compared to 2.4.0....
Is it expected that
getUser
will return a user after thesignoutCallback
has completed?No after the signout process its expected, that you have no user. You will need to debug that. BTW: Which version of this library do you have? 3.0.0 is here different compared to 2.4.0....
Sorry, I should have specified.
oidc-client-ts@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/oidc-client-ts/-/oidc-client-ts-3.0.0.tgz#910b27193b54730dbabd93709ca000f8b1e5bdf2"
integrity sha512-YUcel/+C4AmXXhM/geNWc1jBsBVYzd+xhvSl1NMkxKpzZXqhLKmtj1ttSdxtDYm3P2YelnAr4zS4c96+p02iFQ==
dependencies:
jwt-decode "^4.0.0"
Looking at the source-code, it seems like it silently returns when there is no state in the URL.
AWS Cognito (somewhat strangely) does not pass any state back from the logout callback, so perhaps this is the issue?
I may be that Cognito is not a fully compliant endpoint, but given its popularity I am hoping that people have found work-arounds.
according to https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html the logout endpoint expects a client_id
and a logout_uri
query parameters.
I managed to get logout working by adding extra query params:
userManager.signoutRedirect({
extraQueryParams: {
client_id: userManager.settings.client_id,
logout_uri: 'http://localhost:1234/logout-callback'
}
})
If you specify a redirect_uri
/response_type
instead the user will be asked to re-login before going back to your application with a token. This flow (calling signoutRedirect
and receiving a new token in signoutCallback
) is unexpected, I guess the lib will happily gobble the new token and sign in the user again?