多个应用程序上的 SSO 和 REST Api 身份验证
Posted
技术标签:
【中文标题】多个应用程序上的 SSO 和 REST Api 身份验证【英文标题】:SSO and REST Api Authentication on multiple Application 【发布时间】:2014-10-01 14:56:41 【问题描述】:在我们公司,我们部署了多个使用 CAS 服务器通过 SSO 保护的 Web 应用程序。 用户请求应用程序的 url,如果尚未通过身份验证,则会被重定向到 CAS 服务器登录页面。如果身份验证成功,用户将被重定向回最初请求的 url。通用的工作流程,完美运行。
但是,我们还想使用 CAS 服务器保护我们的 REST API。 我们的首选流程如下:
用户为应用程序 REST Api 创建令牌 使用此令牌,用户可以请求临时访问令牌(如 CAS 令牌) 在对 REST Api 的每个请求中,用户将临时访问令牌作为 HTTP 标头或请求参数包含在内 REST Api 应用程序根据 CAS 服务器检查提供的临时令牌的有效性听起来像 CAS 服务器确实支持的 OAuth,除了在任何时候都不会要求用户提供凭据,但我们还想为服务(即调用我们 API 的其他应用程序)提供身份验证:
开发人员要求提供 REST Api 令牌(与 CAS 用户相关联) 应用程序使用 Api 令牌请求临时访问令牌 对 Api 的进一步请求包括临时访问令牌作为 HTTP 标头或请求参数 REST Api 应用程序根据 CAS 服务器检查临时访问令牌的有效性我们希望我们的 REST Api 应用程序对用户凭据一无所知,它们甚至无法访问用户数据库,这对于使用应用程序的人来说工作得很好(重定向到 CAS 登录页面)。
我不知道我们如何实现这个流程,而不必大量定制 CAS 服务器并自己实现这个行为。
Google 将 JWT 用于 OAuth 2.0 for Server to Server Applications,这似乎是可行的方法。
如果有人能提供一些提示或替代方案(对 CAS 服务器),我将不胜感激。也许有人已经使用 CAS 服务器实现了这个模式,并且可以提供一些关于这个问题的信息。
最好的问候, 马可
【问题讨论】:
【参考方案1】:终于我们用一种简单的方式让它工作了:
在 CAS 服务器上:
实现了一个 REST 端点,允许客户端通过为特定 提供 clientId 和 clientSecret 来获取 CAS 服务票据 ST >服务网址。 clientId 和 clientSecret 分别被认为是 username 和 password。 REST 端点创建一个新的自定义 TokenBasedAuthenticationCredentials 对象并将其传递给 CentralAuthenticationService 以授予 TGT 和 ST(service-url 授予ST 的对象与clientId 和clientSecret 对相关联,并且可以从例如用户数据库clientId |clientSecret|serviceUrl)。 实现了一个新的 AuthenticationHandler 和 CredentialsToPrcincipalResolver,它们仅支持 TokenBasedAuthenticationCredentials。REST 端点 /cas/../token 返回一个 JSON 对象:
serviceTicket: 'ST-ALKSJDFLSJDFLKJ-Ljksdf-sdflkjsf'
在(基于 Spring 的)CAS 客户端(受保护的资源):
启用 authenticateAllArtifacts<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<property name="service" value="$cas.service.url" />
<property name="sendRenew" value="false" />
<property name="authenticateAllArtifacts" value="true"/>
</bean>
扩展 CasAuthenticationFilter 并覆盖 obtainArtifact(request) 以从 HTTP Authorization-Header 获取 ST
现在,想要访问您的受保护资源的客户端可以
从 CAS 服务器获取 ST, 在对受保护资源的每个请求中提供 ST 作为Authorization-Header 获取 /rest/foo/bar HTTP/1.1 主机:www.example.com 授权:CUSTOM_SCHEME ST-ALKSJDFLSJDFLKJ-Ljksdf-sdflkjsf由于 CAS 客户端 CasAuthenticationFilter 在每个请求中获取工件(即 ST),因此客户端仅在单个请求中获得身份验证。
另外在 CAS 服务器上,您可以将 ST 配置为仅对 n 个请求有效(CAS 客户端请求 serviceValidate 的次数em> CAS 服务器上的 url)。
我认为这是一个很好的方法,无需大规模定制 CAS 服务器和客户端,从而产生严重的安全漏洞。
【讨论】:
【参考方案2】:服务票不是设计为一次性使用的吗?
【讨论】:
您可以将其配置为仅有效一次。你能告诉我更多关于你为什么认为它们是为一次性使用而设计的信息吗? @reagten 据我了解,以这种方式公开服务票证(基本上将其用作令牌)会引入一些安全问题(例如无法控制服务票证的使用)。这样做不是更好吗。从 CAS 检索 TGT,使用用户/密码/TGT 对 CAS 进行身份验证。将 CAS REST API 中的服务票证交换为特定于应用程序的令牌?这样 REST API 只知道 Token 而不知道与用户关联的数据,客户端也不能使用 ST 直接调用 CAS /validate 端点(ST 也可以被 IP 锁定)以上是关于多个应用程序上的 SSO 和 REST Api 身份验证的主要内容,如果未能解决你的问题,请参考以下文章
Tomcat 和 spring-security 中的 Web 应用程序和 REST 服务 SSO
如何从 REST API(PUT 方法)更新 Keycloak 密码?