-
-
Notifications
You must be signed in to change notification settings - Fork 302
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
How to allow multiple clients to share the same logout? #342
Comments
Hi,
This scenario requires single sign-out, which is not currently supported by OpenIddict. Backchannel logout may be supported in a future version (see openiddict/openiddict-core#2175), but it will only work with server-side web applications. As an alternative, you can revoke access tokens issued to specific clients from your end session endpoint (note: OpenIddict 6.0 will introduce new APIs to revoke authorizations and tokens attached to a specific client or subject more efficiently) and use the introspection endpoint to query the current status of a token from time to time, which allows detecting whether a token was revoked or not. |
As you know, your answer leads to two questions. |
Here's how you can revoke all the valid access tokens attached to a specific user directly from the logout endpoint (these APIs are already in OpenIddict 4 and 5): [HttpGet("~/connect/logout")]
public IActionResult Logout() => View();
[ActionName(nameof(Logout)), HttpPost("~/connect/logout"), ValidateAntiForgeryToken]
public async Task<IActionResult> LogoutPost()
{
var result = await HttpContext.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
if (result is not { Succeeded: true })
{
return SignOut(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties
{
RedirectUri = "/"
});
}
var subject = result.Principal.GetClaim(Claims.Subject) ?? throw new InvalidOperationException();
await foreach (var token in _tokenManager.FindBySubjectAsync(subject))
{
if (await _tokenManager.GetTypeAsync(token) is TokenTypeHints.AccessToken)
{
await _tokenManager.TryRevokeAsync(token);
}
}
// Ask ASP.NET Core Identity to delete the local and external cookies created
// when the user agent is redirected from the external identity provider
// after a successful authentication flow (e.g Google or Facebook).
await _signInManager.SignOutAsync();
// Returning a SignOutResult will ask OpenIddict to redirect the user agent
// to the post_logout_redirect_uri specified by the client application or to
// the RedirectUri specified in the authentication properties if none was set.
return SignOut(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties
{
RedirectUri = "/"
});
} Alternatively, you can also just revoke the authorizations, which will automatically cause the associated tokens to be rejected when trying to introspect them: var subject = result.Principal.GetClaim(Claims.Subject) ?? throw new InvalidOperationException();
// More efficient way of doing it, but OpenIddict 6.0+-only:
// await _authorizationManager.RevokeBySubjectAsync(subject);
// Usable in previous versions of OpenIddict:
await foreach (var authorization in _authorizationManager.FindBySubjectAsync(subject))
{
await _authorizationManager.TryRevokeAsync(authorization);
}
// Ask ASP.NET Core Identity to delete the local and external cookies created
// when the user agent is redirected from the external identity provider
// after a successful authentication flow (e.g Google or Facebook).
await _signInManager.SignOutAsync();
// Returning a SignOutResult will ask OpenIddict to redirect the user agent
// to the post_logout_redirect_uri specified by the client application or to
// the RedirectUri specified in the authentication properties if none was set.
return SignOut(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties
{
RedirectUri = "/"
}); Once it's in place, enable the introspection endpoint in your server configuration and grant your client the introspection endpoint permission. You'll then be able to use // If that call fails and throws an exception, the access token is no longer valid.
_ = await _service.IntrospectTokenAsync(new()
{
Token = "your access token",
TokenTypeHint = TokenTypeHints.AccessToken
}); |
The above source works normally in 5.0, but an error of unknown cause occurred in my project. After performing several tests, I confirmed that my project version was 3.1.1 for the server and 4.0 for the client. I would like to solve this problem by downloading the server's openiddick library as 5.X from ruget and using the server project code as is. This approach would likely make my project seriously complex. Server openiddick library: 5.X (or 4.X) Is it possible? |
Using different versions of the OpenIddict packages in the same application is not supported but if you're using the OpenIddict server and client in different projects, it shouldn't be a problem. That said, both OpenIddict 3.x and 4.x are no longer supported so I strongly encourage you to update all your projects to 5.x: |
thank you I would like to upgrade to 5.x, but I will upgrade to 4.x. |
Migration from 4.0 to 5.0 I will download and use the 5.0 sample source.
|
Velusia in openiddict-samples-dev 5.X version appears following error. |
Nope. If you use EF Core and its built-in migrations feature, add a new migration after updating the packages and execute it: it will update your database.
Hum, what error exactly? |
I created two Volusia clients. And when I log in one of them, the other client logs off. |
problem appears to be occurring in this part of the code.
|
Weird. Are your two clients hosted on the same domain (e.g localhost)? If so, do you use different cookie names? |
I am in testing. So it's localhost. |
It's possible the ASP.NET Core authentication cookies are colliding. Try setting a different name in one of your clients via |
thank you. I'll let you know the results after testing it. |
My pleasure! ❤️ |
It worked out well. thank you. However, single sign-out does not work.
|
Did you implement this part in your client app? Remember it's not real "single sign-out", you need to poll the token status at regular intervals using introspection:
|
I'm not trying to complete single sign-out. I'm very interested in log out other clients with the cookie name I just resolved. Couldn't this issue be resolved by log out other clients using the cookie name? |
Well, one client or 50, it doesn't change anything, it's still single sign-out, which requires a very specific implementation 😄
Well, it offers a limited level of security since a user can copy the cookies and replay them (they are not "invalidated"). I wouldn't really recommend it. |
Sorry but I still don't understand. introspection endpoint : server What do I need to do to know introspection? |
One simple option is to do that in the |
Please guide me on how to configure the server and client startup. server
client
|
Below code unable access server.
|
You need to add If it still doesn't work, share your logs and I'll take a look. |
You must provide code that handles the server's Introspect endpoint. |
The server options appear to be incorrect.
|
Introspection requests are handled for you by OpenIddict itself: you don't need to provide an action for it. |
I tested it with just the option settings, but it didn't work.
|
No.
Collect the logs and share them, please. |
client
|
server
|
The token isn't attached to the introspection request, most likely because (I'll add a null check to make debugging easier, since it's not legal to send an introspection request without a token attached anyway) |
|
The fundamental problem is that the code below does not read the access token.
|
BackchannelAccessToken is read. But it was rejected by the server.
error message
|
Server logs? |
I'm not sure. Please refer to the code below message
|
No, I really meant the logs of the authorization server: the OAuth 2.0 introspection specification requires returning |
server
client
|
You didn't add the introspection endpoint permission... |
I won't know how unless you tell me. |
👇🏻
https://documentation.openiddict.com/configuration/application-permissions |
It works fine. |
4.x client can't connect to 5.X server?
|
Well, to be honest, it's a workaround, but it should work reliably for the time being 😄
It can, but you can't use the OpenIddict 5.x packages with a database creating using OpenIddict 4x if it hasn't been updated to use the 5.x schema using EF Core migrations. |
Let's make the client 5.x. |
Confirm you've already contributed to this project or that you sponsor it
Version
4.0
Question
VelusiaServer.com VelusiaClientA.com VelusiaClientB.com is logged in. When VelusiaClientA.com logs out, VelusiaServer.com and VelusiaClientA.com log out, but VelusiaClientB.com remains logged in.
How to allow multiple clients to share the same logout?
The text was updated successfully, but these errors were encountered: