简介
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 的根本流程:
- RP(client) 发送一个认证申请到 OpenID Provider(OP)。
- OP 对 End User 进行认证并取得相应的受权。
- OP 返回一个 ID Token 或者 access Token 给 RP。
- RP 应用 access token 向 UserInfo Endpoint 申请用户信息。
- 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 种形式:
- Authorization Code 模式
Authorization Code 流程的步骤如下:
客户端筹备身份认证申请,申请里蕴含所须要的参数
客户端发送申请到受权服务器
受权服务器对最红用户进行身份认证
受权服务得最终用户的对立 / 受权
受权服务器把最终用户发送回客户端,同时带着受权码
客户端应用受权码向 Token 端点申请一个响应
客户端接管到响应,响应的 Body 外面蕴含在和 ID Token 和 Access Token
客户端验证 ID Token,并取得用户的一些身份信息
- 隐式受权
上图就是一个隐式受权的例子,和 Authorization Code 模式不同的是,认证服务器返回的是一个 access token 片段,只有这个片段,咱们是无奈失去 access token 的。
这里咱们须要额定申请一次 client resource 服务器,服务器将会返回一个 script 脚本,通过这个脚本,咱们对 access token 片段进行解析,失去最终的 access token。
- 混合模式
混合模式比拟少用到,它是后面两种模式的混合,它容许从前端和后端别离获取 token 值。
ID Token 能够做什么
那么咱们拿到申请失去的 ID Token 能够做什么事件呢?
- 无状态 session,通过将 token 存储在浏览器的 cookie 中,咱们能够实现轻量级的无状态会话。
服务器端不须要存储会话信息,咱们只须要在服务器端对 token 进行验证即可。
- 能够将 token 传递给第三方,因为 token 自身并不是敏感信息,所以咱们能够将 token 传递给其余应用程序或者后端服务。
- 令牌交互,咱们能够通过 ID Token 去 IdP 服务器中申请 access token,从而起到了交互 token 的目标。
Open Connect 认证码受权的例子
这里咱们举一个应用认证码受权获取到 ID token 的例子。
- 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
- 应用 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 的博客
欢送关注我的公众号:「程序那些事」最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!