# 授权码模式
# 概述
OIDC是OpenID Connect的缩写,OIDC=Identity,Authentication+OAuth2.0。GOSP的认证中心基于OIDC实现。
授权码模式是一种混合模式,是目前功能最完整、流程最严密的授权模式。
它主要分为两个步骤:获取授权码Code和获取令牌access_token。
(A) 用户访问业务系统,业务系统判断用户是否登录,若未登录,将业务系统导向到认证中心。
(B)用户输入账号密码给认证系统。
(C)假设用户认证通过,认证服务器将用户导向业务系统事先指定的"重定向URI"(redirection URI),同时附上一个授权码“Authorization Code”。
(D)业务系统收到授权码,附上早先的"重定向URI",向认证服务器申请令牌access_token。这一步是在业务系统的后台的服务器上完成的,对用户不可见。
(E)认证服务器核对了授权码和重定向URI,确认无误后,向业务系统发放令牌。
具体过程如下图所示:
# 业务系统接入场景说明
# 登录页面
用户通过访问业务系统,业务系统302跳转到认证中心登录页面。
# 获取授权码Code
在认证系统的登录页面内输入用户名、密码等凭证信息后,系统调用认证中心的”获取Code“服务,获取“Authorization Code”,并且携带获取到的code重定向到该服务接口中定义的重定向URL。 此时,业务系统应在需要登录时重定向到认证中心的登录页面,并将redirect_uri参数指向登陆后的业务系统的后续处理页面。
# 获取令牌access_token
业务系统根据先前获取的“Authorization Code”,调用认证中心的”获取Token“服务,获取令牌access_token。 业务系统在access_token的有效期内,可以带着access_token跟GLINK进行交互,完成GLINK系统提供的组织、用户、角色、权限、流程(*)等业务功能。
# 更新令牌access_token
建议业务系统将access_token存放在用户相关的缓存内,一旦access_token过期,业务系统需使用“获取Token"服务获取一个新的访问令牌。
# 获取用户信息
当业务系统需要根据access_token获取用户信息时,可调用本接口获取GLINK平台用户中心的相关信息。
# 用户登出
当业务系统用户退出本系统时,可调用本接口实现身份注销。
# 校验token
当业务系统发起请求时,通过此接口验证token有效性。
# 撤销token
强制使token过期。
# 接口说明
# 获取授权码Code
# 请求路径:
/nepoch-oidc/authorize?response_type={response_type}&scope={scope}&client_id= {client_id}&state={state}&redirect_uri={redirect_uri}
# 请求方法:
GET
# 请求参数:
参数 | 是否必须 | 说明 |
---|---|---|
response_type 或 grant_type | 是 | 授权模式,值固定为 "code" |
client_id | 是 | 客户端ID,由授权中心提供(可向平台人员索取) |
redirect_uri | 是 | 重定向Uri,需进行URL编码,需要是已注册的回调地址。 |
scope | 是 | 值自定义选择一个或多个:openid、email、offline_access、profile" |
state | 否 | 可以指定任意值,认证中心会原封不动地返回这个值 |
# 返回信息:
名称 | 类型 | 字段名 | 描述 |
---|---|---|---|
授权码 | String | code | |
上一步的状态码 | String | state | 防止CSRF, XSRF |
# 示例
- 请求范例:
GET http://oidc.glink.glkyun.com/nepoch-oidc/authorize?response_type=code&scope=openid email offline_access profile&client_id=test01&state=xyz&redirect_uri=https://client.example.com/cb
- 响应范例:
https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
# 获取/更新令牌accessToken
# 请求路径:
/nepoch-oidc/token
# 请求方法:
POST
# 请求参数:
Content-Type: application/x-www-form-urlencoded
参数 | 是否必须 | 说明 |
---|---|---|
grant_type | 是 | 授权模式,第一次获取时为 "authorization_code" 或 "code",更新令牌时为"refresh_token" |
code | 条件 | 上一步获得的授权码,当授权模式为第一次获取"authorization_code"时必填。 |
refresh_token | 条件 | 刷新token,当授权模式为刷新令牌"refresh_token"时必填。 |
client_id | 是 | 客户端ID,由授权中心提供(可向平台人员索取) |
client_secret | 是 | 客户端SECRET,由授权中心提供(可向平台人员索取) |
redirect_uri | 是 | 重定向URI,且必须与上一步的该参数值保持一致 |
scope | 条件 | 申请的权限范围,不可以超出上一次申请的范围。如果省略该参数,则与上一次scope一致。比如" openid email offline_access profile" |
# 返回信息:
名称 | 类型 | 字段名 |
---|---|---|
access_token | String | 请求token |
token_type | String | token类型 |
refresh_token | String | 刷新token |
expires_in | Long | 过期时间 |
scope | String | 授权范围 |
id_token | String | 身份信息 |
# 示例
- 请求范例:
POST /nepoch-oidc/token
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
{
"grant_type":"authorization_code",,
"code": "SplxlOBeZQQYbYS6WxSbIA",
"client_id": "GONGWEN",
"client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"redirect_uri": "https://client.example.com/cb",
"scope": "openid email offline_access profile"
}
2
3
4
5
6
7
8
9
10
11
- 响应范例:
{
"access_token": "eyJraWQiOiJyc2ExIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJhZG1pbiIsImF6cCI6ImdsaW5rIiwiaXNzIjoiaHR0cDpcL1wvb2lkYy5nbGluay5nbGt5dW4uY29tXC9uZXBvY2gtb2lkY1wvIiwiZXhwIjoxNjE1OTY2MzQwLCJpYXQiOjE2MTU5NjI3NDAsImp0aSI6IjhlNzZmZWYzLWY2YTktNGI0Yy04ZWVkLTg5ZTJjMTExNWYyZCJ9.TYbUmuhSQfiULjkb0vNLTwNCe4gSMjn_U_UlkH7AK6LaC7tO7tzrNL_IsfabzXCRWj3MG8z1jGIaTWbG0D0892HdTIft7abtvXNGcUUgyGonjkg6_AUr9rLzhyYIr9M8ctK6L6TK-8qnKva8mqfYIWlFIrbtjCTVMiPBEp6fnjk-HtFiL5mgJwkmm44qum-8tDw66WeAJ09nxGgtBNhVjqtKa-L74R0C6dSTQc5qpiszgdQ6vpd3VrY7P6j7qgQ63W2T9_yb24TigmhSQWOopVlbIDI5_Mou6koQBPTuebYxok3Jukcr1q763biwzmiMvhvHXMCn4eVyf9MOxfKm4Q",
"token_type": "Bearer",
"refresh_token": "eyJhbGciOiJub25lIn0.eyJqdGkiOiJiOTI5YTNlZC0yMTU4LTQ0ZTMtYTY2MC00NzAyODc3M2VlMWIifQ.",
"expires_in": 3599,
"scope": "openid offline_access profile email",
"id_token": "eyJraWQiOiJyc2ExIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJhZG1pbiIsImF1ZCI6ImdsaW5rIiwiYXV0aF90aW1lIjoxNjE1OTYyMjMyLCJraWQiOiJyc2ExIiwiaXNzIjoiaHR0cDpcL1wvb2lkYy5nbGluay5nbGt5dW4uY29tXC9uZXBvY2gtb2lkY1wvIiwiZXhwIjoxNjE1OTYzMzQwLCJpYXQiOjE2MTU5NjI3NDAsImp0aSI6IjU0NmM2MDIwLTdiYmUtNDFmYi05Yzk0LWNjNjAyNDQ5NThmZSJ9.ChT8HLgtOSW_biP0HV0nf0p0d9R69YFV5I8ZnFPglk2XBsyDQyiGinu6aV8ModnXmQsaRPEiIExMXgxOJLwiRvrju3xaRG6A4-_h5dl2JJYpFEYG3ALwuchs_dBqMFRSqZCMbwaksXkrn9Uj681jcZ6vUAGbNpCCk7dBUU0ZUCnP8DqWP45UIjg_bF4y18qBkedaMZvnXjHrRXYCy01Gk5Wyj_qzE8fj6JR8iDm8L1_Pj_kWblVLxBng7BdBwcV0ZqiUpfoqc-Nqe51gg2nASnYwmhq4ITODnvboUaDrOdc4JC-vRE7krkHWuA_NRWLROapJj3Ru3wP3CtDLi_4BDg"
}
2
3
4
5
6
7
8
# 获取用户信息
业务系统可以根据access_token获取用户基本信息。
# 请求路径:
/nepoch-oidc/userinfo
# 请求方法:
GET
# 请求参数:
Authorization:Bearer {access_token}
参数 | 是否必须 | 说明 |
---|---|---|
access_token | 是 | 请求token |
# 返回信息:
名称 | 类型 | 字段名 |
---|---|---|
sub | String | 用户登录账号 |
name | String | 姓名 |
userId | String | 用户id |
account | String | 账号 |
String | 邮箱 | |
mobilephone | String | 手机号 |
sex | int | 性别 |
# 示例
- 请求范例:
GET /nepoch-oidc/userinfo HTTP/1.1
Host: server.example.com
Authorization: Bearer czZCaGRSa3F0MzpnWDFmQmF0M2JW
2
3
- 响应范例:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"sub": "admin",
"name": "管理员",
"email": "540381107@qq.com",
"userId": "1",
"account": "admin",
"subjectid": "1",
"username": "管理员",
"mobilephone": "18392387159",
"code": "admin",
"sex": 1,
"deptid": " ",
"deptname": " ",
"alias": "null"
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 用户登出
实现身份认证注销。
# 请求路径:
/nepoch-oidc/endsession?post_logout_redirect_uri={post_logout_redirect_uri}&id_token={id_token}
# 请求方法:
GET
# 请求参数:
参数 | 是否必须 | 说明 |
---|---|---|
id_token | 是 | 业务系统从认证中心获取的原始id_token,参见/nepoch-oidc/token接口的返回字段说明 |
post_logout_redirect_uri | 是 | 注销跳转地址 |
# 返回信息:
跳转到post_logout_redirect_uri的地址
# 请求范例:
GET
nepoch-oidc/endsession?post_logout_redirect_uri=https://www.baidu.com&id_token_hint=eyJraWQiOiJyc2ExIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiI5MDM0Mi5BU0RGSldGQSIsImF1ZCI6ImxpdXpoYW8iLCJraWQiOiJyc2ExIiwiaXNzIjoiaHR0cDpcL1wvbG9jYWxob3N0OjgwODBcL25lcG9jaC1vaWRjXC8iLCJleHAiOjE2MTQ1ODg1OTAsImlhdCI6MTYxNDU4Nzk5MCwianRpIjoiMWJlZmM5ZGItM2M0Yy00MmYyLTkwMzUtNjA1YmI1YjI0Y2RhIn0.MpFuRMoi5SMhrSNvKaLoDce42ewT4Ltr7BKBPCcLix47qdOJKWKnCpcgetYGKQjQUAhzLM9K5EMGJeyrHNwR09A1er_XtR8Kwo7E-6_duUyfa-g07GpM7cnt-Zv6iKuxbyjdH3dDP2AgxljbF3B-zDEOnxc_4w_0fpOI7cXHkS2HoE7u0koRX15_-LWrDVi9WnihMqcGx0xYN-rKbPz6HxKJy2AfJ5xJsi_T7J5m2DvpYyMPtSxB6mI7_wd15fnfYxfgdWgX1ksGuq8MBAYPVIBE3LVg6Er6Q8ce1wJ_3gIfq9f3JGw14q9GAz_4fOuOFx8qISVWqyUHhDk0RhcmyQ
2
# 示例
- 响应范例:
跳转到 https://www.baidu.com
# 校验token
校验token
# 请求路径:
/nepoch-oidc/jwk
# 请求方法:
GET
# 请求头参数:
Authorization:Bearer {access_token}
参数 | 是否必须 | 说明 |
---|---|---|
access_token | 是 | 请求token |
# 请求范例:
GET
nepoch-oidc/jwk
2
# 示例
- 校验通过响应范例:
{
"keys": [
{
"kty": "RSA",
"e": "AQAB",
"kid": "rsa1",
"alg": "RS256",
"n": "qt6yOiI_wCoCVlGO0MySsez0VkSqhPvDl3rfabOslx35mYEO-n4ABfIT5Gn2zN-CeIcOZ5ugAXvIIRWv5H55-tzjFazi5IKkOIMCiz5__MtsdxKCqGlZu2zt-BLpqTOAPiflNPpM3RUAlxKAhnYEqNha6-allPnFQupnW_eTYoyuzuedT7dSp90ry0ZcQDimntXWeaSbrYKCj9Rr9W1jn2uTowUuXaScKXTCjAmJVnsD75JNzQfa8DweklTyWQF-Y5Ky039I0VIu-0CIGhXY48GAFe2EFb8VpNhf07DP63p138RWQ1d3KPEM9mYJVpQC68j3wzDQYSljpLf9by7TGw"
}
]
}
2
3
4
5
6
7
8
9
10
11
- 校验不通过响应范例
{
"error": "invalid_token",
"error_description": "Invalid access token: eyJraWQiOiJyc2ExIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJyempyIiwi3lzdGVtSWQiOiJudWxsIiwiYXpwIjoicnpqciIsImlzcyI6Imh0dHA6XC9cL29pZGMuZ2xpbmsuZ2xreXVuLmNvbVwvbmVwb2NoLW9pZGNcLyIsImV4cCI6MTY2MjYzMzcxNSwiaWF0IjoxNjYyNjMwMTE3LCJqdGkiOiIyZWM1Yzc2NC1mMmY1LTQxMjgtYTQwNS0zMDIzOTc5MTlkZmUifQ.UJQYNKOmquNFCrEoSRPpTwW3DMl9yHzRTeKg89VsL0ohu6j7dzEyrYrP4gtG-NtTFdmc38O9M8Cv-MZIu0Ha_Uc6-QAQSreEN-eyY9j9dnh1ILH40z5yld4iDzeBMHWcXtI1GnXi67eXp6yUckz-BqdgZ5M34dr_Ccx52TMYwYpa9d8onvRdyc1icKOPmg5BKMLCgUF9q56oGCATQa-tWl0qKg0pxfYevjj7mhJhtXEicqnqsOU8YirD295Dpl8R0L3erx0g_iD2yZGd8Xc4MFTXGN8aqxXfxocwSydZ9P8PJszy-ix0qNd5trY812KMMm7HrU4jED3d1wahw8Ao-Q"
}
2
3
4
# 撤销token
撤销token
# 请求路径:
/nepoch-oidc/revoke
# 请求方法:
GET
# 请求头
"Authorization": "Basic client-id:client-secret"
# 请求参数:body
参数 | 是否必须 | 说明 |
---|---|---|
token | 是 | 请求token |
# 响应示例
- 撤销成功响应范例:
状态码 200
- 撤销失败响应范例
状态码 401
{
"error": "unauthorized",
"error_description": "Bad credentials"
}
2
3
4
5