SSO and REST Api Authentication on multiple Application

marco.eig picture marco.eig · Aug 8, 2014 · Viewed 13.2k times · Source

at our company we have multiple web applications deployed that are secured through SSO using CAS server. A user requests an url of an application, and if not already authenticated, gets redirected to the CAS server login page. In case of successful authentication the user will be redirected back to the originally requested url. common workflow and works perfectly.

but, we also want to protect our REST Apis using CAS Server. Our prefered flow would be as follows:

  • a user creates a token for an application REST Api
  • using this token the user can request a temporary access token (like the CAS token)
  • in each request to the REST Api, the user includes the temporary access token either as a HTTP Header or a request parameter
  • the REST Api application checks the provided temporary token against the CAS server for validity

sounds like OAuth, which CAS server does support, except that the user is not asked for a credentials at any time, but we'd also like to provide authentication for services i.e., other applications calling our APIs:

  • developer asks for a REST Api token (which is associated with a CAS user)
  • application requests a temporary access token using the Api token
  • further requests to the Api include the temporary access token either as a HTTP header or a request parameter
  • REST Api application checks temporary access token against CAS server for validity

We want our REST Api applications to know nothing about user credentials, they don't even have access to the user database, which works just fine for humans using the application (redirect to CAS login page).

I don't know how we can implement this flow without having to heavily customize CAS server and implement this behavior by ourselves.

Google uses JWT for OAuth 2.0 for Server to Server Applications, which seems like the way to go.

I'd appreciate it if anyone can provide some hints or alternatives (to CAS server). Maybe someone has already implemented this pattern using CAS server and can provide some information on this issue.

Best Regards, Marco

Answer

marco.eig picture marco.eig · Aug 26, 2014

finally we got it working in an easy way:

at CAS server:

  • implemented a REST endpoint that allows clients to obtain a CAS service ticket ST by providing a clientId and a clientSecret for a specific service-url. clientId and clientSecret are considered to be username and password respectively.
    • the REST endpoint creates a new custom TokenBasedAuthenticationCredentials object and passes it to the CentralAuthenticationService to grant a TGT and a ST (the service-url for which the ST is granted is associated with the clientId and clientSecret pair and can be obtained from e.g., user-database clientId|clientSecret|serviceUrl).
  • implemented a new AuthenticationHandler and CredentialsToPrcincipalResolver which support TokenBasedAuthenticationCredentials only.

the REST endpoint /cas/../token returns a JSON object:

{ serviceTicket: 'ST-ALKSJDFLSJDFLKJ-Ljksdf-sdflkjsf' }

at (Spring-based) CAS client (protected resource):

  • enabled 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>
  • extend CasAuthenticationFilter and override obtainArtifact(request) to obtain the ST from the HTTP Authorization-Header

now, the client, which wants to access your protected resources, can

  • obtain a ST from the CAS server,
  • provide the ST in each request to the protected resource as Authorization-Header
GET /rest/foo/bar HTTP/1.1
Host: www.example.com
Authorization: CUSTOM_SCHEME ST-ALKSJDFLSJDFLKJ-Ljksdf-sdflkjsf

since CAS client CasAuthenticationFilter obtains artifacts (i.e., ST) on each request, the client gets authenticated in just a single request.

Additionally on CAS server, you can configure the ST to be valid for only n requests (the number of times the CAS client requests the serviceValidate url at CAS server).

I think this is a pretty good way without having to customize CAS server and client massively, and subsequently, creating critical security flaws.