I'm working on an project that implements user authentication through Spring Security using a spring session ID stored in a cookie on the client's browser. There's no authentication server, the same server manages authentication and the whole app as a monolith.
So we are now in the need of implementing SSO with a third party system, so far everything I've read on the matter requires OAuth or some other implementation of token based authentication that supports an external identity provider. I would prefer not to migrate the authentication strategy as we are kinda on the clock.
I work on another project that has OAuth authentication so I'm not new on that topic (though not really an expert either).
Can someone throw some light on this? I just need to know if it is possible or there's no other way to migrate the authentication strategy.
Cookie based SSO is only possible (in an easy way) if you are using a so called 'domain cookie'. Technically all applications need to share the same 'cookie domain' then. However from security point of view this is highly discouraged, due to cookie hijacking being possible.
Related
Background:
I am developing a web application, planned to use spring-mvc and spring security. My plan is to use form based authentication where spring security authenticates credentials and sets a session JSESSIONID so that subsequent requests would be authenticated based on the cookie present in request header.
My understanding:
Web applications requests should have state. This state can be accomplished by using the session.
Purely session based authentication are vulnerable to CSRF attacks. As spring security provides CSRF protection, i didn't find any security loop holes using session + CSRF protection.
access-tokens are only used to give access to APIs which has been exposed for third party applications.
My Question:
But when i see lot of questions in this site, people are using token(OAuth2/JWT) based authentication for web application. But what i believed is tokens are only used to give access to APIs.
But when i see people using tokens for web applications i just got this question. Assuming token based web applications does not uses session but expects token in the header of every request.
When we should go for token based authentication in web application.
As far as security is concerned, which one is good? Session + CSRF or token based authentication.
I am confused with use cases of token and session.
EDIT:
From momo's comment
Most often, it depends on your clients.
For example, for mobile clients (e.g. JSON payload over HTTP), there is no such thing as a Session. JWT has the advantage to work cross-origin. In contrast, a Session-based auth method with Cookies works only for the same (Sub)-domain) and scales not that well.
However, it is easier to invalidate a Session than a JWT. Since you anyway use Spring-MVC and i guess scalability is not critical, just go with the one you are more comfortable.
conclusion: Session supports requests only from same origin, token based authentication preferred for authenticating cross origin requests.
Most often, it depends on your clients. For example, for mobile clients (e.g. JSON payload over HTTP), there is no such thing as a Session.
JWT
JWT has the advantage to work cross-origin over different domains
Therefore, JWT based authentification scale better
very popular in the age of single-page applications (SPA) / Web API's
keep attention to integrity protection by using either a signature or a MAC. Do not allow the unsecured JWTs: {"alg":"none"}
Session
primarily used in conjunction with web browsers
Easier to invalidate (remove) a Session. JWT has only an expiration date and is valid until it expires
keep attention to the following cookie attributes: secure; HttpOnly and to provide some protection against cross-site request forgery attacks: SameSite=Strict or SameSite=Lax
Other approaches:
Open Source Identity Providers like Keycloak with e.g. traefik as load balancer have become quite popular. This brings the advantage, that new routes can go live without restarting any service. Also, in some cases, it saves application downtime caused due to an excessive rate of API calls.
To conclude:
Many roads lead to Rome. It always depends on the specific requirements, the environment and the skills of the team. Since you anyway use Spring MVC and I guess scalability is not critical, just go with the one you are more comfortable..
For Stateless application use JWT
For third party applications use OAuth2
For Statefull application use Session + CSRF
I have been going through lot of documentation to understand what is the standard way (if there is any) in which the java client authenticates themselves with the applications deployed on server container like weblogic, jboss etc.
After reading about JAAS & JNDI authentication documentation for weblogic, I am able to understand the flow, but no documentation answers the below queries
Are JAAS and JNDI the only available methods for authenticating java clients ?
What I understood so far is, that each application server can provide its own abstraction layer to perform authentication, for example OPSS in weblogic, but eventually they all depend on native authentication methods available in JEE framework. Please point out if this assumption is not correct.
The confusion is greatly amplified as some article mention that JAAS security doesn't exists in JEE. Is that valid for java 7+ too?
The oracle weblogic documentation I have been going through clearly states JNDI & JAAS as the standard authentication approaches, and even goes to the extent to specifying JAAS as being preferred over JNDI authentication.
https://docs.oracle.com/cd/E28280_01/web.1111/e13711/fat_client.htm#SCPRG225/
Here is clarification I got based on the material read during last two days.
Most basic thing - All application servers provided provide an identity store, that can store users & groups. Applications can refer to this identity store, as when it is deployed on the server.
A Caller or User is an individual named identity defined in an identity store.
https://dzone.com/refcardz/getting-started-java-ee?chapter=1
How the applications execute authentication?
Based on pure JEE framework, the authentication methods can be classified based on the type of application it secures:
Web Application Authentication
Declarative:
We use either deployment descriptors or #annotations to specify these authentication enablers:
a. Which options to use for rendering authentication i.e. basic (browser popup), custom form, SSL, etc.
b. Which resources(URL patterns) need authentication and authorization.
c. Which users or roles (via groups) are permitted authentication or authorization.
Programmatic
Here we make use of security methods() in built in interface HttpServletRequest.
The application(e.g. servlet) call following methods to instigate authentication from within an "unconstrained" resource.
a. request. Authenticate: A login box pops up to collect credentials.
b. request. login: This methods takes login/password without the pop
c. request. logout: Resets the user/caller identity
There are several other methods also available, that provides more details of the authenticated user like isUserInRole(whether it's in given role), GetRemoteUser(gives user name), etc.
EJB Authentication
How EJBs are authenticated??
EJBs are can also be secured in the same way, as web based apps. i.e. Either with Declarative or programmatic security. Some caveats to this statement, but those are not relevant to current discussion.
So why do we need JAAS, and what is JAAS?
To appreciate this, let's understand a practical scenario for any:
An application may have multiple authentication requirements e.g. password, certificate, authentication users from multiple security realms, perimeter authentication, etc. Do we have to code so much for every application, and type of authentication? Now, it can be cumbersome and complex create & maintain code for authenticating users based on these different techno-business requirements.
To address above situation, there has to be a Pluggable way to writing code for authentication, wherein, developers would only be responsible for mentioning(not coding) which AuthenticationProvider has to be used, and writing code to call the loginModule of that particular provider, which eventually has code to authenticate the given user/caller.
This framework of providing pluggable authentication is called Pluggable Authentication Module in LDAP world.
"JAAS" is java implementation of PAM framework. With JAAS, either updated, or additional authentication technologies can be plugged under an application, without modifying the application code as such.
After Authentication, JAAS also enforces authorization.
JEE provides libraries to implement JAAS in applications!
Is JAAS implemented in same way across different enterprise application servers like Weblogic, JBoss, etc.
Well, "It can be", "but is usually not" implemented in same way across different application servers.
This is because application server may provide its own libraries, which can be used to implement JAAS.
Hope this clarifies the JEE security model to folks who do not have development background.
TL;DR
Objective: Java authorization server:
OAuth2.0 authorization code grant flow with fine-grained permissions (not a mere SSO server)
User management and authentication: custom database
Client management and authentication: Keycloak
Questions: What are the best practices for implementing a Java authorization server with applicative permissions handling backed on Keycloak?
What Keycloak adapter/API should I use in my development?
How should the users be managed/appear in Keycloak if they are to appear at all?
Forewarning
I am quite the beginner with Keycloak and, though I think I understand the main principles, it seems to be a rich tool and I fear I may still be mistaken about some aspects of the best ways to use it. Please do not hesitate to correct me.
Context
We are looking at implementing an API requiring our users (henceforth "users") to grant permissions to third party applications (henceforth "clients").
Our users are stored in a custom existing database-based user management system. As for our clients, we are thinking of using Keycloak.
The users consent will be given using an OAuth2.0 Authorization code grant flow. They will log in, specify which permissions they grant and which they deny, and the client then retrieves the access token it will use to access the API.
It is my understanding that Keycloak can handle the authorization token but it should not know anything applicative, which our permissions are. As a consequence, I thought of building a custom authorization server which will use Keycloak for all identity/authentication problems but will handle the applicative permissions by itself.
Then, we will use Keycloak for client authentication and authorization code/access token management, and an applicative part will check the permissions.
Problem
Besides my first experimenting, I've been roaming the Internet for a week now and I'm surprised as I thought this would be quite a standard case. Yet I found next-to-nothing, so maybe I'm not searching correctly.
I've found many Spring/Spring Boot tutorials1 on how to make a "simple authorization server". Those are mainly SSO servers though, and few do manage permissions, with the exception of those mentioned in this SO answer2. That I think we can deal with.
The real problem I have, and that none of the tutorials I have found are treating, is the following:
How do I integrate Keycloak in this authorization server?
I've been having a look at the available Java Adapters. They look OK when it comes to authenticate but I did not see hints about how to manage clients from a custom authorization server (ie administer the realm).
I therefore suppose I should use the admin API. Am I correct and is it good practice? I saw no adapter for that, so I suppose I should then use the REST API.
I also wonder how we should integrate our users in design? Should they be duplicated inside Keycloak? In this case, should we use Keycloak's admin API to push the data from the authorization server or is there a better way?
Finally, am I missing some other obvious point?
Sorry for the long message and the many questions, but it all boils down to one question in the end:
What are the best practices when building an authorization server using Keycloak as a backbone?
1. Some examples:
Spring Boot OAuth2 tutorial -
A blog post -
Another blog post
2. I've mainly focused on the sample app provided by Spring Security OAuth
Building Java OAuth2.0 authorization server with Keycloak
This is possible but is bit tricky and there is lot of thing which needs to be customised.
You can derive some motivation from below repo.
keycloak-delegate-authn-consent
Building custom Java OAuth2.0 authorization server with MITREid
If you are open to use other implementations of Oauth and OIDC,I can suggest you MITREid which is referrence implementation of OIDC and could be customized to a great deal.Below is the link to its repo and its open source.
I myself used this to requirement similar to yours and it is highly customizable and easy to implement.
https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server
MITREid Connect uses Spring Security for its authentication, so you can put whatever component you like into that space. There are lots of good resources on the web about how to write and configure Spring Security filters for custom authentication mechanisms.
You'll want to look at the user-context.xml file for where the user authentication is defined. In the core project this is a simple username/password field against a local database. In others like the LDAP overlay project, this connects to an LDAP server. In some systems, like MIT's "oidc.mit.edu" server, there are actually a handful of different authentication mechanisms that can be used in parallel: LDAP, kerberos, and certificates in that case.
Note that in all cases, you'll still need to have access to a UserInfo data store somewhere. This can be sourced from the database, from LDAP, or from something else, but it needs to be available for each logged in user.
The MITREid Connect server can function as an OpenID Connect Identity Provider (IdP) and an OAuth 2.0 Authorization Server (AS) simultaneously. The server is a Spring application and its configuration files are found in openid-connect-server-webapp/src/main/webapp/WEB-INF/ and end in .xml. The configuration has been split into multiple .xml files to facilitate overrides and custom configuration.
I'm developing for the first time a Soap web service, using Axis2 upon Tomcat.
What i need is to manage authentication. So, users, before calling rpc have to login.
Now what I'm doing is storing into the DB a passFrase to give back users when they login, so I check if it exist and, if yes, the are allowed to call rpc. The matter is that this way is so inefficient.
Is there a way to handle users authentication easilier and more efficiently? Perhaps some library?
You can use either of these three approaches:
Use transport level authentication such at BASIC or DIGEST AUTH, (and please use HTTPS here).
Use WS-Security (preferably WS-Policy) with a Username Token.
Handle it in the application layer (what you are doing now).
Depending on your demands/taste, choose one of the above that fulfill your needs the most.
I should warn you that as of today, (2) is not possible with the current stable release of Axis2 and Rampart (1.6.2), you have to use an earlier release (1.5.x), which I explained why here.
I am looking to add single sign on (SSO) to one of my web applications. I don't want anything heavy at the moment, I just want to know the userId of the logged in user, without the need for them to enter a username.
The web app is an internal application, so I can guarantee they are coming from a Windows PC etc.
I have looked at jCIFS, but this doesn't seem to be supported any more, and recommends a commercial product.
I have also looked at WAFFLE, but I am building SSO for a playframework application, which does not use a Servlet stack, so I can't make use of the SecurityFilter. I have tried to make sense of the WindowsLoginModule, but couldn't really understand what I had to do to implement it.
Is it possible to just get the username from the HTTP header, or does it require some negotiation first before it will post the header?
You want the windows user to automagically login to your intranet webapp. So the user accounts would sit in an active directory and the usual microsoft way would be to use a protocol like NTML oder Kerberos. Applications are generally advised not to use NTLM, although there are enterprises still using NTML (and jCIFS) for SSO.
A quick search on Kerberos and Java showed this article. It seems to depend on the Java EE stack (JAAS).
For a more stripped down approach: Usually, you cannot sent the username in a http request in a portable way. With ActivX you could do:
var wshshell=new ActiveXObject("wscript.shell");
var username=wshshell.ExpandEnvironmentStrings("%username%");
On the server side, you can parse the http header and extract the username with your technology of choice.
Well, security doesn't matter in your playframework application?
Why don't you use long-living cookies?
Hope it helps!
In an intranet context with ActiveDirectory and workstations registered in the domain, the HTTP SPNEGO Negotiation support is the best option. But it requires specific skills around ActiveDirectory and Java Kerberos implementation.
Spring Security provides implementation and documentation to set it up. But Secure.Security is not designed to support token-based authentication like HTTP Negotiation. So using Spring Security will require a specific integration module.
Other options are OpenID and shibboleth but both requires a dedicated server, which can be configured to do SPNEGO itself. Thanks to available Play modules, integration in your application will be easier.
The only way to get the username in an HTTP header without client-side complex and unsecure/unreliable tweaks is to use an authentication proxy between browsers and your application server. Most of these proxies also support Kerberos SPNEGO as authentication mean.
Non-heavy answer
It sounds like it should be possible to get your ops team to implement a Group Policy which will send the logged-in username down the wire as an HTTP Header.
Otherwise, you're correct in your assumption that there is some sort of negotiation "dance" between IE and your server. See here. Perhaps you can fake this dance in your Play code.
Heavy answer
I know jCIFS and this example uses servlets and filters, but the important bits of code can be extracted and a custom Play Authenticator can be built (I can paste a Scala example override of play.api.mvc.Security.Authenticated , but your answer is tagged Java). You only need the request headers (not body) so it should be doable in an authenticator.
PS jCIFS seems to have had an update since your post, so I'm presuming you'd reconsider using hacking it. I'm wary of unmaintained libraries too, but sometimes they just reach a maturity and stability which alleviates the need for any more updates.
Active Directory uses Kerberos, so all logged in users should have a kerberos ticket.
A fast google found this:
https://blogs.oracle.com/wyllys/entry/kerberos_web_authentiation_with_apache
If you want the windows logon details, I think it's your only option.
You can try to use Shiro for enabling SSO in your application.
Shiro id independent of the servlets and since your framework does not support Servlets you can very easily go for Shiro.
You can create a Realm where you define the hashPassword.
You can configure the username and the hashPassword and ask the shiro to authenticate your user with the hashPassword.
You will then assign role for the user which will serve your purpose of SSO.
You can authenticate user for more than one application and hence when user logs into another application the shiro has already authenticated you and hence it will straight away log you inside the application..
You can go through the shiro documentation(exhaustive and you should be able to configure it on first go) from the following link:-
http://shiro.apache.org/
It provides you many out of the box functionality for authenticating and authorization along with security and Cryptography modules.
The username isn't sent in the header. Even if it was this shouldn't be relied upon as a savvy user could fake the values.
If NTLM would be a valid option for you Jespa might be a good alternative to JCIFS. Jespa (unlike JCIFS) supports NTLM v2, among other things. The limited version of it (up to 25 users) is free.
You can always get any header from filter. See javadoc for HttpServletRequest.