登出
在 Logto(作为基于 OIDC 的身份提供商)中,登出过程是一个多层面的概念,因为它涉及 Logto 管理的集中式登录会话和客户端应用程序管理的分布式认证 (Authentication) 状态。
登录会话
为了更好地理解登出过程,首先需要了解 Logto 中用户登录会话及其认证 (Authentication) 状态是如何管理的。
- 用户访问 Web 应用程序(RP)。
- 客户端应用程序将用户重定向到 Logto(IdP)进行认证 (Authentication)。
- OIDC 提供方检查用户的登录会话状态。如果没有会话或会话已过期,则提示用户登录。
- 用户与登录页面交互以完成认证 (Authentication)。
- 登录成功后,Logto 为用户创建一个新会话,并带授权码重定向回客户端应用程序。
- OIDC 提供方为用户创建新的登录会话和认证 (Authentication) 授权。
- OIDC 提供方带认证 (Authentication) 码重定向用户回客户端(授权码流程)。
- 客户端收到认证 (Authentication) 码并用其换取令牌以访问用户信息。
- 向客户端应用程序授予令牌。
组件
由 Logto 管理的集中式登录会话
在上述流程中,集中式登录会话由 Logto 管理。用户成功登录时会创建会话,用户登出时会销毁会话。用户会话过期时也会销毁会话。
Logto 登录会话通过会话 Cookie 管理。用户登录时会设置会话 Cookie。所有认证 (Authentication) 请求都会根据会话 Cookie 验证。如果会话 Cookie 存在且有效,用户将被自动认证 (Authentication) 并直接重定向回客户端应用程序并带上授权码。否则,用户会被提示登录。
-
共享 Logto 会话 Cookie
对于从同一用户代理(如浏览器)登录多个客户端应用程序的用户,会在 Logto 域下拥有一个共享的会话 Cookie。这意味着用户只需登录一次,即可自动认证 (Authentication) 其他客户端应用程序。 -
隔离的 Logto 会话 Cookie
对于从不同设备或浏览器登录不同客户端应用程序的用户,会在 Logto 域下拥有隔离的会话 Cookie。这意味着用户需要分别为每个客户端应用程序登录。
由客户端应用程序管理的分布式认证 (Authentication) 状态
每个客户端应用程序都维护自己的认证 (Authentication) 状态。无论是 Native、SPA 还是 Web 应用程序,都有各自管理用户认证 (Authentication) 状态的方式。
登录成功后,客户端应用程序可能会收到 ID 令牌 (ID token) 和 访问令牌 (Access token)。客户端应用程序可以使用 ID 令牌 (ID token) 来确定用户身份,使用访问令牌 (Access token) 访问用户资源。用户的认证 (Authentication) 状态由访问令牌 (Access token) 的过期时间表示。
- Native 和 SPA 应用程序:
客户端应用程序需要安全地存储和管理这些令牌,以维持用户的认证 (Authentication) 状态。例如,将令牌存储在本地存储或会话存储中,用户登出时清除令牌。 - Web 应用程序:
例如使用 Next.js 等框架构建的 Web 应用,通常会在本地用户会话和 Logto 下发的令牌之间自行管理登录状态。用户登录后,Web 应用收到 Logto 的令牌,可以像 SPA 应用一样在客户端存储令牌,也可以在服务端存储令牌并通过 Cookie 或其他机制管理会话。
登出机制
清除客户端本地令牌和会话
在客户端,简单的登出操作包括清除本地会话并从本地存储或会话存储中移除令牌(ID 令牌 (ID token)、访问令牌 (Access token)、刷新令牌 (Refresh token))。这种方式只会在客户端登出,集中式会话仍然存在。以这种方式登出的用户,仍可能在同一授权服务器会话下访问其他应用,直到集中式会话过期或被主动销毁。
清除 Logto 登录会话
如需显式登出用户并清除 Logto 的会话,客户端应用程序需要将用户重定向到 Logto 的 end session endpoint。
例如:https://{your-logto-domain}/oidc/session/end
end session endpoint 是标准的 OIDC 端点,允许客户端应用程序通知授权服务器用户已登出。该端点会清除 Logto 的集中式登录会话。
会话清除后,任何后续授权请求都需要用户重新登录。
如果提供了 post-logout redirect URI,会话清除后用户会被重定向到指定 URI。否则,用户会被重定向到 Logto 托管的默认登出后页面。
联邦登出:后端通道登出(Back-channel logout)
为实现更一致的登出管理,Logto 支持 后端通道登出 (back-channel logout)。后端通道登出是一种机制,允许 Logto 在用户登出时通知同一登录会话下的所有客户端应用程序。
这在用户从一个客户端应用程序登出并期望在同一 Logto 登录会话下的所有其他客户端应用程序也被登出时特别有用。
要为你的客户端应用程序启用后端通道登出,请在 Logto 控制台的应用详情页注册后端通道登出 URI。当用户从任意客户端应用程序发起登出请求时,Logto 会向所有已注册的 URI 发送登出令牌。
如果你的客户端应用程序需要在登出令牌中包含登录会话,可在后端通道登出配置中开启 Is session required
设置。此时,登出令牌中会包含 sid
声明,用于标识 Logto 上的用户登录会话。
- 用户从某个客户端应用程序发起登出请求。
- Logto 收到 end session 请求,生成登出令牌,并将其发送到所有已注册的后端通道登出 URI。
- 每个客户端应用程序收到登出令牌并执行登出操作。
客户端应用程序收到登出令牌后的登出操作:
- 验证登出令牌。
- 清除本地会话并从本地存储或会话存储中移除令牌。
Logto SDK 中的登出方法
如果你通过 Logto 的 SDK 集成客户端应用程序:
- 对于 SPA 和 Web 应用程序,
client.signOut()
方法会清除本地令牌存储,并将用户重定向到 Logto 的 end session endpoint。你可以指定 post-logout redirect URI,以便会话清除后重定向用户。 - 对于原生应用程序(包括 React Native 和 Flutter 等混合应用),只会清除本地令牌存储。这是因为在原生应用中,登录流程使用无会话 webview,不会在原生浏览器中存储会话 Cookie,因此无需清除 Logto 的登录会话。每次认证 (Authentication) 请求都是独立的,不携带任何会话 Cookie。
对于不支持无会话 webview 或无法识别 emphasized
设置的原生应用(如 Android 上的 React Native 或 Flutter SDK),你可以在授权请求中传递 prompt=login
参数,强制用户重新登录。
强制每次访问都重新认证 (Authentication)
在高安全场景下——如在敏感操作前验证用户身份——你可能希望每次访问都要求用户重新认证 (Authentication)。要强制此行为,请在认证 (Authentication) 请求中包含 prompt=login
。
设置 prompt=login
会强制 Logto 始终显示登录页面,无论用户是否有活动会话或最近登录过。这会绕过单点登录 (SSO) 行为,确保用户每次都需要输入凭据。
如果你的应用请求了 offline_access scope(以获取刷新令牌 (Refresh token)),OpenID Connect 规范要求你同时包含 prompt=consent
。
大多数情况下,为了同时强制重新认证 (Authentication) 并确保刷新令牌 (Refresh token) 下发,应设置:
prompt=login consent
这样可以保证用户被重新认证 (Authentication) 并明确同意离线访问。
常见问题解答
我没有收到后端通道登出通知
- 请确保后端通道登出 URI 已在 Logto 控制台正确注册。
- 请确保你的客户端应用程序有一个有效的活动登录会话,并且与发起登出请求的是同一个会话。
相关资源
理解 OIDC 后端通道登出 (back-channel logout)。