OpenID Connect的认证与授权详解

OAuth 2.0是一种授权机制,用户通过授权服务器给第三方应用授权,以访问自己的资源(位于资源服务器)。相对于OAuth 1.0,OAuth 2.0简化了对客户端的验证,只保留了获取Authorization Code和Access Token的请求过程。

OpenID Connect是OAuth 2.0的一个扩展,结合OAuth 2.0的授权提供了用户的认证。

常见的认证方式

基于OAuth 2.0的认证/授权协议

复制代码
| 协议                                    | 说明                                        |
|-----------------------------------------|--------------------------------------------|
| OpenID Connect                          | OAuth 2.0 + 身份认证(ID Token)              |
| UMA (User-Managed Access)               | OAuth 2.0 + 授权管理(资源所有者控制访问策略)  |
| OAuth 2.0 Token Introspection           | OAuth 2.0 + 令牌验证标准(RFC 7662)           |
| OAuth 2.0 Dynamic Client Registration   | OAuth 2.0 + 动态客户端注册(RFC 7591)        |
| OAuth 2.0 Authorization Server Metadata | OAuth 2.0 + 服务发现(RFC 8414)              |

非OAuth 2.0的认证协议

javascript 复制代码
| 协议                  | 说明                  |
|-----------------------|----------------------|
| SAML 2.0              | XML格式,企业级 SSO |
| LDAP/Active Directory | 目录服务认证          |
| Kerberos              | 网络认证协议          |
| OpenID 1.0/2.0        | OAuth 2.0前身(已废弃) |

常见的Token格式

  • JWT(JSON Web Token)
  • Reference Token (随机字符串)
  • SAML Token(XML 格式)
  • MAC Token(OAuth 1.0专用,已废弃)

结合Authorization Code + PKCE的OpenID Connect的认证与授权

PKCE (Proof Key for Code Exchange),通过 code_verifier 和 code_challenge 确保只有原始客户端能获得Access Token。

客户端准备
javascript 复制代码
// 客户端生成 code_verifier 和 code_challenge
const code_verifier = generateRandomString(43);  // 43-128 字符
const code_challenge = base64UrlEncode(sha256(code_verifier));

// 保存 code_verifier(sessionStorage 或内存)
sessionStorage.setItem("code_verifier", code_verifier);
用户点击登录

客户端向认证/授权服务器发出HTTP请求如下:

javascript 复制代码
GET /authorize HTTP/1.1
Host: auth.server.com

response_type=code&
client_id=s6BhdRkqt3&
redirect_uri=https://client.example.com/callback&
scope=openid profile email&
state=af0ifjsldkj&
code_challenge=dGhpcyBpcyBhIGNoYWxsZW5nZQ&
code_challenge_method=S256
认证/授权服务器对用户进行认证/授权
  1. 认证/授权服务器显示登录页面
  2. 用户输入用户名/密码
  3. 认证/授权服务器验证凭证
  4. 认证/授权服务器显示授权页面(请求用户授权)
  5. 用户点击 "同意"授权

认证/授权服务器生成Authorization Code,并缓存code_challenge与Authorization Code的关联。

认证/授权服务器重定向

发出HTTP请求如下:

javascript 复制代码
HTTP/1.1 302 Found
Location: https://client.example.com/callback?
  code=SplxlOBeZQQYbYS6WxSbIA&
  state=af0ifjsldkj

返回一次性Authorization Code给客户端。

客户端换取令牌

发出HTTP请求如下:

javascript 复制代码
POST /token HTTP/1.1
Host: auth.server.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=SplxlOBeZQQYbYS6WxSbIA&
redirect_uri=https://client.example.com/callback&
client_id=s6BhdRkqt3&
code_verifier=dGhpcyBpcyBhIGNoYWxsZW5nZQ

使用一次性Authorization Code和code_verifier请求Token。

认证/授权服务器通过Authorization Code找到对应的code_challenge,然后验证code_verifier有效后,返回如下:

