阿里云IDaaS三方登录

1,248 阅读9分钟

统一门户功能

IDaaS的单点登录(Single Sign On,SSO)能力,可以为企业提供统一的门户。用户只需要认证登录一次,就可以访问所有集成了的应用系统。

这里主要调研了JWT和OAuth2.0两种协议模板方式对接。

JWT方式接入介绍

Json web token ( JWT ), 是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以 Json 对象的形式安全的传递信息,该 token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景

请求响应时序图:

实现原理:

SP 接收 IDaaS 平台向 callback url 发出的 id_token 参数(即 JWT 令牌),并使用我们提供的(或第三方提供的) JWT 解密库/方法对 JWT 进行解析,并验证身份。

1)用户通过浏览器登录 IDaaS ,并发起单点请求

2)IDaaS 生成 token 令牌发送到业务应用。

3)业务系统获取到 token 令牌,用我们提供的插件或方法解析 token 令牌,解析成功获取到用户信息并验证

验证通过:业务系统重定向到用户首页,

验证失败:业务系统拒绝登录并页面提示错误信息

第 1 步 创建 JWT 应用

1)登录 IDaaS 管理员平台

使用 IT 管理员账号登录云盾IDaaS管理控制台。具体操作请参考 IT管理员指南-登录

2)添加 JWT 应用

在【应用】-【添加应用】中,找到应用名称为: JWT,点击右边【添加应用按钮】

3)填写信息并保存

参数说明:

  1. 图标:业务应用的 logo 图片。

  2. 应用 ID: 自动生成应用 ID,且唯一。

  3. 应用名称: 填写创建应用的名称。

  4. 应用类型: 代表该服务支持的设备类型,标记使用。

  5. redirect_uri:业务系统中(或 PC 程序)的 JWT SSO 地址,在单点登录时 IDaaS 将向该地址用[GET]方式发送 ID_Token 信息,参数名为ID_Token,业务系统通过 ID_Token 与 Public Key 可获取业务系统中的用户信息,如果在业务系统(SP)发起登录,请求 SP 登录地址时如果携带 Service 参数 IDaaS 会检验合法性,成功后会将浏览器重定向到该地址,并携带ID_Token身份令牌。

  6. Target_link_uri: 业务系统中在 JWT SSO 成功后重定向的 URI,一般用于跳转到二级菜单等,若设置了该 URI,在 JWT SSO 时会以参数 Target_link_uri 优先传递该值,若未设置该值,此时若SSO中有请求参数。

7.是否包含用户角色:用于第三方权限系统对接,开启后会将账户的角色信息包含在 ID_Token 中。

8.SSO Binding:单点登陆请求方式,REDIRECT 为 GET 类型,也可选择 POST。

9.ID_Token有效期:单位秒。

10.是否显示应用:授权给用户后,是否在用户首页显示。默认开启,若关闭,用户登录将看不到该应用。

11.账户关联方式:

a.账户关联(系统按主子账户对应关系进行手动关联,用户添加后需要管理员审批)

b.账户映射(系统自动将主账户名称或指定的字段映射为应用的子账户)

4)导出公钥

完成上面应用创建,我们在【应用列表】中,就可以找到新创建的应用。点击【详情】按钮,点击【查看详情】。

找到 JWT PublicKey

复制粘贴到文本txt,或者使用下方导出,都可以将 JWT PublicKey 导出。将其交给第三方也系统,用作 ID_Token 解析。

第 2 步 SDK 下载

在这里,第三方业务系统就要开始研发的准备工作了。我们提供 4 种语言的 SDK 集成方式。

JAVA/PHP/.NET/Python ,当然,如果您的业务系统是其他语言也可以进行对接,需要您自行编写解析 ID_Token 的代码。可以参考:

JWT 官网

下载方式:

1)登录到 IDaaS 管理平台。登录操作,请参考 开发者访问方式

2)切换至【开发者】

3)点击【单点登录(SSO)】- 点击【单点登录(SSO)开发者文档】

4)在右侧导航栏最下方找到 【其他】-【相关下载】,按需下载即可

第 3 步 业务系统研发【重要】

研发核心思想:

1)能够接收到令牌

2)能够成功解析令牌,拿到 用户信息

3)匹配用户信息是否与当前自己的账号一致

4)跳转至用户首页

1)JAVA 插件式集成

配置环境

JDK 1.6 以上

接收令牌

// id_token 是 IDaaS 请求时带来的,在 body 里获取,PublicKey是在 IDaaS 里注册应用时生成的,注册完可见,此示例代码是获取用户信息。
// JWT SSO
@RequestMapping(value = “/JWT/sso/login”)
public String SSO Url(@RequestParam String id_token, String redirect_url, Model model, HttpServletRequest request){
  //1.接收方法为GET方式,参数名为 id_token
  //2.<解析令牌>为解析 id_token 并验证代码
}

解析令牌

PublicKey: 解析令牌的过程中,我们会使用到应用的 PublicKey。请在 JWT 应用 -> 详细 中将PublicKey字段对应的内容拷贝并存储起来。

