How to read CAS ticket validation XML using spring security? - spring

I have a Spring Boot application and use the Java Apereo CAS Client (version 3.6.2) to use an CAS server for authentication. In other words, I want to turn my app into a CAS client, I didn't set up the CAS server myself.
I checked the list of calls made to CAS server:
The first call to the CAS server is made, but I don't see the second call to the server for ticket validation (i.e., a call to https://cas-server-address/cas/serviceValidate URL) that will return an XML document with user and authtype attributes that I want to extract to store in the database.
I have 2 questions:
Why there is no second call for the CAS server for ticket validation? Is it hidden?
How do I extract user and authtype attributes from the XML document and store them in the database?

Why there is no second call for the CAS server for ticket validation?
There is. The second call is a back-channel call from your application server over to the CAS server. By definition, this is not something you would see in your browser. This call goes over to the CAS server behind the scenes to validate the service ticket received in the first leg (i.e. ST-xyz). The Java CAS client library should be automatically doing this for you, and you can verify this in the logs.
If you don't see this happening, your configuration is not set correctly or there is an error along the process.
Is it hidden?
Hidden from the browser, as it's a back-channel call. For additional details on what happens and why, please study the CAS protocol.
How do I extract user and authtype attributes from the XML document and store them in the database?
The Java CAS client library typically extracts the user id and other attributes. Then, the user-id would be available under the REMOTE-USER header that can be fetched via the http request object. If you have access to the http session, you can also fetch the final Assertion from the session which contains the CAS payload:
var assertion = (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
For a more practical example, see this.

Related

Spring Boot session management - combined solution PostgreSQL + Redis

So, I would like to implement complex session management in my application. Essentially, I would like to store user sessions both in the postgre and Redis.
So, the algorithm should be the following:
A request is sent to the app, the application parses incoming request cookies and extracts a session parameter;
Spring server tries to retrieve respective session object by id from Redis
If the previous step succeeds, then the server verifies the session and lets the request pass through if the session is active and valid. Otherwise - unauthorized path.
If the session object isn't present in the Redis, then the server tries pulling a member session from the postgre. Does the same verifications and caches the response. If the session isn't valid or isn't present in RDBMS - go to the unauthorized path.
Is there any elegant way to implement the following mechanism using existing packages? Or will this require custom logic?
So, I watched this video - https://www.youtube.com/watch?v=TggWLDAXmb4
And I was able to get a gist of how basic security mechanisms work in Spring and implement the workflow described above;
Basically, you will need to have:
Custom security filter that will be preparing specific Authentication;
Custom authentication provider that will be performing authentication (checking session)

CAS 6.0 and Spring Security: JWT configuration fails on Service Ticket validation

I'm setting up a configuration using CAS 6.0 and Spring Boot with Spring Security so as to shift to JWT. Looking at this guide, I've configured module dependency, CAS Service Registry, and signing and encryption Keys. The flow goes fine:
calling the app at https://localhost:9000/secure/home/test I'm redirected to CAS login,
at https://localhost:8443/cas/login?service=https%3A%2F%2Flocalhost%3A9000%2Flogin%2Fcas I can correctly specify credentials and see TGC in JWT form inside the cookies,
after inserting credentials I'm redirected to https://localhost:9000/login/cas.
Last call has the two query string parameters redirect=true and ticket=[JWT string].
I've set up a filter decoding the token and it works, but then the filter chain hits CasAuthenticationFilter, which sees the ticket parameter and tries to validate it as Service Ticket, failing.
How can it be made aware of jwt, and forward the request to the original URL?
the same question in CAS 5.3.x.
finally I did the following flow:
CAS Server:
set up the cas.properties in cas server, add 'cas.ticket.st.numberOfUses=2' to let service ticket can be used twice. (default value is 1)
Application Server:
set up a filter to decode JWT token, extract service ticket from the key "jti" in JWT token.
set the response status to 302 and redirect to the request url and make the service ticket as query string named "ticket". (note that in this step should not go on the next filter)
the redirect request from #2 should not process in #1's filter then go on the filter chain.
The above flow works. But need more testing to confirm the working fine for web applications and result api service.

How does SAML Service Provider understand identity after initial authentication (vs OIDC)?

I'm looking to implement a plugin using OpenSAML for a 3rd party application that will enable the application to be treated as a SAML Service Provider, so that I can integrate it into AWS SSO.
The following image describes the SAML authentication process when the Service Provider (SP) and Identity Provider (IdP) use HTTP Artifact binding (taken from here):
After the initial authentication, the SP returns the protected resource to the user. My question relates to how subsequent requests for protected resources are processed.
With OIDC, the browser would receive a token and this would be sent to the SP for subsequent requests. The SP can inspect the token and confirm its integrity (assuming it is signed) and validity, without needing to make further calls to the IdP to re-authenticate the end-user.
With SAML, how do I achieve the same effect? How do I not have to make repeated calls to the IdP to check identity?
I suppose I could use a session, but I don't understand how I might ensure that such information is not tampered with within the client (i.e. how does the SP not have to rely on information provided by the client?). Does SAML have some sort of concept of a token that is safe for the user to store (the HTTP Artifact binding explicitly restricts the user from seeing the response from the IdP)?
What happens after the last step is not defined in the spec. You could say it's formally outside of SAML protocol. Even the last protocol-formalized step of SP supplying the resource is essentially a "do it yourself":
Section 3.4.5 (HTTP-Redirect binding):
Upon receiving the SAML response, the SAML requester returns an
arbitrary HTTP response to the user agent
Section 3.5 (HTTP-POST binding):
Upon receiving the SAML response, the SAML requester returns an
arbitrary HTTP response to the user agent
Section 3.6 (HTTP-Artifact binding):
[you can probably guess by now]
Most SPs will drop one or more cookies on the client during that last step. One of those cookies will contain a session ID or a more generic pointer that can be used to locate a session when sent back to SP. Subsequent resource "authorization" requests to SP will proceed by having the SP consult this server-side session. The session will usually hold the (authenticated) security context for this user/client.
For example, Shibboleth (built on top of OpenSAML) does so. The content of the cookie is up to the SP. It's arguable that token-based auth via e.g. local storage is more secure vs a cookie. There are pros/cons to both options and many factors specific to use case/context/technology stack impact the evaluation of risk and associated threat model.
Note: AWS SSO does not support the Artifact binding.

Spring oauth2 authorization flow - preapproval in app

we have a server to server communication that we wish to protect with oauth , but the authorization needs to be of a user. (cause the main server maintains a session and perform some validations of user permissions which are not spring roles checking ).
at first i thought of client_credencials but i needed to perform some mapping between the clientid and user. this kind of requires a hidden login on server to have the user session initialized.
also this is not the recommended flow (as written in the spring ClientCredentialsTokenEndpointFilter code)
so i think i want to try a different approach like authrization_code but i don't want any redirects here.i want something as simple as that.
user log in to our application (main server)
generate authorization request - like create API keys or something.
user is presented with authorization_code and state
user goes to the other server and put the code and state somewhere (don't care)
the other server use the code and state to be exchanged for token.
how can i achieve this ?
thanks
Shlomi
You can send a JWT from your server to the remote server that identifiers the user and the remote server can use that as a "grant" to obtain an access token from your server. This is called JWT Authorization Grant. The specification (work in progress) is here: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-jwt-bearer-12 but there are a number of implementations out there already. Below is an example JSON object that could be encoded to produce the JWT Claims Object for a JWT:
{
"iss":"https://jwt-idp.example.com",
"sub":"mailto:mike#example.com",
"aud":"https://jwt-rp.example.net",
"nbf":1300815780,
"exp":1300819380,
"http://claims.example.com/member":true
}
To present the JWT with the claims and header shown in the previous example as part of an access token request, for example, the client might make the following HTTPS request (with extra line breaks for display purposes only):
POST /token.oauth2 HTTP/1.1
Host: authz.example.net
Content-Type: application/x-www-form-urlencoded
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer
&assertion=eyJhbGciOiJFUzI1NiJ9.
eyJpc3Mi[...omitted for brevity...].
J9l-ZhwP[...omitted for brevity...]
Of course the implementations on both sides needs to support this grant type, but it should be be too hard to add this to an existing OAuth 2.0 implementation since it reuses large parts of other grant types.

REST authentication, Best approach

Background:
We are building system that required login information for all pages. the application is designed to be Restful application using codeigniter as Phil Sturgeon library.
Scenario:
- username & password is required when a user called any page [Client]
- Authentication is needed where any Api call is fired
I a bit confused how to migrate or do the above scenario, And what are approach to authenticate the application.
A simple way to authenticate users in a RESTful API is using HTTP Basic or Digest Auth. In this setting the user credentials are sent via the Authorization header in a form of username:password as Base64 encoded hash to the server.
As the principles of REST state that the communication between client and server should be stateless, the client has to sent the authorization on every request. In practice this means that you often store the credentials in a session on the client side (as you don't want to the user to enter his credentials on every request). Please note that you should only do this via an secured connection using HTTPS!
To authenticate the application you could use a token based system, such as an API-Key. This means any request would be signed using additional request parameters. If the number of applications is finite and known, you could alternatively simply identify them by their IP.
You could also take a look at OAuth.
Request the login and password for every page is more suitable and more secure(that what I do in my projects), using 'virtual' and stored session in the database may be a second solution but not a good because it will be an additional charge for the DB.

Resources