I have a setup where Keycloak is acting as an identity broker. There are two Oauth2.0 Identity Providers configured in Keycloak.
A user goes to my app, is forwarded to Keycloak and is presented with two buttons. These buttons can be used to either authenticate with IdP 1 or IdP 2. Once the user is authenticated, keycloak will receive the JWT token and will issue its own JWT token to the client, enriched with claims from the JWT token received from the selected IdP. So far so good.
Now I have the usecase where my app will be embedded in another CRM platform. Let's say this CRM platform uses IdP 1. So a user is able to access the CRM and will authenticate through IdP 1. Then, the user can hit a button and get directed to my app. Of course we don't want the user to authenticate again with the same IdP but now first by going through Keycloak.
My question is, is there a way to let Keycloak use the IdP 1 token the user received when accessing the CRM platform in a way that Keycloak will enrich it and issue a JWT token just as it is done when the user would authenticate through Keycloak?
Consider implementing custom Authenticator that will sign on in Keycloak users that come from CRM. Our goal is to initiate SSO session in Keycloak.
Assume that when user hits button in CRM to got to your app, Keycloak will have access to some data provided by IDP1 that could be useful for identifying which user perform such action. So here we go:
User hit button "go to app"
User comes to App
App redirects user to Keycloak for passing the authentication
Your own custom implementation of Keycloak Authenticator will utilize information from IDP1 (you could utilize mentioned JWT token somehow)
Now SSO session in established and Keycloak redirects user back to your application
???
Profit
Also note that your will have to solve potential problem of session idle synchronization between Keycloak and IDP 1.
Keycloak development guide
Related
We have our own CRM portals and we want to offer OpenID based User authentication and authorization.
To achieve this we have decided to use Keycloak.
The flow we formalized is below and we are stuck due to may be not knowing much of the configurations inside Keycloak or may be its not possible.
User visits our existing CRM login page where he/she provides the username and password.
On click of Login the keycloak custom Identity provider should authenticate the user
Keycloak should receive the authentication success response and generate the JWT token
User is redirected back to CRM dashboard with the help of redirect_url configured in custom IDP.
What we have done till now,
Created a custom IDP inside Keycloak.
Configured all endpoints in this custom IDP
No custom authentication flow yet, all defaults i.e. First login flow is set to 'first broker login'
Challenges we are facing currently,
User on our CRM login page (Not the keycloak login form) and click on login button
The Keycloak login form is shown to user. We dont want any keycloak login pages. but instead the custom IDP endpoints should be executed and a JWT is returned back to redirected CRM application.
Is this possible to achieve the flow I mentioned above?
You need to adapt the browser Authentication Flow
Authentication -> Flows -> Browser
There you find the Identity Provider Redirector. Click Configure and specify a Default Identity Provider (you need the alias of your IDP there)
Normally all available IdentityProviders are listed beside the login form. But if a DefaultIdentityProvider is configured, KC immediately redirects to the external IDP.
I have two service providers set up with one IdP and users are required to be authenticated twice to access both services at the same time. From my point of view, this is not "SSO" and I am thinking that there might have been settings done incorrectly and I would like to see if the community here can provide me with directions and/or possible solutions.
Just a thought - the behaviour for the authentication on each service looks valid as I understand that IdP is required to send signed SAML assertions to the providers in order to access the services. However, because I only have one IdP, can I not be authenticated just once and be able to access all the services?
Any suggestion is appreciated. Thanks.
Typically in this scenario the user would authenticate once to the IdP when the first SP SSO's to it. There would be no authentication at the IdP when the second SP SSO's to it as there's already an authentication session at the IdP for the user.
However, there might be use cases where you want the user to be authenticated at the IdP even if they already have an authentication session. The SP can set the ForceAuthn flag in the SAML authn request sent to the IdP. This requests that the IdP authenticates the user regardless of whether or not they already have an authentication session.
ADFS also has a configuration option for relying parties (SPs) to always require authentication. Take a look at the AlwaysRequireAuthentication flag.
https://learn.microsoft.com/en-us/powershell/module/adfs/set-adfsrelyingpartytrust?view=windowsserver2022-ps
My website have a Restful API, with authentication needed. When a user log-in in website, it's performed a HTTP Basic authentication (username and password), and is returned a access token generated in API.
But recently I have implemented steam login (Yeah, steam can act as an OpenID provider). Everything okay, but How can I auth the user on the API, if no password is sended.
You don't need an username and / or password to authenticate an user that login into your site using an OpenId provider (Steam, in your case). What you need is to trust in this OpenId Provider.
This is a very good definition about OpenId by John Christopher Jones in a blog post:
OpenID is an authentication strategy where an unauthenticated user
visits your site then authenticates themselves by logging in to
Google, Twitter, Facebook, Steam, or some other OpenID provider. Your
server (the OpenID Relying Party) exchanges keys with the OpenID
Provider (Google, et. al.) then sends the user over to the OpenID
Provider to log in.
After the user logs in with the OpenID Provider, the user is sent back
to you with some information identifying who they are, signed by the
key you exchanged with the OpenID Provider. You can trust their
identity at this point and start "logging them in" to your own system
based on their identity.
The image bellow shows the OpenId Flow:
As you can see, after verify credentials, the OpenId Provider (Steam) will send back the user to your website, including credentials in the URL. With these credentials in hands what you need to do is:
Verify if a user associated with this credentials already exists in the
database. If not, create it.
Create a API token associated with this user.
Send the API token for the user waiting on the browser (your client app that consumes your RESTful API).
With this API token in hands your client application can add these token to every request to your RESTful API, as the same way that an authenticated user with username and password would do. Note that your token generation strategy can not be dependent of a username and password.
So basically you want to make sure that the user is authenticated. Here Steam provides your server with a key (OpenID server) and your server has provided a key to the OpenID server. This is very similar to tokens used for Anti-Forgery attacks. Steam provides your server with the user's identification and your server notes down Steam server's location. Then the user is allowed to view your server`s content. Steam surely uses an API so if credentials are cached in the browser well it won't ask for them in the future.
Note: HTTP is stateless so you have to use sessions to make sure that a user`s is still logged on.
I am implementing a SSO using SimpleSAMLPhp Service Provider.
I provided my metadata to remote Shibboleth Identity Provider and was provided a test account.
When a user visits a specific page on my SP, they get redirected to the IdP, login, and are redirected back to my web site with a bunch of IdP provided attributes. This part works.
This part I am struggling with.
If the user authenticates with the same IdP through a different Service Provider and then visits my page, how do I know they are already authenticated? Currently I am being asked to login again.
Is there a configuration value somewhere that lets me do this? Or am I using the wrong method? This is what I am doing.
$as = new SimpleSAML_Auth_Simple({REMOTE_AUTHSOURCE});
$as->requireAuth(); // this redirects to remote IdP login
$attributes = $as->getAttributes();
Thanks.
There are two separate authentication sessions to consider. One session is in you app and the other is at the IdP. The requireAuth method can tell if the user already has an authenticated session in your application, and will return immediately in that case.
There is no way for you to tell if a browser has a session at the IdP. You just call requireAuth whichs send the user there and if the IdP decides the user's session is still valid it will respond without prompting for login.
Are you saying that the user has a valid session at the IdP and they are being re-prompted to authenticate when you send the user there? That could be due to IdP policy, or if your app was sending something like 'forceAuth' in its AuthnRequest.
I have a scenario where I have four to five web based application, which needs to have a common centralized authentication system, in this case how feasible is the SAML based approach i.e each time user want to access any of these web application the user is redirected to SAML server which in return redirects to the IDP, or is their some better solution for such architecture as I am new to the this domain
What you describe is exactly what SAML is designed to solve.
The user is normally only redirected to the SAML Identity Provider (Idp) on the first access to an application (a service provider (SP)). When the user is successfully authenticated by the Idp, the SP sets a cookie in the user's browser to handle authentication of subsequent requests.