//1.使用公钥,解析 id_token
// 使用PublicKey解密上一步获取的 id_token 令牌
DingdangUserRetriever retriever = new DingdangUserRetriever( id_token, PublicKey);
DingdangUserRetriever.User user = null;
try {
  //2.获取用户信息
  user = retriever.retrieve();} catch (Exception e) {
  LOG.warn(“Retrieve SSO user failed”, e);
  return “error”;
}
//3.判断用户名是否在自己系统存在isExistedUsername()方法为业务系统自行判断数据库中是否存在
if (isExistedUsername(user.getUsername())) {
  //4.如果存在,登录成功,返回登录成功后的页面
  User SPUser = userService.updateLoginTimes(user.getUsername());
  request.get session ().setAttribute(Http session SecurityContextRepository. SPRING_SECURITY_CONTEXT_KEY, saveSecurity( SP User));
  //5.如果注册时添加redirect_url,那么返回此自定义url页面if (StringUtils.isNotEmpty(redirect_url)) {
    return “redirect:” + redirect_url;
  }
  //6.否则返回系统默认操作页面
  return “redirect:../../index”;
} else {
  //7.如果不存在,返回登录失败页面,提示用户不存在
  model.addAttribute(“error”, “username { “ + user.getUsername() + “ } not exist”);
  return “error”;
}

OAuth2.0方式接入介绍

OAuth2是一个开放的资源授权协议,应用可以通过 OAuth 获取到令牌 access_token,并携带令牌来服务端请求用户资源。应用可以使用 OAuth 应用模板来实现统一身份管理。

请求时序图:

操作步骤

  1. 以IT管理员账号登录云盾IDaaS管理平台。具体操作请参考 IT管理员指南-登录
  2. 点击左侧导航栏应用 > 添加应用
  3. 选择OAuth2应用模板点击添加应用。
  1. 查看 OAuth2 应用详情, 获得 Client Id、Client Secret、Authorize URL.

    说明:如果您希望应用系统每次登录时,都需要强制到IDaaS进行认证,在调用的 Authorize URL 后加上 prompt=login 参数即可。

  2. 使用浏览器打开 Authorize URL, 使用授权的账户进行登录,登录成功后跳转到回调地址,从浏览器地址栏提取 code 参数的值.

  3. 使用 POSTMAN 发送 POST 请求到 https://{IDaaS_server}/oauth/token?grant_type=authorization_code&code={code}&client_id={client_id}&client_secret={client_secret}&redirect_uri={redirect_uri}

    • {IDaaS_server}需要替换为真实IDaaS服务器地址
      说明 IDaaS服务器地址获取方式:访问云盾IDaaS管理控制台,使用用户访问的Portal的地址
    • {code}需要替换为第 6 步中提取到的 code 参数的值。
      注意 Code 的值只能用一次
    • {client_id}、{client_secret}需要替换为第 5 步中获得的值
    • {redirect_uri} 需要替换为第 2 步添加 OAuth2 应用时输入的跳转值
  1. IDaaS服务器将会响应 access_token, 使用该值可访问 IDaaS服务器资源
  2. 使用 POSTMAN 发送 GET 请求到 https://{IDaaS_server} /api/bff/v1.2/oauth2/userinfo?access_token={access_token}
    说明 其中v1.2是版本,根据实际版本填写。如果js中没有写版本号,那么此处写v1;如果写了版本号,就写对应的版本号

具体接口

  1. Request URI: /oauth/token
    • 接口说明:获得 access_token
    • 请求参数
参数类型是否必选示例值描述
codestringvuQ3n6用户登录成功后回调传递的code值
client_idstringoauth2 client_idOAuth2 client_id
client_secretstringoauth2 client_secretOAuth2 client_secret
redirect_uristringexample.com重定向 url
    • 返回参数
参数类型示例值描述
access_tokenstring333ab704-abc0-48b3-8af0-496eedd15383Access Token
token_typestringbearerToken 类型
expires_instring7199Access Token 过期时间
scopestringread申请的权限范围
    • 错误码说明
HttpCode错误码错误信息描述
400invalid_grantInvalid authorization code: "code".无效的授权码
400invalid_grantRedirect URI mismatch.重定向 URI 不匹配
401UnauthorizedUnauthorized未授权的访问
403ForbiddenForbidden无权限访问
404ResourceNotFoundResourceNotFound访问的资源不存在
415UnsupportedMediaTypeUnsupportedMediaType不支持的媒体类型
500InternalErrorThe request processing has failed due to some unknown error, exception or failure.发生未知错误
  1. Request URI: /api/bff/v1.2/oauth2/userinfo
    • 接口说:获取用户详细信息
    • 请求参数
参数类型是否必选示例值描述
access_tokenstring333ab704-abc0-48b3-8af0-496eedd15383Access Token
    • 返回参数响应示例
{
"success": true,
"code": "200",
"message": null,
"requestId": "59C5766B-C7F9-4DF6-B5E4-0F2A89942749",
"data": {
    "sub": "4982789226325725762",
    "ou_id": "5920417439492153461",
    "nickname": "admin",
    "phone_number": null,
    "ou_name": "PG China",
    "email": "sz@xxxx.com",
    "username": "admin_wli"
  }
}
    • 参数说明
参数类型示例值描述
substring4982789226325725762账户的外部ID
usernamestringadmin_wli用户名
nicknamestringadmin显示名称
emailstringsz@xxxx.com邮箱
phone_numberstringnull手机号
ou_namestringPG China账户所属组织机构名称
ou_idstring5920417439492153461账户所属组织机构外部ID
    • 错误码说明
HttpCode错误码错误信息描述
401UnauthorizedUnauthorized未授权的访问
403ForbiddenForbidden无权限访问
404ResourceNotFoundResourceNotFound访问的资源不存在
415UnsupportedMediaTypeUnsupportedMediaType不支持的媒体类型
500InternalErrorThe request processing has failed due to some unknown error, exception or failure.发生未知错误

其它

1. 是否支持OAuth2退出

在登录接口增加proxmy参数, 当prompt=login则强制跳转登录页 , 也就是在下图 Authorize URL后面增加“&prompt=login ”

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 28 天,点击查看活动详情