了解单点登录常用协议

了解单点登录常用协议
逐暗者最近在改造一个单点登录系统,由于其中涉及到很多不同的协议、不同的授权方式,所以整理了一下相关的知识
名词
什么是单点登录
单点登录(SSO)是一种身份验证机制,它允许用户使用单一的凭据(如用户名和密码)访问多个相互关联的应用程序或系统。在没有单点登录的情况下,用户可能需要为每个应用程序分别记住不同的用户名和密码,这不仅麻烦,而且增加了用户管理凭据的负担和安全风险(如使用简单或重复的密码)。
在企业内部尤为明显,通常企业内部会有许多系统(例如OA系统、库存系统、销售系统、作业系统、审批系统、邮件系统、财务系统等等),如果让员工在每个系统上使用独立的账号密码登录显然不现实。所以就会需要单点登录。用户只要登录一次,就可以在所有系统上工作,无需重复登录。
协议
IdP经常会使用OAuth、OIDC、SAML协议来实现单点登录功能,那这3种协议又有什么区别呢?
OAuth
OAuth(开放授权)是一个开放标准的授权协议,它允许用户在不向第三方应用提供用户名和密码的情况下,授权第三方应用访问其存储在另外一个服务提供商(如社交网络平台、云存储服务等)上的受保护资源。
所以OAuth并不是一种身份认证的协议,而是一个授权协议。
举一个例子: 用户张三访问了一个A网站,A网站希望获取张三在gitee上的代码仓库信息。张三不会把自己的gitee账号密码给A网站,于是A网站就对接gitee,gitee采用OAuth协议授权A网站访问特定资源(这里指的就是张三的代码仓库信息)
核心角色
- 资源拥有者(Resource Owner): 通常为用户,也可以是应用程序,即该资源的拥有者。
- 客户端(Client): 本身不存储资源,需要通过资源拥有者的授权去请求资源服务器的资源,比如:Android客户端、Web客户端(浏览器端)、微信客户端等。
- 授权服务器 (Authorization Server) : 用于服务提供商对资源拥有的身份进行认证、对访问资源进行授权,认证成功后会给客户端发放令牌 (access_token),作为客户端访问资源服务器的凭据。
- 资源服务器(Resource Server): 存储资源的服务器。
授权模式
授权模式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
客户端凭证模式 | 简单 | 受使用场景限制 | 不需要资源拥有者参与的场景,为后台API服务设计,例如:地图信息 |
密码模式 | 不需要多次请求转发,额外开销 | 可以认证身份 | 需要认证服务器和资源服务器互相信赖,例如:同一公司自研系统 |
授权码授权模式 | 安全性高 | 多次请求 | 拥有后台管理的应用 |
隐式授权模式 | 简单 | 安全性较差,只有client_id即可获取令牌 | 应用只有页面没有后台管理,只能使用第三方认证后,直接访问。对安全性不高的场景。例如:浏览器插件 |
- 客户端凭证模式
- 密码模式
- 授权码授权模式
- 隐式授权模式
为什么OAuth可以用于单点登录呢?
OAuth并不是一种身份认证的协议,而是一个授权协议,所以只能用来授权,并不能用来身份认证。但事实上用户信息也是一种授保护的资源。只要授权的对象是获取用户信息,那么就可以在通过OAuth认证后,再获取用户信息,从而实现单点登录。
举个例子:gitee提供OAuth授权信息,并且提供授权访问用户信息
OIDC
OIDC是OpenID Connect的简称,OIDC=(Identity, Authentication) + OAuth2.0。它在OAuth2上构建了一个身份层,是一个基于OAuth2协议的身份认证标准协议。OIDC是一个协议族,提供很多的标准协议,包括Core核心协议和一些扩展协议。
SAML
SAML(Security Assertion Markup Language)是一种基于XML的安全协议,用于在不同的安全域之间交换认证和授权数据。SAML的主要作用是实现单点登录(SSO),使用户能够在多个应用程序中使用相同的凭证进行登录。
核心角色
- 主体(principal):通常代表人类用户/浏览器终端
- 身份提供者(Identity Provider,简称IdP): 主要负责进行身份认证,并将用户的认证信息和授权信息传递给SP
- 服务提供者(Service Provider,简称SP): 主要职责是验证用户的认证信息,并授权用户访问指定的资源信息
认证过程
题外话
在OIDC中,有一个idToken的东东,它里面包含着用户信息,它的格式是JWT。通常对接单点登录服务器,获取到idToken后需要做一系列的校验。
验证签名:使用公钥验证ID Token的签名,确保ID Token未被篡改。
验证发行者:确认ID Token是由信任的授权服务器签发的。
验证令牌类型:确保令牌类型是id_token。
验证受众:确认ID Token是发送给正确的客户端。
验证过期时间:检查令牌是否在有效期内。
验证发行时间:可选,确保令牌在合理的时间范围内被签发。
验证nonce:如果使用了nonce参数来防止重放攻击,需要验证nonce值。
突然发现一个很奇怪的要求,原以为验证了签名就可以保证JWT(这里指idToken)未被篡改,为什么还需要验证发行者(iss)呢?进一步提出了以下疑问:
采用了主流的协议就能保证单点登录系统安全可靠吗?
答案显然是否定的,在OIDC文档中(16节)我们看到了一些安全和隐私注意事项,其中包含多种可能的攻击手段(例如:服务器伪装、令牌重用等)和防御措施(TLS要求等),所以为了单点登录服务器完全,需要多方面(技术方式、不同系统)一起保障。