乐趣区

关于sso:SSO的通用标准OpenID-Connect

简介

OpenID Connect 简称为 OIDC,已成为 Internet 上单点登录和身份治理的通用规范。它在 OAuth2 上构建了一个身份层,是一个基于 OAuth2 协定的身份认证标准协议。

OAuth2 实际上只做了受权,而 OpenID Connect 在受权的根底上又加上了认证。

OIDC 的长处是:简略的基于 JSON 的身份令牌(JWT),并且齐全兼容 OAuth2 协定。

明天咱们将会介绍一下 OIDC 的具体原理。

OpenID Connect 是什么

OpenID Connect 公布于 2014 年,是建设在 OAuth 2.0 协定之上的简略身份层,它容许客户端基于受权服务器或身份提供商(IdP)进行的身份验证来验证最终用户的身份,并取得用户的相干信息。

OpenID Connect 提供了 RESTful HTTP API,并应用 Json 作为数据的传递格局。

之前咱们讲到了基于 XML 格局的 SAML 协定,而 OpenID Connect 因为其更加简洁的数据交换格局,被越来越多的利用应用,曾经成为事实上的规范。

咱们看一下 OpenID connect 的根本流程:

  1. RP(client) 发送一个认证申请到 OpenID Provider(OP)。
  2. OP 对 End User 进行认证并取得相应的受权。
  3. OP 返回一个 ID Token 或者 access Token 给 RP。
  4. RP 应用 access token 向 UserInfo Endpoint 申请用户信息。
  5. UserInfo Endpoint 返回相应的用户信息给 RP。

ID Token

ID Token 就像是一个用户的身份证,它是以 JWT 格局存在的,并且由 OP 进行签名,保障它的安全性。

获取 ID Token 的形式就是向 OP 发送认证申请。

因为 ID Token 是以 JWT 格局存在的,JWT 能够分为三个局部,别离是 Header,Payload 和 Signature。

这里咱们次要关注一下 Payload 的 json 内容:

{
  "sub"       : "alice",
  "iss"       : "https://openid.flydean.com",
  "aud"       : "client-12345",
  "nonce"     : "n-0S6_WzA2Mj",
  "auth_time" : 1311280969,
  "acr"       : "c2id.loa.hisec",
  "iat"       : 1311280970,
  "exp"       : 1311281970
}
  • sub = Subject Identifier:必须。iss 提供的 EU 的惟一标识;最长为 255 个 ASCII 个字符;
  • iss = Issuer Identifier:必须。提供认证信息者的惟一标识。个别是 Url 的 host+path 局部;
  • aud = Audience(s):必须。标识 ID-Token 的受众。必须蕴含 OAuth2 的 client_id;
  • nonce:RP 发送申请的时候提供的随机字符串,用来减缓重放攻打,也能够来关联 ID-Token 和 RP 自身的 Session 信息。
  • auth_time = AuthenticationTime:EU 实现认证的工夫。如果 RP 发送认证申请的时候携带 max_age 的参数,则此 Claim 是必须的。
  • acr = Authentication Context Class Reference:可选。示意一个认证上下文援用值,能够用来标识认证上下文类。
  • iat = Issued At Time:必须。JWT 的构建的工夫。
  • exp = Expiration time:必须。ID-Token 的过期工夫;

下面的是 ID Token 的规范 Claims。

申请 ID Token

当初咱们晓得了 ID Token 是什么,那么在 OpenID Connect 的 RP 客户端如何申请一个 ID Token 呢?

尽管 OpenID Connect 并未指定应如何理论验证用户身份,这取决于提供者来决定。然而咱们通常由 Web 浏览器来执行认证步骤。

浏览器将用户重定向到认证服务器的认证窗口,用户输出用户名和明码之后,通过 OAuth 2.0 协定申请 ID token。

应用 OAuth 2.0 来获取 ID Token 有 3 种形式:

  1. Authorization Code 模式

Authorization Code 流程的步骤如下:

客户端筹备身份认证申请,申请里蕴含所须要的参数

客户端发送申请到受权服务器

受权服务器对最红用户进行身份认证

受权服务得最终用户的对立 / 受权

受权服务器把最终用户发送回客户端,同时带着受权码

客户端应用受权码向 Token 端点申请一个响应

客户端接管到响应,响应的 Body 外面蕴含在和 ID Token 和 Access Token

客户端验证 ID Token,并取得用户的一些身份信息

  1. 隐式受权

上图就是一个隐式受权的例子,和 Authorization Code 模式不同的是,认证服务器返回的是一个 access token 片段,只有这个片段,咱们是无奈失去 access token 的。

