# jAccount认证接入方法

# 开放式认证系统连接

开放式认证系统连接OpenID Connect(OIDC) (opens new window)是基于OAuth2.0 (opens new window) 的身份认证标准协议,OIDC使用OAuth2的授权服务器来为第三方客户端提供用户的身份认证,并把对应的身份认证信息传递给客户端,且可以适用于各种类型的客户端(比如服务端应用,移动APP,JS应用)。OIDC还完全兼容OAuth2,能实现应用服务的授权。OIDC本身是多个规范构成,已实现的规范内容包括认证接入和应用退出。

# 身份令牌

身份令牌(ID Token) (opens new window)是一个授权服务器提供的包含用户信息的JWT标准格式 (opens new window)的数据结构,使用客户密钥(client_secret)进行验证签名(verify signature)。

身份令牌的主要构成部分如下:

{
    "iss": "https://jaccount.sjtu.edu.cn/oauth2/",
    "sub": "test-user",                             //当前登录用户的 jAccount 账号,String 类型
    "aud": "s6BhdRkqt3",                            //请求的客户身份标识号 client_id,String 类型
    "nonce": "n-0S6_WzA2Mj",                        //申请 token 时客户端传递的 nonce 参数
    "exp": 1311281970,                              //过期时间,UNIX 时间戳
    "iat": 1311280970,                              //签发时间,UNIX 时间戳
    "name": "张三",                                  //当前登录用户姓名,String 类型
    "code": "123456",                               //当前登录账号默认身份学工号
    "type":"student"                                //当前登录账号默认身份类型,值域见附录 A.1
 }
1
2
3
4
5
6
7
8
9
10
11

TIP

登录账号身份类型值请参考附录

# 认证过程

# 概述

jAccount能够提供3种认证方式。前二种基于OIDC,后一种是基于授权码模式的用户信息(Profile)API认证方式。
OIDC是基于OAuth2.0的,因此OIDC的认证过程也是由OAuth2.0的几种授权过程延伸而来。jAccount基于OIDC能获取身份令牌和访问令牌的方法有:

  • 授权码认证模式:使用授权码授权过程获取身份令牌和访问令牌的认证方式;
  • 隐含认证模式:使用隐含授权过程获取身份令牌和访问令牌的认证方式。

基于授权码模式的用户信息(Profile)API认证方式,是基于OAuth2.0授权码授权过程的,通过获得访问令牌(Access Token),调用用户账号信息(Profile)API获取当前登录用户信息。相比基于OIDC的认证方式,该方式能获取多的用户信息,支持业务系统个性化登录需求。

# 使用授权码(Authorization Code)过程的 OIDC 认证模式

授权码认证模式是使用授权码授权过程获取身份令牌和访问令牌的认证方式,是OIDC的一种认证模式。这种模式的功能特点是:OAuth2.0在“客户端”与“服务提供商”之间,设置了一个授权层(authorization layer);“客户端”不能直接登录“服务提供商”,只能登录授权层,以此将用户与客户端区分开来;“客户端”登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。

授权码模式的认证流程(流程图见RFC6749 Figure 3 (opens new window))如下:
a) 用户访问客户端,客户端将用户导向认证服务器。
b) 用户选择是否给予客户端授权。
c) 假设用户给予授权,认证服务器先生成一个授权码,并返回给用户,认证服务器将用户导向客户端事先指定的“重定向URI”(redirect uri),同时附上一个授权码(code)。
d) 客户端收到授权码,附上早先的“重定向URI”,向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
e) 认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)或更新令牌(refresh token)。
f) 客户端验证身份令牌信息的完整性和正确性,并解析获取当前用户信息。

上述认证流程分为两个阶段:第一阶段授权服务器给予客户端一个授权码(步骤a-c);第二阶段客户端通过授权码获取身份令牌和访问令牌(步骤d-f)。在第三方应用按规定完成接入申请后,具备了基本权限的前提下,使用OAuth2.0的授权码模式完成用户身份认证。具体实现过程见以下示例。


