云山雾隐 端隐SDP

企业博客

端隐零信任如何实现单点登录?

SSO(Single Sign On)即单点登录,指的是用户在多个应用系统中,仅需登录一次即可访问其他相互信任的应用系统。以支付宝为例,登陆了支付宝就可以在淘宝、天猫中使用支付宝的登录信息进行单点登录,无需重复输入账密及二次验证。

目前主流、常用的单点登录协议有SAML和OIDC,SAML是早年基于XML且仅用于浏览器的协议,而OIDC是近几年在RESTFul服务流行期间基于OAuth协议拓展出来用于单点登录协议部分的一个超集,其信息传输使用了JWT(Json Web Token)。由于OIDC基于OAuth协议,所以不止支持B/S架构,同时也支持C/S架构应用,而SAML仅支持B/S架构。而在端隐零信任中又是如何使用Go语言实现单点登录功能的呢?

1.Golang单点登录库

SAML协议相关库

该SAML库中很多SAML实现不一定能完全满足产品需求,需自己写兼容或改源代码,不过该库算是Go语言中为数不多的SAML协议库。

OIDC协议相关库

其中dex和hydra是比较复杂的库,可用于快速构建一个现成的IdP服务器,而fosite是一个相对比较简单的OIDC协议实现库,可以便捷的内嵌到企业现有的业务中。

2.SAML协议实现方式

将 crewjam/saml clone到本地,打开Example翻到Server部分。可以看到主要的验证处理逻辑位于src/github.com/crewjam/saml/identity_provider.go:212,代码大致如下:

// 精简篇幅期间删掉了错误处理和log部分, 完整代码可以在Github上看到 func (idp *IdentityProvider) ServeSSO(w http.ResponseWriter, r *http.Request) {  req, err := NewIdpAuthnRequest(idp, r)  if err := req.Validate(); err != nil {    return  }  session := idp.SessionProvider.GetSession(w, r, req)  assertionMaker := idp.AssertionMaker  if assertionMaker == nil {    assertionMaker = DefaultAssertionMaker{}  }  if err := assertionMaker.MakeAssertion(req, session); err != nil {    return  }  if err := req.WriteResponse(w); err != nil {    return  } } copy

我们先认为身份提供商为服务端(生产者),请求身份提供商身份验证的为客户端(消费者)。首先使用NewIdpAuthnRequest函数从Request的Parameter里获取到经过Base64处理过的SAMLRequest(内容为遵循SAML协议的XML),然后调用Validate检查SAMLRequest是否有效。检查完内容有效性后对元数据进行断言,一般用DefaultAssertionMaker即可,有特殊需求可根据产品需求参考默认实现进行拓展。在这一步通过已上传的SAML客户端元数据,根据session还有SAMLRequest的内容构造SAMLResponse,然后响应给客户端。最后在ResponseWriter中写入Response,需注意SAML协议使用的Time是UTC时间,所以在时间的获取上需注意,有些系统可能会"不认"发送过去的时间字段,比如Jira及Confluence。

根据上述代码流程来看,核心在于MakeAssertion这一步。由于该库仅包含了协议基础框架结构,许多定制化功能需开发者根据自身需求去实现对应的AssertionMaker,比如自定义数据映射功能——将身份提供商的用户信息映射到客户端处,或对接腾讯云、AWS的Federation模式的SAML等,基本都是对AssertionMaker进行定制。

端隐零信任在单点登录功能的实现中,为方便客户使用,已经将部分必要且可预知的字段提前写在了代码中,用户仅需根据模版中的步骤填写必要字段即可,在很大程度上简化了用户使用SAML协议进行单点登录的配置流程。


该库在对接Gitlab SAML单点登录时,需额外点击Gitlab登录页面上的“使用XXX登录按钮”才会向身份提供商发送请求,再开始单点登录流程。若想直接输入某链接就直接登录进Gitlab时应该怎么做?

目前有两种方法,一种是身份提供商去构造SAMLRequest;首先在某个URL注册一个handler去构造SAMLRequest,再转发给上述流程处理,想访问Gitlab时直接访问该URL即可;端隐零信任用该方法尝试过Gitlab、Salesforce及AWS中国,均可满足需求。

第二种是自主实现AssertionMaker,从DefaultAssertionMaker的MakeAssertion实现中可看到经有效性检查后用到的SAMLRequest的内容仅有AttributeConsumingServices,也就是我们应将SAMLResponse返回到那里。如Gitlab服务器是127.0.0.1:8000,而AttributeConsumingService是 http://127.0.0.1:8000/users/auth/saml/callback,则最终鉴权完成后就会跳转到以下地址http://127.0.0.1:8000/users/auth/saml/callback?SAMLResponse=xxxxxxxx。此时我们跳过Validate流程,直接构造SAMLResponse响应给客户端即可。

以上两种方法存在一定兼容性问题,自己构造的SAMLRequest和部分客户端构造的SAMLRequest可能无法兼容,这将会导致构造的SAMLResponse不被客户端接受。需要根据无法使用的客户端去研究其构造的SAMLRequest大致包含什么内容和自主构造的通用SAMLRequest又有什么区别,两者对比后再进行定制。自主跳过验证实现的MakeAssertion也可能有类似问题,具体需根据特定客户端进行个性化定制。

端隐零信任除了支持SAML、OIDC、OAuth2等主流认证协议,也支持SDK接入;同时为阿里云、Gitlab、Jenkins、华为云等多种应用提供了定制化模板,以适配各类型应用的集成和接入。

管理员可根据企业内部现有的业务系统架构、开发语言及支持的认证协议在端隐零信任后台中选择已有的应用模板进行匹配;仅需选择对应模板,并通过配置身份提供商信息即可完成对该应用的单点登录集成,从而达到安全快速管理该业务应用的目的。实现用户仅需一套账密即可登录访问所有已授权应用,并提供账密、企业微信扫码、短信验证码、钉钉扫码等多种登录方式,方便用户快速登录与直接访问。