I'm not expert on this subject.
On Keycloak on the same realm we have defined two client ID.
My client ID are configured with OpenID connect and authorization code flow.
Like this a user can be authenticated with its credentials over these clients.
I have a problem. One of my user shares the same Keycloak session between these two differents client ID. In the fact, when user log on client A, he is logged out of client B. And same when he logs in client B, he is logged out of client A.
Why it's possible to share the same Keycloak session? And how to be sure to have two different Keycloak session.
UPDATE: I noticed, when the user logs in over client A or client B, he uses the same browser. If he logs in over client A, he doesn't need to enter its login/password over client B. The result is there is one Keycloak session. (If user uses different browser of each client, there is one keycloak session by client). Is it possible to force, one keycloak session by client ID?
What you are describing is a basic function in almost all AM software implementing OIDC, there is no such a thing as log in to clientA, the users always log in to the IDP, i.e. Keycloak.
Clients dont have sessions by default, keycloak does, and clients use keycloak session in thier OIDC flow. For example if you are already authenticated to keycloak, and you tried to do OIDC flow with ClientA or ClientB, you wont be prompted to enter username/password, keycloak will use the existing session.
So if you want to have different session for the same user, then you have to create your own session, for example if your clients are using apache, you can use apache oidc module to create a local session ( which will be your ClientA session), as for keycloak session, you cant have two sessions, but you can have one keycloak session for the two clients and two apache session for each clients.
Related
My understanding of an Oauth2.0 Server is that it grants clients access to resources when the resource owner has granted permission to a client. So say I have a user Bob and he's given permission to two clients (client1, client2) to access his stuff. As part of that Bob logs in 2x. Once like so:
http://10.234.233.23:9081/oauth/authorize?client_id=client1&response_type=code&scope=all
and he gets an auth-code -> FIbSqy
and again like so for the second client
http://10.234.233.23:9081/oauth/authorize?client_id=client2&response_type=code&scope=all
and again he gets a second auth-code -> h4ckJQ
He hands those auth-codes off to app1 and app2 respectively. Then those clients log into the oauth server and exchange those auth-codes for tokens. Then ever after the tokens are used to make calls and get resources.
My question is how the heck do you authenticate two clients at once on the auth server when the auth server appears to cache the first person's credentials and then never lets anyone else login.
Because for me the first client to exchange an auth code for a token...gets tokens and every other sorry client afterwards gets the following error:
I know you can register clients...and I have them all registered with the outh server...but is there also a "login" url that I'm missing that lets them all login at the same time?
OAuth supports state. This is recommended to prevent cross-site request forgery. This state can be used to support multiple logins simultaneously.
http://10.234.233.23:9081/oauth/authorize?client_id=client1&response_type=code&scope=all&state=some-big-random-number-string
I've a site which will hopefully use a third party service for logging in (through use of OAuth2 and OIDC). I understand 90% of the process involved but am failing to get what I see as the final step. I'll describe the steps as I see them here and maybe someone can help me fill in the gaps. In my set up the Resource Server and Authorisation servers are the same machine.
This is the login process as I envisage it.
User comes to my site (let's call it Site A) and clicks login
They're redirected to the authentication site (Site B) where they
input their username / password.
Assuming correct credentials they're then redirected back to Site A with an auth code.
Site A takes this auth code and in a back channel communicates with Site B
again asking to exchange the code for a token.
Site B provides an access token to Site A (not to the end user, to the server)
Site A then communicates with Site B again (Resource and Authentication servers are the same in this scenario) and gets the relevant user detail.
So the user is authenticated and we know what claims they have, however, what I don't get in the above scenario is how Site A knows who I (the end user) am.
I never logged in on Site A so presumably no cookie was set. Basically I've gone to the site, been redirected to another site, logged in there and then am redirected back to Site A but is there a cookie set at that last redirect to identify me?
I've read plenty about this online but haven't found a clear answer.
Also, am I correct in thinking that in authorization code flow that the access token never gets to the user but instead resides on the application server?
If you really want to know who the user is on SiteA, it has to be the user from SiteA's own user database. It makes sense if SiteA is not just a proxy for SiteB's API and has its own users, permissions and functionality.
To figure out who the user is on SiteA you will need to match all your SiteA's users with Auth Server's users.
Part 1. Import your existing users into Auth Server
If you control Auth Server, import all your current users into its user database. Every one of them will have Subject ID (Id on Auth Server side). Copy those IDs back to corresponding users in your SiteA's db: your SiteA's User table will have new column, for example:
userid, user_name, user_last_name, user_auth_id (new column)
if you can't import all your users, it gets complicated. The only way I can think of: you will have to log those users in twice - once into OIDC provider and once in SiteA and then associate SiteA's user with OIDC user.
Part 2. Matching the incoming user to the internal user in SiteA
In successful response from OIDC Server you will get ID Token back. It contains sub claim with Subject ID of the user. When you've got that, you will need to do a lookup in your internal DB and find a corresponding SiteA's user. If you did not find one, create a new user at SiteA (if all existing users had been imported)
Once you know who the user is, log them in to SiteA like you would normally do (give them a cookie for example).
OpenID Connect auth servers provide the userinfo endpoint, which Site A can use for getting info about the user who authorized the access token (or the authorization code). For the auth provider (Site B) to be able to do it, it needs to keep association between a token and its user. So there is no cookie for this purpose.
You are correct about the auth code flow - the access token stays at the backend - there is no need to send it to the frontend / user.
To be able to pair the tokens kept at the SiteA backend with the consequent requests from the browser, you have few options:
You can use a backend session with cookies, which is very easy, because most backend frameworks have a built-in support for it. The cookie is sent automatically with each request and the tokens can be stored in a session object. This solution may be harder to scale - if you need a cluster.
You can create your own session implementation - either by using cookies or by some identifier expected on REST API as the Authorization HTTP header value. The backend session data can be kept in some distributed storage, such as Hazelcast or database. The session identifier can be in form of signed JWT, so you can keep user info in it.
I am working on an application in which users with elevated roles (administrators) can create other users (with lower roles). I'm using PHP (Slim framework) and MySQL.
So far i have a Resource Server which can be accessed through a REST API with access tokens obtained from the OAuth Server using the Password Grant. The two servers have separate databases. There is also a Web Server which provides a dashboard where administrators log in and create new users by setting their username, password and other generic information.
Considering the fact that both the Resource Server and the OAuth Server have to store user data in their respective db tables, would it be ok if the Resource Server, upon a new user request, stores the generic user info in it's "users" table AND sends a request with the user credentials to the OAuth Server which will add a new entry in it's "oauth_users" table ? If not, what would be the best and secure way to achieve this functionality ?
Thank you in advance!
This approach works for us.
On the Auth Server db side you have to store only: user id, redirect url's and authorized service level (scopes) configured; the access tokens granted; and other authorization required data (roles in your case).
The Login Server db, stores: user id, password and other authentication related data.
The User resource service (commonly a RESTFul API) should store: user id and other personal data.
Upon a new user request of a secured resource data (some scope is needed here), redirects to the Login Server, with this successful authentication, redirects to the Auth Server to grant permissions using that scope, generate an access token and redirect to the secured resource with an access token, the resource server validates the token and the scope (some implementations also make another call to the Auth Server to validate this using JWT) to finally allow the initial user request.
In general, I personally use the DRY principle with this kind of architecture.
Cheers!
I am exploring keycloak for my project SSO solution, and I am trying the open-connect on this blog https://developers.redhat.com/blog/2017/05/25/easily-secure-your-spring-boot-applications-with-keycloak/
And I would like to as one question about Single Sign Out, I would like to know what’s the principle behind. Tried to search online document but I didn’t find any clue .For a while, I was thinking there is no elegant solution for Single Sign Out in oauth2 world.
This is the way Keycloak implements it (yes, this is not part of OAuth):
when you use Keycloak to create a server side session in your application using the Java Client, Keycloak will trigger a logout of the session once the logout at Keycloak is triggered. You'll need to set up an Admin URL for your application in Keycloak. This is called "backchannel logout" in the documentation.
When you use Keycloak in a HTML5 client, Keycloak will create a hidden IFRAME that will check that the Keycloak-Cookie is still present. If it is not, the HTML5 application knows that you have been logged out.
OpenID Connect Back-Channel Logout seems to be the way to go nowadays. It works by exposing a special end-point in your application (backchannel_logout_uri), which will be invoked by the OpenID Provider when the user logs out from SSO. Through this endpoint, the Provider gives you a signed Logout Token, to notify your application that the user's session should be terminated.
Because a user may be logged in from multiple devices, browsers, etc., the OpenID Provider can also include a Session ID (sid claim) as part of the Logout token. You can compare it with the sid that you would have received in the ID Token during login, to decide which session to terminate.
The standard back-channel logout was implemented in Keycloak 12.0, which shipped in December 2020. Earlier versions only implemented an alternative, proprietary mechanism.
I would like to provide some standarized SSO mechanism in my application (some different clients, growing number of services in the backend). I am wondering if OIDC/OAuth 2 is the right tool for it.
In all examples I have seen, end user is the Resource Owner and it grants permissions (or not) to some external apps by redidericting to a page asking for permissions.
My use case is different, I want to use OAuth inside my system (for apis, web pages etc.): resource owner is i.e. some service with database (plus administrator who have access to it), end user tries to get some resources from the system. User cannot grant anything, he can be granted. I think it's the most classic scenario, which can be named Single-Sign-On. Is there any standard flow for this in OAuth 2 (or preferably OpenId Connect)? Is it achievable? Or am I looking at a wrong tool?
OIDC/OAuth can be used for both consumer as well as enterprise scenario's. The consent steps of OAuth are useful in consumer oriented scenario's. When dealing with enterprise scenario's like yours, there's no point in asking consent since it is implicit, at least for the enterprise's apps. That is certainly covered by OAuth/OIDC: the Authorization Server is not required to ask for consent and can (typically) be configured to skip that step for particular Clients. So: using OpenID Connect without consent would be suitable.
For your usecase you can use combination of OpenID Connect and OAuth Client_Creds flow. For example suppose you have a HRMS application which needs to get the employee data to show to the employee from some DB.
Register HRMS with OPenID Provider
Register HRMS as Client to OAuth Server (OpenID Server and OAuth Server can be same)
When User comes to HRMS application:
a. Check for Id_token cookie, if not present then redirect to IDP
b. IDP authenticates and if successful redirects back to SP with ID token
c. If token is valid then SP sets the token as cookie in the browser using another redirect to itself but to the home page
Now All processing will be server side:
a. HRMS app hits the IDP to get the User Data
b. If successful then it hits the OAuth Server to get the access_token
c. if successful then it uses the access_token to talk to DB Service and
get the data
SP=Service Provider, IDP = Identity Provider
Actual flow can be a little different based on security considerations.
Hope this makes it helps.