写点什么

OIDC & OAuth2.0 认证协议最佳实践系列 02 - 授权码模式(Authorization Code)接入 Authing

作者:Authing
  • 2023-05-31
    北京
  • 本文字数:9152 字

    阅读完需:约 30 分钟

OIDC & OAuth2.0 认证协议最佳实践系列 02 - 授权码模式(Authorization Code)接入 Authing

在上一篇文章中(OIDC & OAuth2.0 协议及其授权模式详解|认证协议最佳实践系列【1】),我们整体介绍 OIDC / OAuth2.0 协议,本次我们将重点围绕授权码模式(Authorization Code)以及接入 Authing 进行介绍,从而让你的系统快速具备接入用户认证的标准体系。


接入 Authing 后的优势: 在整个 Authing 的身份源中,已经包含了社会化登录方式 微信、微博、QQ、FB、TW ...等等,企业登录方式 飞书、钉钉、企微、AD 等等,只要你完成了接入 Authing 就意味着你的业务系统具备了这些能力。

01 授权码模式(Authorization Code)

授权码模式适合应用具备后端服务器的场景。授权码模式要求应用必须能够安全存储密钥,用于后续使用授权码换 access_token。授权码模式需要通过浏览器与终端用户交互完成认证授权,然后通过浏览器重定向将授权码发送到后端服务,之后进行授权码换 token 以及 token 换用户信息。

1.1 整体流程

整体上,有以下流程:


1.在你的应用中,让用户访问登录链接,浏览器跳转到 Authing,用户在 Authing 完成认证。

2.浏览器接收到一个从 Authing 服务器发来的授权码。

3.浏览器通过重定向将授权码发送到你的应用后端。

4.你的应用服务将授权码发送到 Authing 获取 AccessToken 和 IdToken,如果需要,还会返回 refresh token。

5.你的应用后端现在知道了用户的身份,后续可以保存用户信息,重定向到前端其他页面,使用 AccessToken 调用资源方的其他 API 等等。


流程图如下:


1.2 准备接入

在 Authing 创建应用及配置


创建应用:


配置登录回调和登出回调,配置为你实际项目的地址,我们在这里配置 localhost 用于测试。


若你想匹配多个登录/登出回调,可以使用 ‘*’ 号进行通配,登录/登出回调可以是如下格式:



在协议配置中,我们勾选 authorization_code 并且使用 code 作为返回类型,如下图所示:

1.3 接入测试

01 所需调用接口列表

GET${host}/oidc/auth 发起登录(拼接你的发起登录地址)POST${host}/oidc/token 获取 TokenGET${host}/session/me 获取用户信息POST${host}/oidc/token/introspection 校验 TokenPOST${host}/oidc/token 刷新 TokenPOST${host}/oidc/revocation 吊销 TokenGET${host}/session/end 登出
复制代码

02 Run in Postman

以下要介绍的接口可以通过我们的在线 postman collection 自行 fork 体验。

03 发起登录

GET${host}/oidc/auth
复制代码


这是基于浏览器的 OIDC 的起点,请求对用户进行身份验证,并会在验证成功后返回授权码到您所指定的 redirect_uri。


拼接发起登录地址(浏览器中打开):

https://{host}/oidc/auth?scope=openid+profile+email+phone+username&redirect_uri={redirect_uri}&response_type=code&client_id={应用 ID}&state={state}
复制代码


如您需要额外获取 refresh_token 则请求格式为:

https://{host}/oidc/auth? scope=openid+profile+offline_access+username+email+phone&redirect_uri=http://localhost:8080/&response_type=code&client_id={应用 ID}&prompt=consent&state={state}
复制代码


点此体验:

https://oidc-authorization-code.authing.cn/oidc/auth?scope=openid+profile+offline_access+username+email+phone&redirect_uri=http://localhost:8080/&response_type=code&prompt=consent&nonce=054d3c0e-9df9-46f2-a8fa-a7f479032660&client_id=63eb4585156d977101dd3750&state=1676366724
复制代码


参数说明:

04 获取 Token

POST${host}/oidc/token
复制代码


用户在 Authing 侧完成登录操作后, Authing 会将生成的 code 作为参数回调到 redirect_uri 地址,此时通过 code 换 token 接口即可拿到对应的访问令牌 access_token 。


1.请求参数


2.请求事例