示例 步骤a)客户端发起认证请求
GET /oauth2/authorize?response_type=code&scope=openid&client_id=s6BhdRkqt3&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
Host: jaccount.sjtu.edu.cn
1
2

参数要求

  • response_type:回复类型,应为“code”
  • scope:请求资源权限,应为“openid”
  • client_id:jAccount 成员站点的身份标识
  • redirect_uri:重定向地址
  • state:可选参数,应用用于维持请求和反馈间状态的参数,授权服务器在返回授权码时会原样返回该参数。

示例 步骤c)授权服务器授权回复
HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
1
2

参数解释

  • code: 当资源拥有者授权后,由授权服务器产生的授权码,该授权码有效期 1 分钟。
  • state:当应用请求时发送了 state 参数时,授权服务器必须返回该参数。

示例 步骤d)请求访问令牌(Access Token)
POST /oauth2/token HTTP/1.1
Host: jaccount.sjtu.edu.cn
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb&client_id=s6BhdRkqt3&client_secret=sexxsdded
1
2
3
4
5
6

参数要求

  • grant_type:授权模式,应为“authorization_code”。
  • code:上一步获取到的有效授权码。
  • redirect_uri:重定向地址,应与请求授权步骤保持一致。
  • client_id: 应用身份标识号,应和请求授权步骤保持一致。宜使用基本认证方式通过 Authorization 头传递。
  • client_secret:应用密钥。宜使用基本认证方式通过 Authorization 头传递。

示例 步骤e)授权服务器返回访问令牌
{
    "access_token":"9ddc5252fc612f0baa93a6df846555d8",
    "refresh_token":"132b92f45043281bd12572fde4124917",
    "id_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJzNkJoZFJrcXQzIiwiaXNzIjoiaHR0cHM6Ly9
qYWNjb3VudC5kZXYuc2p0dS5lZHUuY24vb2F1dGgyLyIsInN1YiI6InRlc3QtdXNlciIsImV4cCI6MTMxMTI4MTk3MCwiaWF0Ijo
xMzExMjgwOTcwLCJuYW1lIjoi5byg5LiJIiwiY29kZSI6IjEyMzQ1NiIsInR5cGUiOiJzdHVkZW50In0.J6ZZ03Kzqy4-7UKlSYr
uZkLMQMVLpfZehU0DM6gmylk",
    "token_type":"Bearer",
    "expires_in":1800
}
1
2
3
4
5
6
7
8
9
10

参数解释

  • access_token:访问令牌
  • refresh_token:刷新令牌,与访问令牌一一对应。当访问令牌过期后,可使用刷新令牌更新该访问令牌有效期。
  • expire_in:访问令牌有效时长,单位秒。
  • id_token:用户身份令牌,可以解析出当前登录用户基本信息(见身份令牌)。

# 基于隐含授权(Implicit)过程的 OIDC 认证模式

隐含授权模式是授权码模式的简化版,适用于使用javascript脚本在浏览器上实现的无服务器端的应用。相比授权码模式,应用在资源拥有者授权后将直接获得访问令牌,而不是授权码。该授权模式中授权服务器通过“重定向URI”来实现对应用的认证。考虑到本授权模式存在一些安全风险,在可以使用授权码模式授权的情况下,应当尽量避免使用隐含授权模式。

隐含模式的认证流程(流程图见RFC6749 Figure 4 (opens new window))如下:
a) 用户访问客户端,客户端将用户导向认证服务器。
b) 用户决定是否给于客户端授权。
c) 假设用户给予授权,认证服务器向客户端发送身份令牌(id token)、访问令牌(access token)以及更新令牌(refresh toke)。
d) 客户端验证身份令牌信息的完整性和正确性,并解析获取当前用户信息。
在第三方应用按规定完成接入申请后,具备了基本权限的前提下,使用OAuth2.0的隐含授权过程来完成用户身份认证。具体实现过程见以下示例:


