Can we implement Single Sign On (SSO) using offline cookie in Keycloak ?
I have application 'A ' connected to Keycloak 7.0.1 (KC) server for authentication. KC generates the active session and offline session for user under 'clientA' and returns access token & offline token to user. Offline token has validity of say X days. So when user tries connecting to application 'A" again it uses offline cookie to get the access token and user gets authenticated. So authentication is working using that offline cookie for Application 'A'.
Now I have another application 'B' , lets say it is hosted on same or different domain. KC is able to access the same offline cookie but it doesn't allow the authentication. The client for this application is 'client B'. The error which I get is "Session doesn’t have required client"
Looking at error and reading at articles I understood that two different clients cannot access same offline cookie. But still I wanted to know do anyone came across this scenario and what was the way used to allow both the applications to use same offline cookie or does we have any keycloak configuration which is missing .
Editing this question:
Can we have any REALM level Offline Token instead of creating different offline tokens for each client in realm ?
The keycloak is there to generate the credentials for the different applications, you need to create a second client in the same realm for the application b (you say you have already done that).
I do not think that you can use the access token from application a to application b. Maybe you could do that depending in the way that you generate the token if the two applications share the same private key, but if you do that then probably you do not need keycloak.
Then make an authorization request in this client, since you already have a session in keycloak this should happen automatically and generate the credentials that you need for application b.
To see if this works correctly, I would try to login directly in application b, go to keycloak, login there and see if the token provided can log me in application b.
Sorry for the high level response, but your question is also quite high level itself.
Related
On their Getting started guide, reference, Spring Authorization Server have a piece of code where they declare two beans - UserDetailsService and RegistredClientRepository. I wanted to play around retrieving some tokens from the server. I tried using postman. Within authorization tab I entered the values from the guide:
it answered with:
So then I tried inputting client credentials from RegistredClientRepository entry:
And it worked.
So my question is: what is the purpose of UserDetails and RegistredClient being both available in this case?
And another little bit off-topic question: if I create my own authorization server for client credentials flow between my servers, how does every server know that token belongs to legitimate server and not to some attacker who can just register with needed clientId if there's an opportunity? How can resource server actually verify that token owner is the server it trusts?
Generally in oauth2, a "client" is an application which users might use to interface with some service - for example something like an App people can install on their phones or a web application.
Most oauth2 implementations have "scopes" (basically defined sets of access rights). Clients (client applications) are registered with some metadata (name, author, ...), a set of scopes they might use and some details to improve security - like "where is that application hosted" (in form of "which redirect URIs are valid"), client ID and client secret.
Depending on the oauth2 flow chosen, your App needs to prove being that app by some means - e.g. by having a valid combination of client ID and redirect URI or by doing HTTP basic auth with their client ID as username and client secret as password when exchanging a "code" for a "token".
All this was about clients - now about users: they are what you would expect, the users of a service - like you and me are users on Stackoverflow.com
And another little bit off-topic question: if I create my own
authorization server for client credentials flow between my servers,
how does every server know that token belongs to legitimate server and
not to some attacker who can just register with needed clientId if
there's an opportunity? How can resource server actually verify that
token owner is the server it trusts?
for this you could either use a form of signed tokens (look at e.g. JWT) or store the currently valid tokens per user in a database reachable by all your servers - both have pro's and con's, tokens in a database are easier to revoke, while signed tokens don't require you to store any state in a database (which can be expensive in big distributed systems)
Update - OP actually wants to do server-to-server authentication, see comments below
Server-to-server authentication can often work very well without any extra authentication server, in cases where your parties a less dynamic - like when you always have "those three servers" and they don't come and go very often.
In such cases, using a simple token is probably better and easier than using an oauth2 stack. Each server could just have a list of randomly generated strings in its config file, let's call this "the set of valid tokens" and also knows which token to send when communicating with a specific other server. When a request comes in, the server checks if the given token is in its set of valid tokens - done.
I'm in in process of looking to create an Android app; security is obviously the most important thing to keep in mind.
What is the best-practice for authenticating a user and handling business logic (scenario below).
For example, the current design would facilitate the permissions based on the user's login. When a user logs in and successfully authenticates, their Username and Password are stored in session variables. When the user attempts to request a resource that requires a certain permission to view, as part of the process for accessing the resource their Username and Password is sent up to the intermediary Web Service, if this authenticates with the correct permission-set the resource is then accessible.
Is this a reasonable way of operating an Android application or is there a better solution to handling this?
Thanks.
Presumably you're referring to building some sort of web API such as REST API that the Android App would send requests to and the API performs the database actions.
I wouldn't send the username/password combo for every request that tends to be bad practice. You send the user/password combo once to authenticate and the authentication returns some sort of token and this token is then sent in every request and is validated on the API side to ensure it is a valid session token. You could either roll this yourself or use some sort of Single Sign On (SSO) solution such as Google Sign on for example or OAUTH is a common authentication mechanism. Maybe https://oauth.net/ will help.
I have 4 single page applications with same technologies: Spring MVC, Spring Security, Angulajs.
Each application has own ldap authentication and authorization. We want to build a single sign architecture and make a central authentication application. And make the other 4 application use this central application.
When user login into one of the apps, he should not need to login the others.
What is the easy way to implent this in server side and client side?
What you want is Single Sign-On (SSO). There are two options:
Use some existed SSO server like CAS.
Do it yourself using subdomain cookie technique.
First option is exactly what you want implement. When you open URL of app1 you will be redirected to SSO server and prompted for login/password. After successful authentication you will be redirected to app1 URL. Now if you open app2 URL you will be signed in automatically. One of advantages is that user password is stored only in SSO server.
Second option is more lightweight IMHO, because instead of using existed SSO server for sharing authentication information between your apps you use HTTP cookies. From the other side you need to write some minimal authentication code which may be less secure.
Subdomain cookie technique:
Use subdomains for all your apps (app1.domain.com, app2.domain.com)
When user connects to app1, generate some token (your session id), store it in some shared DB and as a cookie for domain.com
When user opens app2, check if token is present (as a cookie for domain.com), verify that it is valid (use shared DB) and allow access.
It is very simple algorithm that do not take into account all possible security vulnerabilities (like session fixation for example). So if you do not have enough time to solve them it may be better to go with first option.
We use the username-password grant to connect our JS client to our REST server. In a way the token returned by oauth/token is our session, as it allows access to the backend for a limited time.
We would like to refresh that session/token every time we make a request to the backend using the token.
I know there is this refresh token issued by the server and I could use it to refresh my token after it has expired.
The thing is: I don't want to make it the client responsiblity to catch token expired exception and re-authenticate or schedule a refresh prior to token expiration. I want the token to refresh itself until it is not used any more for a limited amount of time - just like a session. (I also wouldn't like it to issue a refresh request with every "data" request, though I think I remember reading, a refresh token is only valid once..?!)
Is there a way to do that in spring security or will I have to build some custom implementation of the token store or whatever part I choose?
Since I can't really find an answer (hence the post) I'm thinking: Maybe it is not wise to do this, though I can't think why. If I can steal the token, I can steal the refresh token as well. So I guess I don't really see the point in having a refresh token in the first place..
EDIT
In response to Luke Taylor's answer I'll clearify our use case.
We have a REST server that holds application data like persons. but also provides access to our content management and allows clients to post to facebook. It encapsulates application logic and data storage
We have a fully fledged client application already in place that has its own security layer and justs accesses the data on our REST server via client credentials flow. Who can do what is decided on the client side
We have several medium and small applications like a contact app on facebook that access the data on the REST server also using client credentials
We are now developing a client application using only javascript that will access the REST layer to do all the stuff the big client application does but also needs to provide a means to authenticate individual users and allow multi tenancy. Therefore this new client application uses the username-password grant to authenticate and method level security to authorize the users
So we have a REST server that needs to provide complete access to our trusted application that does its own security stuff and that same server needs to provide access for users of our new multi tenancy javascript client application. In production we will have several REST servers each with its own database but the core will always be the same, so in theory one server should be able to handle all.
I want the token to refresh itself until it is not used any more for a limited amount of time - just like a session
This doesn't really make sense (in an OAuth2 context). The access token is issued by the authorization server, which decides how long it is valid for. It is "used" at a resource server, which may be completely separate from the authorization server, so there is no facility in OAuth2 to connect usage with the lifetime of the token. It would in theory be possible to hack something together which made this work, but it sounds like a bad idea.
If I can steal the token, I can steal the refresh token as well. So I guess I don't really see the point in having a refresh token in the first place..
The access token is used repeatedly and sent by the client to servers other than the authorization server. The refresh token is retained by the client and only sent back to the authorization server. A client also has to authenticate to successfully use a refresh token, so the client id and secret would also have to be compromised.
It's not really clear from your question why you are using OAuth2. You should probably expand your question to clarify this. If there is only one client and a REST server, why not just use something like BASIC auth over HTTPS?
Also, is the client a browser-based app? If so, the username/password grant isn't really suitable for use in an untrusted client.
We are implementing Single Sign On [SSO] across multiple applications, which are hosted on different domains and different servers.
Now as shown in the picture, We are introducing a Authenticate Server which actually interacts with LDAP and authenticate the users. The applications, which will be used/talk to Authenticate Server are hosted across different Servers and domains.
for SSO, I can't use session variables, as there are different servers and different applications, different domains, a domain level cookie/session variable is not helpful.
I am looking a better solution which can be used for SSO across them. Any demonstrated implementation is existing? If so, please post it or point me in the right direction for this.
You can achieve this by having all your log-ins happen on the auth server. The other applications can communicate to the auth server through a back channel. The general principle is like this:
User accesses application 1.
Application 1 needs the user to sign on, so it sends a token to the auth server through the back channel. Application 1 then redirects the user to the log in page on the auth server with the token as a parameter on the request.
User logs in to auth server. Auth server sets a cookie, flags the token as authenticated and associates the user details with it. Auth server then redirects user back to application 1.
Application 1 gets request from user and calls auth server over back channel to check if the token is OK. Auth server response with user details.
Application 1 now knows that the user is authorised and has some basic user details.
Now this is where the SSO bit comes in:
User accesses application 2.
Application 2 needs the user to sign on, so it sends a token to the auth server through the back channel. Application 2 then redirects the user to the login page on the auth server with the token as a parameter on the request.
Auth server sees that there is a valid log in cookie, so it can tell that the user is already authenticated, and knows who they are. Auth server flags the token as authenticated and associates the user details with it. Auth server then redirects user back to application 2.
Application 2 gets request from user and calls auth server over back channel to check if the token is OK. Auth server response with user details.
Application 2 now knows that the user is authorised and has some basic user details.
There are some existing implementations of this method, for example CAS (Central Authentication Service). Note that CAS is supported out of the box in Spring Security. I would advise you look at using an existing implementation, as writing your own will be hard. I have simplified things in my answer and there is a lot of potential for introducing security holes if you're new to this.
I will recommend you check out OAuth. It is a good Authenticaiton and Authorization protocol used by several large organizations including facebook, google, windows live and others. It may have an initial learning curve, but it is a production grade solution.
It also has libraries for Java, Ruby, PHP and a range of other programming languages.
For example, the following server side implementations are available for Java.
Apache Amber (draft 22)
Spring Security for OAuth
Apis Authorization Server (v2-31)
Restlet Framework (draft 30)
Apache CXF
Following client side Java libraries are also available:
Apache Amber (draft 22)
Spring Social
Spring Security for OAuth
Restlet Framework (draft 30)
Please refer here for more details:
http://oauth.net/2/
http://oauth.net/documentation/
The bigger question is how you are implementing single sign on. Many open source and even proprietary (IBM Tivoli) offerings worth their salt offer cross domain single sign on capability. This would be the easiest and best way to implement cross domain sso. You can configure the LDAP server you use in the sso server you choose.
Taking for instance open sso, here is an article to configure cross domain single sign on
http://docs.oracle.com/cd/E19681-01/820-5816/aeabl/index.html
To configure LDAP in open sso,
http://docs.oracle.com/cd/E19316-01/820-3886/ghtmw/index.html
Reference on the issue is presented in a neat diagram here
http://docs.oracle.com/cd/E19575-01/820-3746/gipjl/index.html
Depending on which offering you use, you can configure cross domain single sign on.
With this, your diagram will look like this, with the auth server being your utility to interact with sso server of your choice.
Having an auth server that communicates with sso is a sound architecture principle. I would suggest making calls to authenticate as REst end points which could be called via http from different applications.
You cannot use Rest Service .
You could use what i call a Refferer Url Authentication
Say you have a Authentication application running on www.AAAA.com
In the applications , where you want to authenticate , you could have a filter which looks for a authenticated cookie in its domain else redirect to www.AAAA.com for authentication
On Successfull authentication , you could pass the user profile information as encrypted GET / POST data back to the application
Since I have built a Java application, I have been looking for an SSO solution for it. I found a free Java SAML Connector using which you can achieve SSO in java based applications built using any java framework.
Here's the link to it - https://plugins.miniorange.com/java-single-sign-on-sso-connector