javascript 复制代码
{
  "access_token": "2YotnFZFEjr1zCsicMWpAA",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
  "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}

其中ID Token是给客户端使用验证用户身份的,根据OpenID Connect规范的要求必须采用JWT格式。

Access Token是给资源服务器鉴定用户的访问权限的,用于请求资源服务器,可以是JWT,也可以是Reference Token。JWT是自包含的,鉴权时无需调用认证/授权服务器;Reference Token的鉴权需要调用认证/授权服务器。Keycloak默认使用Reference Token。JWT是无状态、自包含的,签发后无法主动失效,只能等待过期失效。Reference Token可以根据需要随时注销。

ID Token和Access Token的有效期都较短。

Refresh Token有效期较长,缓存在Redis中,用于生成新的Access Token。Refresh Token过期后,需要重新认证。

客户端验证 ID Token
javascript 复制代码
// verify ID Token
const payload = verifyJwt(idToken, {
  issuer: "https://auth.server.com",
  audience: "s6BhdRkqt3",
  nonce: storedNonce,
  jwksUri: "https://auth.server.com/oauth/jwks"
});

// save to session
sessionStorage.setItem("user_id", payload.sub);
sessionStorage.setItem("user_name", payload.name);
sessionStorage.setItem("access_token", accessToken);

客户端会缓存ID Token,在必要的时候(如敏感请求、用户重新登录等)随时检查ID Token是否过期。ID Token过期后,可以使用Refresh Token请求新的ID Token,此时用户无需登录。

客户端使用Access Token访问资源服务器的资源

发出HTTP请求如下:

javascript 复制代码
GET /api/user/profile HTTP/1.1
Host: api.example.com
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
资源服务器向认证/授权服务器验证Access Token(仅Reference Token需要, JWT不需要)

JWT是自包含的,无需验证,但只能到期失效。Reference Token需要验证,但便于随时注销。

发出HTTP验证请求如下:

javascript 复制代码
POST /introspect HTTP/1.1
Host: auth.server.com
Authorization: Basic base64(api-client:secret)

token=2YotnFZFEjr1zCsicMWpAA

认证/授权服务器返回"active": true表示有效,示例如下:

javascript 复制代码
{
  "active": true,
  "scope": "profile email",
  "client_id": "s6BhdRkqt3",
  "username": "taiyangdao@example.com",
  "token_type": "Bearer",
  "exp": 1716123456,
  "iat": 1716120456,
  "sub": "123456789"
}
资源服务器看到有效Access Token,返回被请求的资源
javascript 复制代码
{
  "id": 123,
  "name": "taiyangdao",
  "email": "taiyangdao@example.com"
}
刷新Access Token

Access Token过期后,需要通过Refresh Token请求新的Access Token,HTTP请求如下:

javascript 复制代码
POST /token HTTP/1.1
Host: auth.server.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&
refresh_token=tGzv3JOkF0XG5Qx2TlKWIA&
client_id=s6BhdRkqt3&
client_secret=secret

认证/授权服务器返回如下:

javascript 复制代码
{
  "access_token": "new_access_token_xyz",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "new_refresh_token_xyz"
}

每次使用Refresh Token,都会创建新的Refresh Token,但是其有效期仍然从最初认证时间计算。如果Refresh Token过期,则用户必须重新登录。

相关推荐
玩AI的奶茶2 天前
从零到跑通:在算家云上部署大模型的完整操作手册(实例创建 / 镜像选择 / 远程连接 / 成本控制)
人工智能·ai·gpu算力·token·算力租赁
deepseek232 天前
MCP 2026-07-28 规范拆解:无状态协议核心怎么让 MCP 服务器跑在普通负载均衡后面
oauth·ai agent·mcp·无状态·协议规范
CSharp精选营2 天前
Blazor 里 JWT 过期,用户正下单就被踢
认证·jwt·webassembly·blazor·令牌刷新
信马堂2 天前
WorkBuddy 接入第三方模型 API 全流程:安装与配置实录
人工智能·大模型·token·ai算力·workbuddy
liangshanbo12153 天前
面试题:AI 产品里,前端怎么降低 Token 消耗?
token
xiangshangdemayi3 天前
Strata教程:让GISer真正实现了token自由
ai·gis·教程·token·strata·自由
网络毒刘5 天前
Token 用量观测实战:从会话结构拆前缀/工具/生成,建立个人降本仪表盘
人工智能·性能优化·token·cursor
网络毒刘8 天前
Token 账单的「隐形税」:系统提示、工具定义与历史滚动为何比生成贵
agent·token·cursor·成本·mcp
白帽攻防录9 天前
SRC 挖洞:WSO2 JWT 算法混淆绕过深度复盘,CVE-2026-5430 不支持的算法怎么变成管理员
网络·算法·安全·网络安全·jwt
算家云10 天前
doubao-seed-2-1 系列模型上架算桥 API | 多模态理解能力继续加强!
人工智能·api·token·算力租赁·算力平台