登陆服务 | 四、单点登陆OIDC

2021 11 1, Mon

之前简单做好了登陆的部分,但是单独一个登陆用处不大,我们希望的是给其他服务提供登陆的能力。

单点登陆

单点登陆 ( Single Sign On ) 指的是一处登陆,各个系统都可以按条件自动获取到身份信息的过程。常见的SSO过程有OAuth和SAML两大类,OAuth2.0之上又有 OIDC ( OpenID Connect )

单点登陆的主要目的有两个:

  • 用户可以减少登陆次数,提升认证过程的体验。比如说我登陆了Github,那么我就不再需要登陆CircleCI、Gist之类的其他应用,只需要告诉Github说我授权这些应用访问我的数据即可。
  • 减小应用授权体系的复杂程度,不需要每个网站都存储一遍密码,不需要每个网站都做一遍登陆的模块。

OIDC

OIDC是一层构建在OAuth2之上的协议,除了OAuth2的认证流以外,额外规定了一些方便应用接入的资源。也有认证方便非常权威的应用认为OAuth2的核心在于访问资源和分享,而OIDC是规定了认证的部分(按我的理解胡乱复述的)。

OIDC的认证过程中有三方:浏览器、认证服务器、应用服务器。应用服务器需要认证时引导浏览器跳转到认证服务,浏览器向认证服务器认证后携带认证code跳转回应用服务器,最后应用服务器向认证服务器验证Code并获取用户信息,将用户信息放入session中完成对应浏览器的认证过程。过程中code是一个普通字符串以外,其他的通信大都依靠JWT的签名来验证发布者身份。

计划在我的登陆服务中集成的就是OIDC的过程。

SAML

和OIDC的验证过程类似,SAML通过XML传递消息,由于过程类似,就不多描述了

Auth

Auth一般可以理解为Authentication,也可以理解成Authorization。之前一直不理解是什么概念是什么区别,一直到工作以后写了第一个OAuth2的应用才理解。

Authentication

Authentication也就是身份认证,证明我是我的过程。比如说密码认证,手机号和短信认证,登陆以后服务器就可以认定这个终端是我在使用。

Authorization

Authorization叫授权,授权什么应用可以使用什么资源。比如说我登陆了QQ,要在一个应用中用到QQ登陆,那么登陆后这个应用可以访问我的哪些数据?只是我的ID吗?还是可以获取我的公开信息,还是可以获取到一部分的不开放的数据,还是可以获取到我的好友列表。类似的还有有的时候是比如说Kubernetes集群这样、授权用户访问某些访问资源,有的时候是用户授权应用访问某些资源。

OIDC

ORY/Hydra

OIDC可以自己全部实现一遍,倒是没有什么大问题,但是考虑耗费精力比较多,没有必要自己造轮子,所以我使用了ORY/Hydra来构建OIDC的部分

Hydra是开源认证服务提供商开发的认证服务,部署一个额外的hydra服务+自己写几个认证和授权的页面就可以实现完整的OIDC服务的功能。

Browser         Application         Login-Server              Hydra
  | visit application|                    |                     |
  +----------------->|                    |                     |
  | redirect to auth |                    |                     |
  |<-----------------+                    |                     |
  | visit hydra      |                    |                     |
  +------------------+--------------------+-------------------->|
  |                  |                    | redirect to login   |
  |<-----------------+--------------------+---------------------+
  | visit login service                   |                     |
  +------------------+------------------->| fetch login info    |
  |                  |                    |-------------------->|
  |                  | redirect to hydra  | return login info   |
  |                  |    after login     |<--------------------+
  |<-----------------+--------------------+                     |
  | visit hyra       |                    |                     |
  +------------------+--------------------+-------------------->|
  |                  |                    |redirect 2 consent   |
  |<-----------------+--------------------+---------------------+
  | visit consent service                 |                     |
  +------------------+------------------->| fetch consent info  |
  |                  |                    +-------------------->|
  |                  | redirect to hydra  | return consent info |
  |                  |   after consent    |<--------------------+
  |<-----------------+--------------------+                     |
  | visit hydra      |                    |                     |
  +------------------+--------------------+-------------------->|
  |                  |                    | redirect with code  |
  |<-----------------+--------------------+---------------------|
  | visit app with code                   |                     |
  +----------------->| fetch token with code                    |
  |                  +--------------------+-------------------->|
  |                  |                    |    return token     |
  |                  <--------------------+---------------------+
  |                  | fetch user info    |                     |
  |                  +------------------->|                     |
  |                  | return user info   |                     |
  |                  |<-------------------+                     |
  |return with session                    |                     |
  |<-----------------+                    |                     |

Hydra在其中维护了Token、Consent和部分Login的状态。

需要实现的部分

认证

由于登陆服务本身就有登陆的功能,也就是所谓的身份认证,我们是不需要处理认证过程的。只需要在没有登陆的情况下跳转到登陆页面,登陆以后跳转回来就行。

授权

授权这一步在OIDC中主要是需要用户授权应用访问用户的某些数据,对于OIDC来说则是需要提供一个Consent Flow,告知用户应用一定要用哪些数据、可选使用哪些数据,这个授权的范围称为是scope,需要实现一个页面来告知用户有哪些scope、选择scope。

登出

无需多言。

资源发现

OIDC同时要求提供资源发现的地址,主要是通过JSON提供了各个资源所在的地址。Hydra中自带。

应用管理

为了方便管理OAuth2应用,我们还需要实现一个OAuth2应用的页面。

具体的代码

具体来说我们就是需要实现三个HTTP Handler,分别处理OIDC的的登陆、授权和登出。

除此之外需要一个只能给管理员或者管理员组查看的面板,用来管理OIDC的应用。