写在前面
本文来一起看下OIDC(openid connect)相关内容。
1:什么是OIDC
OIDC的全称是openid connect,和OAuth2.0一样,也是属于协议和规范的范畴。OAuth2.0是一种授权协议,即规定了what you can do
的内容。而OIDC是OAuth2.0的超集,不仅规定了what you can do
,还定义了who you are
的内容,即OIDC不仅是授权协议,也是一种认证协议。实际上,OIDC也正是在OAuth2.0的基础上做了扩展,从而支持了身份认证的功能,如下图:
为了更加容易理解OIDC,我们先来回一下OAuth2.0所包含的4个角色:
1:受保护资源的拥有者
一般是我们自己
2:受保护的资源
一般就是HTTP的接口形式的API,当然也可以是其他形式
3:三方软件
一般是希望拿到受保护资源的角色
4:授权服务器
给客户端完成授权的角色
OIDC要做的事情是用户通过认证服务器来证明自己的身份,从而访问三方服务
,所以OIDC包含如下3个角色:
用户:规范中叫End User,即EU
认证服务器:规范中叫OpenID Provider,即OP
三方服务:规范中叫relying party,依赖方,即RP
如果要把OAuth2.0的四个角色和OIDC的3个角色做对比的话,可以按照下面这种关系来理解:
接下来我们来看下OIDC规范中定义的流程,就会更加明白它就是在OAuth2.0的基础上做了认证相关的扩展了:
是不是和OAuth2.0的流程基本上完全一样,除了code换取令牌时多了id_token,而这里的id_token也正是实现用户认证的关键所在,因为要使用其来标记用户的登录态
,所以如下的信息是必须设置的:
* iss,令牌的颁发者,其值就是身份认证服务(OP)的 URL。
* sub,令牌的主题,其值是一个能够代表最终用户(EU)的全局唯一标识符。
* aud,令牌的目标受众,其值是三方软件(RP)的 app_id。
* exp,令牌的到期时间戳,所有的 ID 令牌都会有一个过期时间。
* iat,颁发令牌的时间戳。
如下代码:
String iss = "http://localhost:8899/auth";
String sub = userId;
String aud = appId;
Date exp = new Date(System.currentTimeMillis() + 10000);
Date iat = new Date((System.currentTimeMillis()));
String idToken = JwtUtils.generateIdTokenJwt(iss, sub, aud, exp, iat);
RP在获取到id_token之后,就可以获取到其中的用户关键信息,来标记用户的登录态了。
接着我们来看下如何使用OIDC来实现SSO。
2:SSO
使用OIDC实现SSO的流程如下:
其中,如果是认证服务判断用户已经登录,就不会要求用户重新登录了,而只是回调code,让RP获取ID_token和access_token,这也是实现SSO的关键所在。
2.1:SSO实战
源码 。
以下点需要注意:
1:简单起见,RP,OP都放在一个项目中了,工程上他们应该是独立的项目
2:例子中有RP,也是在一个项目中的,工程上他们也应该是独立的项目
3:简单起见,省略了在OP中注册RP的步骤,注册是为了获取合法的客户端标识app_id,app_secret等,这和授权是一样的。工程上OP需要提供这样的注册功能
4:简单起见,OP中省略很多很多的安全性校验,比如app_id的校验,回调地址的合法性校验等,工程上,这些校验必不可少,一定要注意
首先我们访问第一个RP:http://localhost:8899/app1/index
:
点击:
点击登录:
成功登录,此时我们还会将sub信息记录到浏览器中(记录的是用户id)
,这样下次访问时RP就可以咨询OP当前用户是否登录了:
当然,具体如何记录登录态
的信息,你可以根据具体的情况来处理,不一定非得这样子实现。
好,接着我们再来访问RP 2http://localhost:8899/app2/index
:
此时直接就访问了,而不需要重新登陆。
当然,如果是将localstorage中的内容删除的话,就又要重新登陆了:
写在后面
参考文章列表
如何通过 OIDC 协议实现单点登录?[通俗易懂]
多知道一点
联合登陆,单点登录
比如你开发了一个三方软件,希望使用微信,微博,等来直接登录,就叫做联合登录。
比如你公司有n个系统,这n个系统是一家子的,你希望在其中任何一个系统中登录之后,再去访问其他的任何一个系统都不需要登录,这种功能或者是效果就叫做单点登录。
其实联合登录和单点登录是很相似的,比如联合登录需要你到比如微信的OP来验证微信的的登陆状态,而单点登录是需要你输入你在自己的系统中注册的用户名密码信息,然后到自己的OP中验证用户名密码从而完成登录。
进一步看,二者都可以分为两种情况来分析:
- 未登录时
联合登录:会跳转到微信,让你登录微信
单点登录:会弹出自己家的登录页面,让你输入用户名密码登录
- 已登录时
联合登陆:微信会问你是否允许授权登录,你同意就登陆了
单点登录:因为是自家的应用,所以也就不问你了,直接就登陆了
OIDC基于OAuth2.0来做扩展是一个明智的选择吗?
必须是,站在巨人的肩膀上永远是一个明智的正确的不能更正确选择。