结论:授权码模式五步:1)客户端把用户重定向到授权服务器(带 client_id、redirect_uri、state、PKCE 的 code_challenge);2)用户登录并同意授权;3)授权服务器 302 回 redirect_uri 附带一次性 code;4)客户端后端用 code + client_secret + code_verifier 向授权服务器换 access_token(+refresh_token);5)用 token 访问资源。code 这层把"用户授权"与"发令牌"解耦,token 不再经过浏览器地址栏/历史/Referer 泄露。

展开:为什么需要 code:早期 implicit 模式直接在前端回调里发 token,token 出现在 URL fragment,可能经第三方 JS、浏览器扩展、日志泄露;code 本身单独拿到没用——兑换需要 client_secret(机密客户端)或 PKCE verifier(公开客户端),且一次性、短时效、绑定 redirect_uri。安全细节三连:1)state 参数防 CSRF——客户端生成随机 state,回调校验一致,防止攻击者把自己的 code 塞给受害者登录成攻击者账号;2)PKCE 防授权码截获——移动端/SPA 没有 secret,用动态生成的 verifier/challenge 绑定发起者与兑换者,如今所有客户端都该用;3)redirect_uri 必须精确匹配白名单,开放重定向是 code 被盗的经典路径。易错点:access_token 放 localStorage 有 XSS 窃取风险,高安全场景用 BFF(后端持 token,前端只持 HttpOnly Cookie 会话)。

追问方向:OIDC 在 OAuth2 上加了什么(id_token 与身份声明)、refresh token rotation 如何检测令牌被盗。