示例 步骤 a) 客户端发起认证请求
GET /oauth2/authorize?response_type=id_token&scope=openid&client_id=s6BhdRkqt3&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1
Host: jaccount.sjtu.edu.cn
1
2

参数要求

  • response_type:回复类型,应为“id_token”
  • scope:请求资源权限,应为“openid”
  • client_id: jAccount 成员站点的身份标识
  • redirect_uri:重定向地址
  • state:可选参数,应用用于维持请求和反馈间状态的参数,授权服务器在返回授权码时会原样返回该参数。

示例 步骤c)授权服务器返回访问令牌和身份令牌
{
    "access_token":"9ddc5252fc612f0baa93a6df846555d8",
    "refresh_token":"132b92f45043281bd12572fde4124917",
    "id_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJzNkJoZFJrcXQzIiwiaXNzIjoiaHR0cHM6Ly9
qYWNjb3VudC5kZXYuc2p0dS5lZHUuY24vb2F1dGgyLyIsInN1YiI6InRlc3QtdXNlciIsImV4cCI6MTMxMTI4MTk3MCwiaWF0Ijo
xMzExMjgwOTcwLCJuYW1lIjoi5byg5LiJIiwiY29kZSI6IjEyMzQ1NiIsInR5cGUiOiJzdHVkZW50In0.J6ZZ03Kzqy4-7UKlSYr
uZkLMQMVLpfZehU0DM6gmylk",
    "token_type":"Bearer",
    "expires_in":1800
}
1
2
3
4
5
6
7
8
9
10

参数解释:

  • access_token:访问令牌
  • refresh_token:刷新令牌,与访问令牌一一对应。当访问令牌过期后,可使用刷新令牌更新该访问令牌有效期。
  • expire_in:访问令牌有效时长,单位秒。
  • id_token:用户身份令牌,可以解析出当前登录用户基本信息(见 6.2)。

# 基于授权码模式的用户信息(Profile)API 认证模式

本认证模式分为两个阶段:
a) 获取用户账号信息API访问令牌
b) 调用用户账号信息API,获取当前登录用户信息。

其中,步骤a)也是基于授权码授权模式的,获取访问令牌过程与使用授权码(Authorization Code)过程的 OIDC 认证模式的步骤a)至步骤e)基本一致,只是scope参数的范围是basic或essential而不是openid。获取到的结果将不再有id_token字段。
具体实现过程见以下示例:


示例 获取访问令牌
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
    "access_token":"2YotnFZFEjr1zCsicMWpAA",
    "token_type":" Bearer ",
    "expires_in":1800,
    "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA"
}
1
2
3
4
5
6
7
8
9
10

示例 调用用户信息API获取登录用户信息
GET https://api.sjtu.edu.cn/v1/me/profile?access_token=token HTTP/1.1
1

示例 请求结果展示(scope=basic)
{
    "id":{guid},            // jAccount 自身的唯一 id,用于关联用户当前和曾经拥有的全部身份
    "account":{string},     // jaccount, 账号名
    "name":{string},        // 真实姓名
    "kind":"canvas.profile" //数据对象类型,无业务意义
} 
1
2
3
4
5
6

# 应用登出

单点登录接口支持当前应用登出。其他已经通过jAccount认证登录的应用不自动同步登出。登出的具体实现过程见以下示例。

示例 应用登出

GET http://jaccount.sjtu.edu.cn/oauth2/logout HTTP/1.1
1

参数解释

  • client_id:(必填)jAccount 成员站点的身份标识
  • post_logout_redirect_uri:(必填)回调地址
  • state:提供时通过回调地址回传

# 附录

# 用户类型代码

代码 名称 代码 名称
faculty 教职工 external_teacher 外聘教师
student 学生 summer 暑期生
yxy 医学院教职工 team 集体账号
fsyyjzg 附属单位职工 alumni 校友
vip 贵宾 green 绿色通道
postphd 博士后 outside 合作交流

# 机构代码

对于需要限制登录人机构的可以参考查询机构代码API