🎉 开放平台文档站换新颜。 欢迎填问卷给我们建议,意见,反馈,夸夸 →
Skip to Content

授权码模式

授权码模式(Authorization Code Flow)是OAuth 2.0和OpenID Connect(OIDC)中最安全、最常用的认证授权流程。本文档详细介绍Keycloak授权码模式的完整流程、参数配置和实现细节。

概述

授权码模式是一种重定向基础的流程,要求客户端能够与用户代理(通常是Web浏览器)交互,并且能够接收来自授权服务器的重定向请求。该模式特别适用于Web应用程序、移动应用和桌面应用。

核心特点

  • 安全性高:客户端永远不会直接处理用户凭据
  • 令牌交换:通过授权码换取访问令牌
  • 支持刷新令牌:可以获取长期有效的刷新令牌
  • OIDC兼容:支持获取ID令牌和用户信息

授权流程详解

Keycloak授权码模式包含以下几个关键步骤:

步骤1:构建授权请求

客户端将用户重定向到Keycloak的授权端点,携带必要的参数。

端点URL格式:

https://api.tongji.edu.cn/keycloak/realms/OpenPlatform/protocol/openid-connect/auth

请求参数:

参数必填说明示例值
response_type固定值code,表示使用授权码模式code
client_id所分配的client_idtest_login
redirect_uri授权完成后的回调地址https://dev.tongji.edu.cn/authorization-demo/
scope推荐请求的权限范围openid
state推荐防CSRF攻击的随机值abc123
kc_idp_hint使用的第三方登录器,为了用户体验请填写固定值tjiamtjiam

完整示例:

https://api.tongji.edu.cn/keycloak/realms/OpenPlatform/protocol/openid-connect/auth? response_type=code& client_id=test_login& redirect_uri=https://dev.tongji.edu.cn/authorization-demo/& scope=openid& state=34e17e87-8618-4d79-86db-136ca8400f25& kc_idp_hint=tjiam

步骤2:用户认证和授权

用户会被引导到开放平台的登录界面,完成认证以后会触发授权。

符合以下情况,则该授权页面不会弹出

  • 用户已经授权
  • 应用没有申请任何接口权限
  • 应用被允许无需弹出授权页面

步骤3:返回授权码

用户授权成功后,Keycloak将用户重定向到客户端指定的redirect_uri,并携带以下参数:

成功响应参数:

参数说明
code授权码,有效期很短
state原样返回客户端提供的state值

示例重定向URL:

https://dev.tongji.edu.cn/authorization-demo/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=abc123

错误响应参数:

参数说明
error错误代码(如access_deniedtemporarily_unavailable
error_description错误描述
state原样返回state值

步骤4:交换访问令牌

客户端使用收到的授权码向Keycloak令牌端点请求访问令牌。

端点URL:

https://api.tongji.edu.cn/v1/token

请求方式: POST Content-Type: application/x-www-form-urlencoded

请求参数:

参数必填说明
grant_type固定值authorization_code
client_id所分配的 client_id
client_secret所分配的 client_secret(大多数客户端需要)
code步骤3获得的授权码
redirect_uri必须与授权请求中的redirect_uri一致

示例请求:

curl -X POST \ https://api.tongji.edu.cn/v1/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code" \ -d "client_id=my-client" \ -d "client_secret=your-secret" \ -d "code=SplxlOBeZQQYbYS6WxSbIA" \ -d "redirect_uri=https://dev.tongji.edu.cn/authorization-demo/"

成功响应示例:

{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 300, "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_expires_in": 1800, "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "scope": "openid profile email", "session_state": "e48e5a57-86da-4cf5-8fc4-XXXXXX" }

成功响应参数:

参数名备注
access_token获得的token
expires_intoken的有效期
token_typetoken类型,现阶段只有Bearer类型Token
refresh_token用于刷新令牌
refresh_expires_inrefresh_token的有效期
scope申请的授权范围
not-before-policy现阶段无需关注
id_token现阶段无需关注

步骤5:使用访问令牌

获取访问令牌后,客户端再进一步获取用户信息。例如通过解析 id_token 获取用户名。或者请求具体的用户信息接口即可。

API请求示例:

curl -X GET \ https://api.tongji.edu.cn/v1/dc/user/single_info \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

令牌类型说明

访问令牌(Access Token)

  • 用途:访问受保护的API资源
  • 格式:JWT token
  • 有效期:默认2h,可申请配置
  • 验证:资源服务器需要验证令牌的有效性

ID令牌(ID Token)

  • 用途:包含用户身份信息
  • 格式:JWT
  • 包含信息:用户标识、认证时间、发行者等
  • 验证:客户端需要验证签名和声明

刷新令牌(Refresh Token)

  • 用途:获取新的访问令牌
  • 有效期:默认半年,可申请配置
  • 存储:需要安全存储
  • 使用:当访问令牌过期时使用

注意事项

授权服务器提供 access_token 的令牌签发,并确保令牌签发的过程中有用户的认证授权确认。会话应由应用端自行维护管理。尽管我们在授权码模式中,集成了 CAS 认证协议,并与学校其他 CAS 集成应用相兼容并支持 SSO。但 SSO 的会话仍然应该与应用本身的会话相独立,已经完成认证的用户应该由应用本身会话管理,避免不必要的认证触发行为。

当应用的会话有效期比较长时,可能需要刷新 token 以重新获取用户信息,此时可以使用 refresh_token 来刷新 token。

刷新令牌

当访问令牌过期时,可以使用刷新令牌获取新的访问令牌。

请求示例:

curl -X POST \ https://api.tongji.edu.cn/v1/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=refresh_token" \ -d "client_id=my-client" \ -d "client_secret=your-secret" \ -d "refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

响应示例:

{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 300, "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_expires_in": 1800, "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "session_state": "e48e5a57-86da-4cf5-8fc4-XXXXXX" }

获取用户信息

使用访问令牌调用用户信息端点获取用户详细信息。

端点URL:

https://api.tongji.edu.cn/keycloak/realms/OpenPlatform/protocol/openid-connect/userinfo

请求示例:

curl -X GET \ https://api.tongji.edu.cn/keycloak/realms/OpenPlatform/protocol/openid-connect/userinfo \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

响应示例:

{ "sub": "1234567890", "name": "John Doe", "preferred_username": "johndoe", "given_name": "John", "family_name": "Doe", "userid": "xxxx" }

登出

需要同时登出keycloak与同济大学统一身份认证(tjiam)

keycloak登出

重定向用户到登出端点:

https://api.tongji.edu.cn/keycloak/realms/OpenPlatform/protocol/openid-connect/logout? redirect_uri=https://dev.tongji.edu.cn/authorization-demo/

同济大学统一身份认证(tjiam)登出

使用刷新令牌进行后端登出:

https://iam.tongji.edu.cn/idp/profile/OAUTH2/Redirect/GLO? redirectToUrl=https://dev.tongji.edu.cn/authorization-demo& entity=client_id

错误处理

常见错误代码

错误代码描述解决方案
invalid_request请求缺少必需参数或参数无效检查请求参数格式和完整性
unauthorized_client客户端未授权使用此授权类型检查客户端配置
access_denied用户或授权服务器拒绝了请求提示用户重新授权
unsupported_response_type不支持的响应类型使用正确的response_type
invalid_scope请求的作用域无效使用有效的作用域
server_error授权服务器内部错误重试或联系管理员
temporarily_unavailable服务暂时不可用稍后重试

错误响应格式

重定向错误响应:

https://dev.tongji.edu.cn/authorization-demo/callback? error=access_denied& error_description=User%20denied%20the%20request& state=abc123

令牌端点错误响应:

{ "error": "invalid_grant", "error_description": "Invalid authorization code" }

实现示例

示例实现已开源(纯前端模式),可通过以下链接访问: 访问地址 项目源码