Integrating Java Web App with SAML SSO - java

I have a Restful Java Web application which is to be deployed to a number of different environments (outside of my control) which will be using a SAML 2.0 SSO solution.
My application (which I believe is the "service provider") needs to store state generated by the user, and uses internal business logic to work out which users are allowed to view or update other user's data. In order for this to work we need to know who the user is, and what groups the user is part of. But how do I get this information?
Ideally my web app will be SSO agnostic, and would look for some configurable key headers in the http requests to get this information e.g. a SAML token in a request which could be parsed, or perhaps some custom headers specific to my "service provider".
Many Thanks

You are correct, your application is the Service Provider and you will have an external Identity Provider (IdP) to authenticate to.
Basically you need to issue an Authentication Request to the IdP (via either front channel HTTP POST or back channel SOAP/whatever they support) and use the authenticationResponse from the IdP to make your decision on whether they are who they say they are. As a rule you should be able to get the subject principal (ie username) and any group memberships from the authnResponse however exactly how this works will depend on what the IdP is or isn't configured to do.
Before you do this you will need to exchange SAML metadata with the IdP (this is generally part of being registered as a SP with the IdP) which gives both parties things like the public X509 cert for signing and validating requests.
There's a good spring library for SAML SP support, http://docs.spring.io/autorepo/docs/spring-security-saml/1.0.x-SNAPSHOT/reference/htmlsingle

you could run a reverse proxy in front of the Java web application to handle the SSO protocol part and relay user identity information to the application in HTTP headers; for SAML 2.0 there is mod_auth_mellon: https://github.com/UNINETT/mod_auth_mellon

If this is done in Java and running on a webcontainer (Tomcat, JBoss, etc.), then the agent could be implemented as a web authentication (servlet) filter (add into web.xml). The user would be typically derived from the SAML Auth response's <saml:NameID> or from <saml:Attribute> matching the userid attribute (uid,email, etc.). This user should be validated against the web app's identity repository (could be LDAP, database, etc.) and corresponding groups computed. Instead of using arbitrary headers or custom representation for the authenticated user, consider using java Principal (for users and groups) in a Subject.
The filter can then run the rest of the filter chain in a Subject.doAs(). That way, the Subject can be looked up any where in the downstream code using Subject.getSubject().

Related

Should we expose REST API as an OAuth 2 resource server?

