身份认证
授权模式
客户端模式(client credentials)
描述:OAuth2 客户端模式进行授权
请求方法:POST
请求地址:https://api.tongji.edu.cn/v1/token
请求参数,参数格式为application/x-www-form-urlencoded:
参数名 | 是否必填 | 备注 |
---|---|---|
client_id | 是 | 所分配的client_id |
client_secret | 是 | 所分配的client_secret |
grant_type | 是 | 必须是client_credentials |
返回参数:
参数名 | 备注 |
---|---|
access_token | 获得的token |
expires_in | token的有效期 |
token_type | token类型,现阶段只有Bearer类型Token |
scope | 申请的授权范围 |
not-before-policy | 现阶段无需关注 |
请求示例:
curl --location --request POST 'https://api.tongji.edu.cn/v1/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=xxb-example-api' \
--data-urlencode 'client_secret=3fwowzYYEgcCci1p7UPUtqgg9xdiWejv' \
--data-urlencode 'grant_type=client_credentials'
以上的clientid和secretid是真实存在的,各位可以亲自上手测试一番,使用该账户获得的token访问测试专用的fake_api系列的接口
响应示例:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIwOG0wVG5rb3M0QWVyaVE2Q0hiNUt0TGNXbDN6R0MtS2ZPbG5UYjVqRTF3In0.eyJleHAiOjE2NjM2NzE5MDIsImlhyyyyyyyyyyyyyyyyyy.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"expires_in": 7200,
"not-before-policy": 0,
"refresh_expires_in": 0,
"scope": "fake_api",
"token_type": "Bearer"
}
授权码模式(Authorization code)
描述:OAuth2 授权码模式进行授权
使用授权码模式,将先通过一次用户的身份认证与授权,经用户确认后方能获得 token。
下面这个程序是授权码模式的一个例子。这个例子是纯前端模式,和下面的介绍的流程在d)步骤上稍有不同,请充分理解二者区别。
https://api.tongji.edu.cn/app/authorization_demo/
源码整理之后,开源放出。
OIDC 认证协议
OpenID Connect 是基于 OAuth2.0 的身份认证标准协议,并且还完全兼容 OAuth2,可同时实现对应用服务接口的授权。OIDC本身是多个规范构成,目前实现的是认证接入的 JWT 部分。其他部分正在开发中,敬请期待。
身份令牌
身份令牌,也就是 ID Token 是由身份认证服务返回的,包含用户基本信息的 JWT 令牌。下文中Token和令牌代表同一含义。
身份令牌的 payload 可能用户需要感知的主要构成部分如下:
{
"exp": 1663754580, // 到期时间
"iat": 1663750380, // 签发时间
"typ": "Bearer", //类型
"azp": "test_login", //client_id
"scope": "openid dc_user_single_info", //scope 也就是授权的接口
"userid": "20666093" //所认证的学工号
}
认证流程
当集成身份认证时,采用的即为 OAuth2.0 授权码模式的认证流程,详见[RFC6749-section-4.1 ,流程大抵如下:
- a) 用户访问客户端,客户端将用户导向认证服务器。
- b) 用户进行身份认证,并选择是否给予客户端授权。
- c) 假设用户给予授权,认证服务器先生成一个授权码(code),并返回给用户,认证服务器将用户导向客户端事先指定的“重定向URI”(redirect uri),同时附上一个授权码(code)。
- d) 客户端收到授权码,附上早先的“重定向URI”,向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。如果用户拒绝授权,仍然会导向“重定向URI”,但是不带有code(而是带有一个值为”access_denied”的error参数),所以客户端要加入用户拒绝授权情况下的回调逻辑。
- e) 认证服务器核对了授权码和重定向URI,确认无误后,向客户端返回访问令牌。
- f) 客户端可解析令牌中的
userid
数据获取用户名信息,或者使用令牌调用有权限的接口,以获得更多用户相关信息。
a-c) 发起认证请求
用户侧发起请求,重定向到认证服务的 Authorization Endpoint(即 https://api.tongji.edu.cn/keycloak/realms/OpenPlatform/protocol/openid-connect/auth) ,并携带相关参数
请求参数和示例
参数名 | 是否必填 | 备注 |
---|---|---|
redirect_uri | 是 | 回调地址 |
response_type | 是 | 必须是 code |
client_id | 是 | 所分配的client_id |
kc_idp_hint | 是 | 使用的第三方登录器,为了用户体验请填写固定值tjiam |
state | 否 | 随机数,预防 cors 供给,建议加上 |
scope | 否 | 本次认证需要申请的scope |
https://api.tongji.edu.cn/keycloak/realms/OpenPlatform/protocol/openid-connect/auth?client_id=test_login&redirect_uri=https%3A%2F%2Fapi.tongji.edu.cn%2Fapp%2Fauthorization_demo%2F&state=34e17e87-8618-4d79-86db-136ca8400f25&response_mode=fragment&response_type=code&scope=openid&nonce=f8538cd9-1c38-47de-8f80-aed1385394df&kc_idp_hint=tjiam
认证授权
用户会被引导到开放平台的登录界面,完成认证以后会触发授权。
符合以下情况,则该授权页面不会弹出
- 用户已经授权
- 应用没有申请任何接口权限
- 应用被允许无需弹出授权页面
返回参数和示例
参数名 | 备注 |
---|---|
code | 所返回的 code |
state | 请求时附加的随机数,原样带回 |
d-e) 换取 Token 请求方法 POST 请求地址 https://api.tongji.edu.cn/v1/token 请求参数
参数名 | 是否必填 | 备注 |
---|---|---|
grant_type | 是 | 必须是 authorization_code |
client_id | 是 | 所分配的 client_id |
client_secret | 是 | 所分配的 client_secret |
code | 是 | 上一步获取到的code |
redirect_uri | 是 | a-c)步骤中,填入的回调地址 |
返回参数
参数名 | 备注 |
---|---|
access_token | 获得的token |
expires_in | token的有效期 |
token_type | token类型,现阶段只有Bearer类型Token |
refresh_token | refresh_token |
refresh_expires_in | refresh_token的有效期 |
scope | 申请的授权范围 |
not-before-policy | 现阶段无需关注 |
id_token | 现阶段无需关注 |
session_state | 现阶段无需关注 |
f) 获取用户信息 获取到 token 以后,客户端再进一步获取用户信息。例如通过解析 id_token 获取用户名。或者请求具体的用户信息接口即可。
注销
调用登出链接,回掉地址redirect_uri请自行填写 https://api.tongji.edu.cn/keycloak/realms/OpenPlatform/protocol/openid-connect/logout?redirect_uri=https%3A%2F%2Fapi.tongji.edu.cn%2Fapp%2Fauthorization_demo%2F
会话与用户授权管理
授权服务器提供 access_token 的令牌签发,并确保令牌签发的过程中有用户的认证授权确认。会话应由应用端自行维护管理。尽管我们在授权码模式中,集成了 CAS 认证协议,并与学校其他 CAS 集成应用相兼容并支持 SSO。但 SSO 的会话仍然应该与应用本身的会话相独立,已经完成认证的用户应该由应用本身会话管理,避免不必要的认证触发行为。
当应用的会话有效期比较长时,可能需要刷新 token 以重新获取用户信息,此时可以使用 refresh_token 来刷新 token。
授权码模式的应用,可以申请用户授权状态管理的接口,从而自行修改或更新用户的授权状态。详细情况待建设。
资源拥有密码模式(Resource Owner Password Credentials)
建设中
使用令牌调用接口
除了元数据字典接口,或者接口有特殊说明以外,所有接口的调用均需要携带所申请的令牌,即access_token才可调用成功。
在接口——支持的模式中,我们列出了接口所支持的授权模式,请使用该接口所支持的模式来申请access_token。 使用 access_token 调用数据时,请遵循以下格式:
https Header携带token
放在 https Header 的 Authorization 中,增加 Bearer为前缀。
调用示例,注意其中的Authorization: Bearer后面的token请替换成自己的有效access_token:
curl --location --request GET 'https://api.tongji.edu.cn/v1/fake_api/user' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIwOG0wVG5rb3Myyyyyyyyyyyyyyyyyyyyyyyyyyyyyy.RAHD9atu93SMiDNbeIziGBgbOTCPAHPMxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
令牌有效期说明
- client credentials 模式下可以允许同时申请多个 access_token
- 默认有效期:
access_token
默认有效期为7200秒(2小时)。如果有需求更长的有效期可以联系我们进行特殊申请 - 缓存建议:请在应用侧缓存
access_token
,避免频繁申请导致接口速率限制或临时封禁。 - 失效处理:当
access_token
过期或无效时(返回错误代码401),应用侧应该实现 access_token 失效时重新申请的策略。可以根据返回的错误代码判断,当代码为401时表示access_token过期或者无权限访问。此时应用应当尝试重新申请token。
刷新令牌
待定