这里咱们须要额定申请一次 client resource 服务器,服务器将会返回一个 script 脚本,通过这个脚本,咱们对 access token 片段进行解析,失去最终的 access token。

  1. 混合模式

混合模式比拟少用到,它是后面两种模式的混合,它容许从前端和后端别离获取 token 值。

ID Token 能够做什么

那么咱们拿到申请失去的 ID Token 能够做什么事件呢?

  1. 无状态 session,通过将 token 存储在浏览器的 cookie 中,咱们能够实现轻量级的无状态会话。

服务器端不须要存储会话信息,咱们只须要在服务器端对 token 进行验证即可。

  1. 能够将 token 传递给第三方,因为 token 自身并不是敏感信息,所以咱们能够将 token 传递给其余应用程序或者后端服务。
  2. 令牌交互,咱们能够通过 ID Token 去 IdP 服务器中申请 access token,从而起到了交互 token 的目标。

Open Connect 认证码受权的例子

这里咱们举一个应用认证码受权获取到 ID token 的例子。

  1. RP 通过重定向到 OpenID Provider 的 OAuth 2.0 认证终端,来初始化一个用户认证。

上面是一个重定向的例子:

HTTP/1.1 302 Found
Location: https://openid.flydean.com/login?
          response_type=code
          &scope=openid
          &client_id=s6BhdRkqt3
          &state=af0ifjsldkj
          &redirect_uri=https%3A%2F%2Fclient.flydean.com%2Fcb
  • response_type:因为咱们是认证码模式,这里抉择 code
  • scope:openid 示意申请的是 openid。
  • client_id:RP 的 client id,OP 通过这个 client_id 来辨认是否是可辨认的 RP。能够提前注册或者提前约定。
  • state:RP 生成的一个状态规范,次要为了避免攻打。
  • redirect_uri:认证结束之后,跳转的链接。

在 OP 端,将会检测是否曾经存在一个无效的用户 session,否则将会弹出用户登录界面,让用户登录。

登录胜利之后,client 将会重定向到 redirect_uri,并带上认证码:

HTTP/1.1 302 Found
Location: https://client.flydean.com/cb?
          code=SplxlOBeZQQYbYS6WxSbIA
          &state=af0ifjsldkj
  1. 应用 code 获取 ID token

下面返回的 code 只是一个两头产物,RP 须要将 code 提交给 OP 换取 ID token。

这次咱们间接应用一个后端的 POST 申请:

POST /token HTTP/1.1
Host: openid.flydean.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

grant_type=authorization_code
 &code=SplxlOBeZQQYbYS6WxSbIA
 &redirect_uri=https%3A%2F%2Fclient.flydean.com%2Fcb
  • grant_type:authorization_code 示意是受权码格局
  • code 就是下面一步取得的 code
  • redirect_uri 是 callback url

如果胜利,OP 会返回一个 JSON 对象,带有 ID token, access token 或者 refresh token:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc
    yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5
    NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ
    fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz
    AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q
    Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ
    NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd
    QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS
    K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4
    XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg""access_token": "SlAV32hkKG",
  "token_type": "Bearer",
  "expires_in": 3600,
}

其中 ID token 的格局是 JWT。

User Info

咱们获取到的 ID token 外面曾经蕴含了一些十分有用的 claims 信息。

事实上 ID Token 还能够蕴含其余的 user info 信息:

比方 name,profile,picture,email,gender,birthdate,phone_number,address 等等有用的信息。

咱们能够在 token 申请的时候增加上额定的 scope:

HTTP/1.1 302 Found
Location: https://openid.flydean.com/login?
          response_type=code
          &scope=openid%20email
          &client_id=s6BhdRkqt3
          &state=af0ifjsldkj
          &redirect_uri=https%3A%2F%2Fclient.flydean.com%2Fcb

比方下面的例子中,咱们增加了额定的 email 信息,那么 OP 将会在 token 中退出 email 选项。

比方:

{
   "sub"                     : "alice",
   "email"                   : "alice@wonderland.net",
   "email_verified"          : true,
   "name"                    : "Alice Adams",
   "given_name"              : "Alice",
   "family_name"             : "Adams",
   "phone_number"            : "+86 18888888888",
   "profile"                 : "https://flydean.com/users/alice"
}

本文作者:flydean 程序那些事

本文链接:http://www.flydean.com/openid-connect-startup/

本文起源:flydean 的博客

欢送关注我的公众号:「程序那些事」最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!

退出移动版