I have a spring boot application exposing several REST API endpoints. I want to enable google oauth authentication (authorization code grant) on it. I am guessing what is correct way to do this out of following options:
Have separate application as OAuth 2 client (i.e. with spring-boot-starter-oauth2-client dependency and make the existing app a resource server (i.e. with spring-boot-starter-oauth2-resource-server dependency)
a. This Udemy's course keeps two application separate: resource server, OAuth 2 client. Then it seem to need a proxy REST endpoint in oauth
2 client project corresponding to every REST endpoint in resource server. REST end point in OAuth 2 client retrieves access token and adds it to every request to corresponding REST endpoint in resource server.
b. This stackoverflow threads talks about making same application both OAuth2 client as well as resource server
Make the existing app OAuth 2 client. (that is include spring-boot-starter-oauth2-client dependency) and simply require user to be authenticated to access REST endpoint URLs.
I have following doubts:
Q1. Should REST API always be exposed as resource server? And if yes, then is approach 2 not-so-recommended way? (as it does not expose existing REST API as resource server but as a part of OAuth client with restricted access to those APIs)?
Q2. If approach 2 is not fine, then which of approaches (1.a) and (1.b) are preferred or when to prefer one above other? (I believe (1.a) is more suitable when we want single OAuth client as a point of access for several different resource servers.)
In OAuth2 world, a REST API is a resource-server by definition.
In your scenario, Google currently is an authorization-server. You could hide it behind a Keycloak instance or something else capable of user identity federation if you need to extend to other identity providers (Github, Facebook, etc.) or want some roles definition, but as Google serve JWT access-tokens, you can use it for you resource-server security (if google IDs are enough for your security rules).
In both cases (Google directly or with an OIDC authorization-server in the middle), you can find sample configuration here (or there if you prefer to stick to spring-boot-starter-oauth2-resource-server but it requires more Java conf as you can see in tutorials).
I personnaly don't like to merge client(s), resource-server(s) and authorization-server(s). My clients are generally mobile and web with client-side rendering (Angular), but even for spring clients I'd keep it separate.
There is a special case, thought: when a resource-server delegates some of its processing to another, then, by definition, it is a client too. In that case, it is possible that security requirements and mechanisms are pretty different:
is your API authenticating in its own name (using client credentials flow)? In that case, you might use spring-boot-starter-oauth2-client to negotiate access-token to be used when issuing requests to other service.
is your API issuing requests in the name of authenticated user and does the other service know about the authorization-server which issued user authentication? In that case, you can forward the token you received
is the service you are consuming not OAuth2 at all? (just requires basic auth header for instance)

Create a custom identity provider and configure it with keycloak

I am working on a project where I need to create an application that shall act as an OIDC mediator between a client which only supports OIDC for authentication and a REST api. The REST api is able to generate tokens and give user info but does not support OIDC.
To achieve this I am thinking of using keycloak to handle the OIDC communication with the client and implement my own java application that keycloak can trigger to realize the authorization, token and userinfo endpoint (sort of a custom ownmade identity provider) handling the communication with the rest api.
I have created a realm in keycloak and configured the realm to use an Identity Provider Redirector with an Identity Provider I added in keycloak (user-defined OpenID Connect v1.0). In the identity provider configuration I have set all the URLs to point to my java application but the initial OIDC authorization call from the client just redirects to the redirect_uri with a #error=login_required without any of my endpoints in the java application beeing triggered.
I guess there is something I have missed.. I need to intervene the authorization flow so that I can pick up a query param from the authorization request that needs to be handled in my java application. I also need to map the token from the rest api into the token request (when this request comes from the backend of the client app), and finally map the userinfo object as a response to the userinfo request.
I really hope someone have time to point me in the right direction. Thank you so much in advance.
Edit:
I have added a sequence diagram to explain it better:
I need to intercept the authorization request call to pick up a custom query param (endUserString) that identifies the user. There will be no user login form. I need the param in my code that uses this towards the REST API. Both the token and the userinfo must be received from my APP and not from keycloak itself.
The Java Mediator may ask for a token in advance (A) and use this to access the Rest API (using a predefined clientId and clientsecret). Alternatively this token may be fetched for each method. To token must be used to retrieve customer info from the REST API (B). I want to wrap this with OIDC support without any login form. A browser will just redirect to the authorization flow with the endUserString identifying the end user. The customer info will be returned from the java mediator into keycloak responding this in the GetUserInfoRsp.
I think there might be a simpler solution than what you envisioned: implementing your own custom authenticator for Keycloak.
Keycloak has a notion of authentication flow which is a tree of authenticators than are provided by Keycloak or custom made. Each authenticator can be called to try to authenticate the user.
The most common one is the Username/Password Form which displays a login page to the user and authenticates the user if the provided credentials are valid. But you could imagine any type of authenticator such as an SMS authenticator or a magic link one.
You can find the existing Keycloak's authenticators on their repo and the documentation on how to create your own here.
In your case, you would need to implement your own logic where your authenticator would get the endUserString param from the request and call the REST API to validate the user's identity. You could fetch the REST API token at initialisation or for each request. You could also modify the user stored in Keycloak with data coming from the REST API's user info endpoint (common OIDC attributes or custom attributes).
Please note that the dev team announced Keycloak X, a sort of reboot of the project which will probably bring breaking changes to their APIs.
Also, please consider all the security impacts of your design as, from what you provided, it seems the authentication of a user will only rely on a simple query parameter which, if it doesn't change over time for example, feels like a big security hole.

which oauth2 flow do I need for multiple domain with a custom login screen

I'm implementing an authentication and authorization mechanism to unify login mechanism's across three different websites using an external identity provider and OAuth2.
The requirements that are causing design implications.
- Users and permissions managed externally to the existing websites in an external identity provider.
- The user should only have to log in once.
- The login screen needs to be embedded in our application rather than using an identity providers.
I'm creating a login web application. I'm not sure which OAuth2 flow to use. I've used the Authorization code flow previously with Spring security, but that seems to need an external identity provider's login form.
Should I use the implicit flow directly from the login site's javascript? How concerned do I need to be that it's not as secure as the code flow.
Do I need to handroll a solution to call an idp's sdk to get tokens and then sling them into http headers for subsequent use by the other domains Presumably CORS will be an issue? I'll need to include the id token for the other domain to know which user it is - is it secure to pass around the id token via the resource user's browser.
thanks for any guidance, as you can tell its a bit of a muddle in my mind!

Is OAuth necessary when implementing a RESTful web application that has its own login system (no social media)?

If I have a web application with a RESTful back-end that has a login system that keeps track of its own accounts (no social media logins what-so-ever), is there a point in using OAuth2 as a means of accessing the REST api? Essentially, if a login system does not have social media as a login choice, is there another route?
I have a Java-Spring back end. Would JWT be a suitable replacement for OAuth in this situation?
I see no reason why not.
When should you use JSON Web Tokens?
Here are some scenarios where JSON Web Tokens are useful:
Authentication: This is the most common scenario for using JWT. Once the user is logged in, each subsequent request will include the
JWT, allowing the user to access routes, services, and resources that
are permitted with that token. Single Sign On is a feature that widely
uses JWT nowadays, because of its small overhead and its ability to be
easily used across different domains.
Information Exchange: JSON Web Tokens are a good way of securely transmitting information between parties, because as they can be
signed, for example using public/private key pairs, you can be sure
that the senders are who they say they are. Additionally, as the
signature is calculated using the header and the payload, you can also
verify that the content hasn't been tampered with.
Source: https://jwt.io/introduction/

Extending JASIG CAS for Authorization

I have to build a Centralized Authentication And Authorization Service. I am trying to use the JASIG CAS. But its mentioned that its a authentication protocol.My scenario is as follows.
My application redirect to cas server on the first access.
CAS redirect the user for google authentication
User signs in with the desired email and redirect back to CAS
At this moment i need to validate the user in my local jdbc store for user enabled or not and if not already registered user, and the email domain is abc.com i need to auto register the user.
CAS redirect to the calling service
My service do the validateService api call. I would like to get the user authorities for the requested service in the result response from the CAS
Does this scenario can be achieved by CAS, if extension possible for CAS, can someone suggest how to do that, basically the classes that i need to modify
Does this scenario can be achieved by CAS
Jasig CAS is highly customizable and because it is build with spring framework and spring security you can extend it to any your needs.
basically the classes that i need to modify
classes of your interests are:
PolicyBasedAuthenticationManager
Entry point into authentication subsystem. It accepts one or more
credentials and delegates authentication to configured
AuthenticationHandler components. It collects the results of each
attempt and determines effective security policy.
AuthenticationHandler
Authenticates a single credential and reports one of three possible
results: success, failure, not attempted.
PrincipalResolver
Converts information in the authentication credential into a security
principal that commonly contains additional metadata attributes (i.e.
user details such as affiliations, group membership, email, display
name).
Jasig CAS is well documented. you should be able to find all information that you need there.

Categories