curl --location --request POST 'https://{host}/oidc/token' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'client_id={应用ID}' \--data-urlencode 'client_secret={应用密钥}' \--data-urlencode 'grant_type=authorization_code' \--data-urlencode 'redirect_uri={发起登录时指定的 redirect_uri}' \--data-urlencode 'code={/oidc/auth 返回的code}'
复制代码


3.响应示例 (成功)

{    "scope": "openid username email phone offline_access profile",    "token_type": "Bearer",    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImVtSzBGbVRIa0xlQWFjeS1YWEpVT3J6SzkxV243TkdoNGFlYUVlSjVQOUUifQ.eyJzdWIiOiI2M2ViNTNjNDQxYTVjMmYwNWYyNGJiMDMiLCJhdWQiOiI2M2ViNDU4NTE1NmQ5NzcxMDFkZDM3NTAiLCJzY29wZSI6Im9wZW5pZCB1c2VybmFtZSBlbWFpbCBwaG9uZSBvZmZsaW5lX2FjY2VzcyBwcm9maWxlIiwiaWF0IjoxNjc2MzY2OTE0LCJleHAiOjE2Nzc1NzY1MTQsImp0aSI6ImVmVU04enNrbl92LXYzeXZfbDVHRV9fQ2JEY0NNZDhEVDFnYVI0bHRqcHAiLCJpc3MiOiJodHRwczovL29pZGMtYXV0aG9yaXphdGlvbi1jb2RlLmF1dGhpbmcuY24vb2lkYyJ9.E3gAYzCQbJmrtM5zl91OPHm2YPnDxzRejw75oVMF1tLqCS0trj6CSBxyxP3Z9t6Eb_oAu1f_3I6XC3KC-l0DTM6q7_R2rnW4LWlik2rDCLuGpG0FqFScLZhwafmrPsVn93yaBQfEEoaLviqKhj3DgOymKqHZzFG3taaz2k_pWsxt4z97DtKjRTiqyMvcSfHsVrjSKELaC-5S_PHPWcQ70iX85IwUb6i5ldZGxYmODCvChNC9p4D4IOT3atvyEHgBTmjA9ZKI-T7hCVHSO91WZY3l1p4iWdi6KdP1oMGTy8WbmUHG9SiWO1Efh_9I5ZpRzVNWXINLv-lZ0d2aZKjg2w",    "expires_in": 1209600,    "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI2M2ViNTNjNDQxYTVjMmYwNWYyNGJiMDMiLCJhdWQiOiI2M2ViNDU4NTE1NmQ5NzcxMDFkZDM3NTAiLCJpYXQiOjE2NzYzNjY5MTQsImV4cCI6MTY3NzU3NjUxNCwiaXNzIjoiaHR0cHM6Ly9vaWRjLWF1dGhvcml6YXRpb24tY29kZS5hdXRoaW5nLmNuL29pZGMiLCJub25jZSI6IjhiYjg3MjdhLWU1MGUtNDUzOC05ZmZmLWZhOTFlNWQ0Y2MwYSIsIm5hbWUiOm51bGwsImdpdmVuX25hbWUiOm51bGwsIm1pZGRsZV9uYW1lIjpudWxsLCJmYW1pbHlfbmFtZSI6bnVsbCwibmlja25hbWUiOm51bGwsInByZWZlcnJlZF91c2VybmFtZSI6bnVsbCwicHJvZmlsZSI6bnVsbCwicGljdHVyZSI6Imh0dHBzOi8vZmlsZXMuYXV0aGluZy5jby9hdXRoaW5nLWNvbnNvbGUvZGVmYXVsdC11c2VyLWF2YXRhci5wbmciLCJ3ZWJzaXRlIjpudWxsLCJiaXJ0aGRhdGUiOm51bGwsImdlbmRlciI6IlUiLCJ6b25laW5mbyI6bnVsbCwibG9jYWxlIjpudWxsLCJ1cGRhdGVkX2F0IjoiMjAyMy0wMi0xNFQwOToyNjoyOC4wNjhaIiwiZW1haWwiOm51bGwsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicGhvbmVfbnVtYmVyIjoiMTg1MTY4Mjk5OTUiLCJwaG9uZV9udW1iZXJfdmVyaWZpZWQiOnRydWUsInVzZXJuYW1lIjpudWxsfQ.GweoWBCEyHQGP6G9ohbfBMUMALlbZMM9hRAes1De7BM",    "refresh_token": "KanvCEmonS_FgCRdFftOCwka2f8Qjj4tcsIfJF-VC1W"}
复制代码


4.响应示例 (失败)

{    "error": "invalid_grant",    "error_description": "授权码无效或已过期"}
复制代码

05 通过 AccessToken 获取用户信息

GET${host}/session/me 获取用户信息
复制代码


此端点是 OIDC 获取用户端点,可以通过 AccessToken 获取有关当前登录用户的信息。


1.请求参数


2.请求示例

curl --location --request GET 'https://{host}/oidc/me?access_token={access_token}' 
复制代码


3.响应示例 (成功)

{    "name": null,    "given_name": null,    "middle_name": null,    "family_name": null,    "nickname": null,    "preferred_username": null,    "profile": null,    "picture": "https://files.authing.co/authing-console/default-user-avatar.png",    "website": null,    "birthdate": null,    "gender": "U",    "zoneinfo": null,    "locale": null,    "updated_at": "2023-02-14T09:26:28.068Z",    "email": "xxx@authing.cn",    "email_verified": true,    "phone_number": "185xxxx9995",    "phone_number_verified": true,    "username": "neo",    "sub": "63eb53c441a5c2f05f24bb03"}
复制代码


4.响应示例 (失败)

{    "error": "invalid_grant",    "error_description": "Access Token 无效"}
复制代码

06 校验 Token

POST${host}/oidc/token/introspection
复制代码


此端点接受 access_token、id_token、refresh_token ,并返回一个布尔值,指示它是否处于活动状态。如果令牌处于活动状态,还将返回有关令牌的其他数据。如果 token 无效、过期或被吊销,则认为它处于非活动状态。


1.验证 Token 分为两种方式:


本地验证与使用 Authing 在线验证。我们建议在本地验证 JWT Token,因为可以节省你的服务器带宽并加快验证速度。你也可以选择将 Token 发送到 Authing 的验证接口由 Authing 进行验证并返回结果,但这样会造成网络延迟,而且在网络拥塞时可能会有慢速请求。


access_token 可以使用 RS256 签名算法或 HS256 签名算法进行签名。下面是这两种签名算法的区别:


RS256 是使用 RSA 算法的一种数字签名算法,它使用公钥/私钥对来加密和验证信息。RS256 签名生成的令牌比 HS256 签名生成的令牌更加安全,因为使用 RSA 密钥对进行签名可以提供更高的保护级别。使用 RS256 签名算法的令牌可以使用公钥进行验证,公钥可以通过 JWK 端点获取。


HS256 是使用对称密钥的一种数字签名算法。它使用同一个密钥进行签名和验证。HS256 签名算法在性能方面比 RS256 签名算法更快,因为它使用的是对称密钥,而不是使用 RSA 公钥/私钥对来签名和验证。使用 HS256 签名算法的令牌可以通过 shared secret (应用密钥)进行验证。 在实际应用中,RS256 算法更加安全,但同时也更加消耗资源,如果系统需要高性能,可以选择 HS256 签名算法。


以下是本地验证和在线验证的优劣对比:


2.在线验证


需要注意的是,id_token 目前无法在线校验,因为 id_token 只是一个标识,若需要校验 id_token 则需要您在离线自行校验。


请求参数


请求示例

curl --location --request POST 'https://{host}/oidc/token/introspection' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'client_id={应用ID}' \--data-urlencode 'client_secret={应用密钥}' \--data-urlencode 'token={ token }' \--data-urlencode 'token_type_hint={token_type_hint}'
复制代码


校验 access_token 响应示例(校验通过)

{    "active": true,    "sub": "63eb53c441a5c2f05f24bb03",    "client_id": "63eb4585156d977101dd3750",    "exp": 1677648467,    "iat": 1676438867,    "iss": "https://oidc-authorization-code.authing.cn/oidc",    "jti": "ObgavGBUocr1wsrUvtDLHmuFSgoebxsiOY4JNRqIhaQ",    "scope": "offline_access username profile openid phone email",    "token_type": "Bearer"}
复制代码


校验 access_token 响应示例(校验未通过)

{    "active": false}
复制代码


校验 refresh_token 响应示例 (校验通过)

{    "active": true,    "sub": "63eb53c441a5c2f05f24bb03",    "client_id": "63eb4585156d977101dd3750",    "exp": 1679030867,    "iat": 1676438867,    "iss": "https://oidc-authorization-code.authing.cn/oidc",    "jti": "6F2TO1v1YZ1_N7I3jXYHjK-vZzKtlD0IiP5KPoUFUCQ",    "scope": "offline_access username profile openid phone email"}
复制代码


校验 refresh_token 响应示例(校验未通过)


{ "active": false}
复制代码


3.离线校验


可参考文档:离线校验


( 文档链接:https://docs.authing.cn/v2/guides/faqs/how-to-validate-user-token.html# )
复制代码


我们简单说下,若您使用离线校验应该对 token 进行如下规则的校验:


1.格式校验 - 校验 token 格式是否是 JWT 格式

2.类型校验 - 校验 token 是否是目标 token 类型,比如 access_token 、id_token、refresh_token

3.issuer 校验 - 校验 token 是否为信赖的 issuer 颁发

4.签名校验 - 校验 token 签名是否由 issuer 签发,防止伪造

5.时间校验 - 校验 token 是否在有效期内

6.claims 校验 - 是否符合与预期的一致


以上 6 点均校验通过,我们才能认为 token 是有效且合法的。


下面是一个示例 Java 代码,可以用于在本地校验 OIDC RS256 和 HS256 签发的 access_token 。

import com.nimbusds.jose.JWSObject;import com.nimbusds.jwt.JWTClaimsSet;import com.nimbusds.jwt.SignedJWT;
import java.net.URL;import java.text.ParseException;import java.util.Date;
public class OIDCValidator { private static final String ISSUER = "https://your-issuer.com"; private static final String AUDIENCE = "your-client-id";
private final URL jwkUrl;
public OIDCValidator(final URL jwkUrl) { this.jwkUrl = jwkUrl; }
public JWTClaimsSet validateToken(final String accessToken) throws ParseException { final SignedJWT signedJWT = SignedJWT.parse(accessToken); if (signedJWT == null) { throw new RuntimeException("Access token is null or empty"); }
final JWTClaimsSet claims = signedJWT.getJWTClaimsSet(); if (claims == null) { throw new RuntimeException("No claims present in the access token"); }
if (!claims.getIssuer().equals(ISSUER)) { throw new RuntimeException("Invalid issuer in access token"); }
if (!claims.getAudience().contains(AUDIENCE)) { throw new RuntimeException("Invalid audience in access token"); }
final JWSObject jwsObject = signedJWT.getJWSObject(); if (jwsObject == null) { throw new RuntimeException("No JWS object found in the access token"); }
// Fetch the JWKs from the JWK set URL final JWKSet jwkSet = JWKSet.load(jwkUrl); final JWK jwk = jwkSet.getKeyByKeyId(jwsObject.getHeader().getKeyID()); if (jwk == null) { throw new RuntimeException("No JWK found for the access token"); }
if (!jwsObject.verify(jwk.getKey())) { throw new RuntimeException("Invalid signature in access token"); }
if (claims.getExpirationTime() == null || claims.getExpirationTime().before(new Date())) { throw new RuntimeException("Expired access token"); }
return claims; }}
复制代码


这段代码使用 Nimbus JOSE+JWT 库来解析和验证 JWT token。它使用指定的 issuer 和 audience 值对 access_token 进行验证,并验证 JWT 中 claims 的格式、类型、签名、有效期和 issuer。如果发生任何验证错误,则将抛出 RuntimeException。使用时需要传入对应的 JWK URL 和 access_token 进行调用,例如:


final URL jwkUrl = new URL("https://your-issuer.com/.well-known/jwks.json");final OIDCValidator validator = new OIDCValidator(jwkUrl);final String accessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";final JWTClaimsSet claims = validator.validateToken(accessToken);
复制代码


这个示例只校验了 RS256 和 HS256 签名算法。

07 刷新 Token

POST${host}/oidc/token


此功能用于用户 token 的刷新操作,在 token 获取阶段需要先获取到 refresh_token 。


1.请求参数


2.请求示例

curl --location --request POST 'https://{host}/oidc/token' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'client_id={应用ID}' \--data-urlencode 'client_secret={应用密钥}' \--data-urlencode 'refresh_token={刷新令牌}' \--data-urlencode 'grant_type=refresh_token'
复制代码


3.响应示例(成功)

{    "refresh_token": "6F2TO1v1YZ1_N7I3jXYHjK-vZzKtlD0IiP5KPoUFUCQ",    "scope": "offline_access username profile openid phone email",    "token_type": "Bearer",    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImVtSzBGbVRIa0xlQWFjeS1YWEpVT3J6SzkxV243TkdoNGFlYUVlSjVQOUUifQ.eyJzdWIiOiI2M2ViNTNjNDQxYTVjMmYwNWYyNGJiMDMiLCJhdWQiOiI2M2ViNDU4NTE1NmQ5NzcxMDFkZDM3NTAiLCJzY29wZSI6Im9mZmxpbmVfYWNjZXNzIHVzZXJuYW1lIHByb2ZpbGUgb3BlbmlkIHBob25lIGVtYWlsIiwiaWF0IjoxNjc2NDQ0MjY4LCJleHAiOjE2Nzc2NTM4NjgsImp0aSI6IkEtZUlQYkJ5N3lJLTliUmp1RnJHeXNCSXdjbWtOUl9WalpYODB2aU05VFkiLCJpc3MiOiJodHRwczovL29pZGMtYXV0aG9yaXphdGlvbi1jb2RlLmF1dGhpbmcuY24vb2lkYyJ9.Kk3jSK5BSUEDVTQMdMAdG5cBCxZt31vQiD-XYHNA84Gd3Mo8eDLcQpjMEzQ8HJ4_b9IgMOz5ydXz0zAQ6AjLMW3Rl49qhTGDB7Kq7tHTFmDO8itoO2LQTCLPCPtP3TkoOgptlFD_sd32nefH-HojNhuqwKw469Byw3xnW5xEs3wSuOoUdHwR2n9j1T1Zgp3e90xmBjbtbofQE1z0IWtCnrfJ9ujWsKXoN_7OAXbCTa-Ak_DhgLHU7xutQaaBOgD28lLLT5xclgBWfv7Leyx_kBnVGT5Jvo1tfA6AUEp6wJO4GUBzsijLefI04VDzBGypNuFJlw_jOhSp-SWxJjQSwQ",    "expires_in": 1209600,    "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI2M2ViNTNjNDQxYTVjMmYwNWYyNGJiMDMiLCJhdWQiOiI2M2ViNDU4NTE1NmQ5NzcxMDFkZDM3NTAiLCJpYXQiOjE2NzY0NDQyNjgsImV4cCI6MTY3NzY1Mzg2OCwiaXNzIjoiaHR0cHM6Ly9vaWRjLWF1dGhvcml6YXRpb24tY29kZS5hdXRoaW5nLmNuL29pZGMiLCJuYW1lIjpudWxsLCJnaXZlbl9uYW1lIjpudWxsLCJtaWRkbGVfbmFtZSI6bnVsbCwiZmFtaWx5X25hbWUiOm51bGwsIm5pY2tuYW1lIjpudWxsLCJwcmVmZXJyZWRfdXNlcm5hbWUiOm51bGwsInByb2ZpbGUiOm51bGwsInBpY3R1cmUiOiJodHRwczovL2ZpbGVzLmF1dGhpbmcuY28vYXV0aGluZy1jb25zb2xlL2RlZmF1bHQtdXNlci1hdmF0YXIucG5nIiwid2Vic2l0ZSI6bnVsbCwiYmlydGhkYXRlIjpudWxsLCJnZW5kZXIiOiJVIiwiem9uZWluZm8iOm51bGwsImxvY2FsZSI6bnVsbCwidXBkYXRlZF9hdCI6IjIwMjMtMDItMTRUMDk6MjY6MjguMDY4WiIsImVtYWlsIjpudWxsLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInBob25lX251bWJlciI6IjE4NTE2ODI5OTk1IiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjp0cnVlLCJ1c2VybmFtZSI6bnVsbH0.DGoJrzkgti44zw-MotVM1KpLxbJTzc5pfh-xYun_xDQ"}
复制代码


4.响应示例(失败)

{    "error": "invalid_grant",    "error_description": "Refresh Token 无效或已过期"}
复制代码

08 撤回 Token

POST${host}/oidc/token/revocation


撤销 access_token / refresh_token


1.请求参数


2.请求示例

curl --location --request POST 'https://{host}/oidc/token/revocation' \--header 'Content-Type: application/x-www-form-urlencoded' \--data-urlencode 'client_id={应用ID}' \--data-urlencode 'client_secret={应用密钥}' \--data-urlencode 'token= {token}' \--data-urlencode 'token_type_hint={token_type_hint}'
复制代码


3.响应示例(成功)

HTTP 200 OK
复制代码


4.响应示例(失败)

{    "error": "xxxx",    "error_description": "xxxx"}
复制代码

09 用户登出

GET${host}/oidc/session/end


使用此操作通过删除用户的浏览器会话来注销用户。 post_logout_redirect_uri 可以指定在执行注销后重定向的地址。否则,浏览器将重定向到默认页面


1.请求参数


2.请求示例 (浏览器访问)


GET https://oidc-authorization-code.authing.cn/oidc/session/end?id_token_hint={id_token}&post_logout_redirect_uri=http://localhost:8080/&state=1676452381
复制代码

02 SSO (Single Sign-On) 单点登录 & SLO (Single Logout) 单点登出

2.1 SSO 实现

SSO(Single Sign-On) 单点登录,即同时访问多个应用仅需要登录一次。


举例:我们现在有两个站点分别是


uthing.com


ething.com


我们希望用户在 uthing.com 进行认证后,跳转到 ething 后无需二次认证,反之也是一样的。


具体流程:


1.用户访问 http://uthing.com ,uthing 前端发现用户未认证,跳转至 Authing 进行认证。

2.用户在 Authing 发起认证完成,Authing 创建 SSO Session ,下发临时授权码 (code) 重定向到 uthing 后台。


需要注意的是,在这里我们也可以重定向到前端页面,再由前端页面自行判断如果是 Authing 回调请求,则携带临时 code 到 uthing 后台去获取 token 。


3.uthing 后台通过 code 向 Authing 换取 access_token、id_token、refresh_token 等,并下发给前端。

4.uthing 前端通过 access_token 可以直接向 Authing OIDC 用户信息端点获取当前用户信息。

5.uthing 前端在在后续请求后台时,携带由 Authing 颁发的 access_token ,后台在接受到用户请求后去 Authing 校验 Token 是否有效,有效则可放行,若 Token 校验失败或已过期则返回错误信息。

6.用户访问 http://ething.com ,ething 跳转至 Authing 进行认证。

7.由于用户在 Authing 已经完成认证,创建了 sso_session ,Authing 侧直接下发临时授权码 (code) ,无需二次认证,后续流程同 1 。


我们发现,用户在 uthing 认证成功的时候,再访问 ething 的时候会向 Authing 跳转一下,才能完成后续流程,这是由于 http://ething.comhttp://uthing.com 并不是同一个站点,无法实现 cookie 共享,如果你的产品地址是 :


uthing.xxx.com


ething.xxx.com


我们则可以利用相同域下 cookie 共享的方式实现 SSO ,从而避免此问题。

2.2 SLO 实现

SLO(Single Logout) 单点登出,即多个应用仅需要登出一次,其他应用也自动登出 。

01 场景 1

如果你的产品地址是同一个域,例如:

uthing.xxx.com

ething.xxx.com


则 SLO 流程如下:


1.用户在某个站点登出,我们则需要调用 OIDC 登出端点销毁 Token,由于是 cookie 共享实现的 SSO ,然后清除 http://xxx.com 对应会话的 cookie 即可。

2.ething / uting 应当在每次发起请求前,判断 cookie 中是否存在登录态,若不存在,则需要跳转默认页面提示用户已经登出。

02 场景 2

如果你的产品地址不是同一个域,例如:

uthing.com

ething.com


则 SLO 流程如下:


1.用户在某个站点登出,我们则需要调用 OIDC 登出端点销毁 Token,在 Authing 的应用配置中,你应当先把应用都添加到 SSO 中,或者 http://uthing.comhttp://ething.com 使用 Authing 的同一个自建应用,当用户在某个站点登出后,另外一个站点的 Token 也会失效。

2.用户未登出的站点发起请求,当后台校验 Token 失败后,则下发清除 cookie 的命令并跳转默认页面提示用户已经登出,需要登录。

03 本章总结

本章我们介绍了 OIDC 授权码模式的接入流程以及相关接口的调用方式,对于小白来说可能需要整体跑一遍流程才能熟悉,我们也建议你 fork 我们的 postman collection 跑一遍流程,对授权码模式你就基本掌握啦。


接下来我们还会介绍 OIDC 的授权码+PKCE 流程,以及接入 Authing 的方式,需要你对授权码模式的流程有一定了解哦。

用户头像

Authing

关注

还未添加个人签名 2022-01-24 加入

还未添加个人简介

评论

发布
暂无评论
OIDC & OAuth2.0 认证协议最佳实践系列 02 - 授权码模式(Authorization Code)接入 Authing_低代码_Authing_InfoQ写作社区