We have multiple services in our environment.
There are scenarios where we want the user to auto-login/silently login to one or more participating services without being challenged by the Identity Provider for credentials or communicating with the Identity Provider after the first successful login from one service.
For Eg, we have a front-end UI App which we want to be authenticated using Spring Security SAML. And when the UI App communicates to back-end services we want the security context/assertion response to be propagated automatically to subsequent service calls.
Perhaps, the invoked services/app can validate the Assertion Response accordingly and allow access to their services/applications without having the all the services/apps to communicate directly with Identity Provider every time they need to be accessed.
Is there a way to propagate the SAML Assertion response obtained after successful authentication with Identity provider from one app/service to other downstream apps/services which are being invoked from the SAML authenticated app/service.
I tried to register 2 apps with Identity Provider and then authenticated one with IdP successfully, but am not not able access the other App successfully from the first one. I get an error message when I use Spring's RestTemplate to hit the service as below.
I am not sure if all downstream apps/services should be registered with IdP or not.
I get an error message as below in the first app after it has successfully authenticated with Idp and when it is trying to invoke another app which is also secured with Idp.
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
</head>
<body onload="document.forms[0].submit()">
<noscript>
<p>
<strong>Note:</strong> Since your browser does not support JavaScript,
you must press the Continue button once to proceed.
</p>
</noscript>
<form action="https://dev-305397.oktapreview.com/app/mncdev305397_memberapp_1/exk6jc1rntqWvSkWD0h7/sso/saml" method="post">
<div>
<input type="hidden" name="SAMLRequest" value="PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgQXNzZXJ0aW9uQ29uc3VtZXJTZXJ2aWNlVVJMPSJodHRwOi8vbG9jYWxob3N0OjQwODAvc2FtbC9TU08iIERlc3RpbmF0aW9uPSJodHRwczovL2Rldi0zMDUzOTcub2t0YXByZXZpZXcuY29tL2FwcC9tbmNkZXYzMDUzOTdfbWVtYmVyYXBwXzEvZXhrNmpjMXJudHFXdlNrV0QwaDcvc3NvL3NhbWwiIEZvcmNlQXV0aG49ImZhbHNlIiBJRD0iYTMzMzI4MjgzNTBmMmlkNDFoM2QxYjhiYjMwOWM2NCIgSXNQYXNzaXZlPSJmYWxzZSIgSXNzdWVJbnN0YW50PSIyMDE2LTA3LTI2VDA2OjI4OjI0LjcxNFoiIFByb3RvY29sQmluZGluZz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmJpbmRpbmdzOkhUVFAtUE9TVCIgVmVyc2lvbj0iMi4wIj48c2FtbDI6SXNzdWVyIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj51cm46dGVzdDptZW1iZXI6cmVhZHl1c2VyPC9zYW1sMjpJc3N1ZXI+PGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PGRzOlNpZ25lZEluZm8+PGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3JzYS1zaGExIi8+PGRzOlJlZmVyZW5jZSBVUkk9IiNhMzMzMjgyODM1MGYyaWQ0MWgzZDFiOGJiMzA5YzY0Ij48ZHM6VHJhbnNmb3Jtcz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjc2hhMSIvPjxkczpEaWdlc3RWYWx1ZT5IZ2ZRcm9pdUpRZFRqWS9uN1VENnJQSythazQ9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8+PGRzOlNpZ25hdHVyZVZhbHVlPkFGYUxJRDJicnRmQXNBbzY5RzhYcVdXbFVDSzByL3NxZXM1dlMvRThRUnQvL3EvdEZLR21xVm9XdFNmZnBlL3UyY0twZWFqMzNqM0NodzNGc0xkbzBtZ1JQYlU2ZFVGTk9BNkVYVEYyeEgzbXdYY1M4VUNRem10bnZoY0N6QUlDS0pSM3R0ZU83OWZiTisrZU4vYTQ0a1VoN2pydVZINUFBWmtVNTI4RHNCMkwvOTZnYzJKVmFkUlA3bUVEc0ZleTFPUmhmOXpUTWswZHZsSnpIRFNFd3JCOXZuWkhsZlEzSmNmZ05PYmIvNlJNaW9yRXJUK1l1NU5jOW41aC9iRkF1Vyt6SzNWcTg4WWZ1ZzNyeEsxbVZnMjM1U2VGSXJtRXd2aVBJTkkwNmFxNmlUaTVSOHo3MFdoN2l5c1BqUnh3bit5YVpkZ2dEUXhMbFY2NUlVOFI1UT09PC9kczpTaWduYXR1cmVWYWx1ZT48ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE+PGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlEVWpDQ0FqcWdBd0lCQWdJRVVPTElRVEFOQmdrcWhraUc5dzBCQVFVRkFEQnJNUXN3Q1FZRFZRUUdFd0pHU1RFUU1BNEdBMVVFDQpDQk1IVlhWemFXMWhZVEVSTUE4R0ExVUVCeE1JU0dWc2MybHVhMmt4R0RBV0JnTlZCQW9URDFKTk5TQlRiMlowZDJGeVpTQlBlVEVNDQpNQW9HQTFVRUN3d0RVaVpFTVE4d0RRWURWUVFERXdaaGNHOXNiRzh3SGhjTk1UTXdNVEF4TVRFeU9EQXhXaGNOTWpJeE1qTXdNVEV5DQpPREF4V2pCck1Rc3dDUVlEVlFRR0V3SkdTVEVRTUE0R0ExVUVDQk1IVlhWemFXMWhZVEVSTUE4R0ExVUVCeE1JU0dWc2MybHVhMmt4DQpHREFXQmdOVkJBb1REMUpOTlNCVGIyWjBkMkZ5WlNCUGVURU1NQW9HQTFVRUN3d0RVaVpFTVE4d0RRWURWUVFERXdaaGNHOXNiRzh3DQpnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDWHFQMHdxTDJBaTFoYWVUajBhbHdzTGFmaHJEdFV0MDBFDQo1eGM3a2REN1BJU1JBMjcwWm1wWU1CNFcyNFVrMlFrdXdhQnA2ZEkveVJkVXZQZk9UNDVZWnJxSXhNZTI0NTFQQVFXdEVLV0Y1WjEzDQpGMEo0L2xCNzFUdHJ6eUg5NFJucVNIWEZmdlJOOEVZL3J6dUV6cnBackhkdE5zOUxSeUxxY1JUWE1NTzR6N1FnaEJ1eGgzSzVndTdLDQpxeHBIeDZObzgzV05aajRCM2d2V0xSV3YwNW5iWGgvRjlZTWVRQ2xUWDFpQk5BaExReFdod1hNS0I0dTFpUFEvS1NhYWwzUjI2cE9ODQpVVW11MXFWdFUxcXVRb3pTVFBEOEh2c0RxR0cxOXYyKy9OM3VmNWRSWXR2RVBmd1hOM3dJWSsvUjkzdkJBNmxubDVuVGN0WklSc3lnDQowR3Y1QWdNQkFBRXdEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBRlF3QUFZVWpzbzFWd2pEYzJreXBLL1JSY0I4Yk1BVVVJRzBoTEdMDQo4Mkl2bktvdUdpeEdxQWNVTHdRS0l2VHM2dUdtbGdiU0c2R241Uk9iMm1sQnp0WHFRNDl6UnZpNXFXTlJ0dGlyNmV5cXdSRkdPTTZBDQo4cnhqM0poeGkyVmIvTUpuN1h6ZVZISEx6QTFzVjVod2wvMlBMbmFMMmg5V3lHOVF3QmJ3dG1rTUVxVXQvZGdpeEtiMVJ2YnkvdEJ1DQpSb2dXZ1BPTk5TQUNpVytaNW84VWRBT3FOTVpRb3pEL2kxZ09qQlhvRjBGNU9rc2pRTjd4b1FaTGo5eFhlZnhDRlE2OUZQY0ZEZUVXDQpiSHdTb0J5NWhMUE5BTGFFVW9hNXpQRHdsaXh3UmpGUVRjNVhYYVJwZ0lqeS8yZ3NMOCtZNVFSaHlYbkxxZ082N0JsTFlXL0d1SEU9PC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PC9kczpTaWduYXR1cmU+PC9zYW1sMnA6QXV0aG5SZXF1ZXN0Pg=="/>
</div>
<noscript>
<div>
<input type="submit" value="Continue"/>
</div>
</noscript>
</form>
</body>
</html>
I am using okta as the Identity Provider for my sample application.
From the error I see it is asking us to make a AuthN request to the Identity provider as it is not done directly from the browser but through code.
Can someone help me on the right way to approach this problem, so that I can successfully authenticate with one app (SP) and pass the security context/assertion response to subsequent apps/services which are involved in that flow.
Thanks,
suser
What I think you're looking for is a way to have a user login to any of the apps using the Okta IDP and be able to navigate to any of the others without being prompted for credentials again. Trying to send the assertion intended for one SP to another is not going to work. The signed SAML request includes where the request came from and where it's intended to go. You'd have to disable that portion of the security in order to get it to work and it would ultimately compromise the security of your applications.
You could have a single app configured with SAML that can act as the entry point. This project handles the SAML portion and could be extended
to allow users to login to other apps without being prompted for credentials by combining it with JWT and cookies.
This can be accomplished through cookies issues to your domain that will be included in each subsequent request. This project is an example of stateless security that also uses cookies to allow the user to close the tab, and navigate back to the app and still be logged in. In theory, you could extend this behavior to multiple apps if the cookie is issued correctly, i.e. *.example.com If the other apps are configured to use the same cookie, the behaviour you should see is what I think you're looking for.
Hope this helps.
One solution to have the SAML User Authn Context propagation is by using IdP-Proxy (chain federation).
Okta-IdP <---> Your IdP-Proxy <---> Your SP-Apps
IdP-Proxy is a SAML-to-SAML gateway that sits between an IdP and an SP (as shown above). IdP-Proxy must have an SP component (so it can talk to the Okta-IdP) and it must also have an IdP component (so it can talk to the your SP-Apps).
You can configure your IdP-Proxy with Okta IdP, then configure N-number of SP-apps to your IdP-Proxy and it can talk to Okta-IdP directly to authenticate user. Then Okta send SAML Assertion to IdP-Proxy, IdP-Proxy verifies it, generate a new SAML Assertion particular to the requested SP-App and send that assertion across to the requested SP-App.
Check this for more info.
Related
Does ORY Hydra currently have a feature that verifies if a client is logged in via OpenID Connect? I notice there is an API to logout via front-channel
When a user revisits the identity provider, however, I have no way of knowing if they are currently logged in or not. They could delete their client-side HTTP cookies and then I am out of sync with Hydra. Meaning: Hydra has them as logged in, but I have them now as logged out. Also, in the event of a back-channel logout, I want to be able to query for this state.
Is there an API I am overlooking that allows me to know whether a client currently has an active OpenID Connect login via Hydra?
It appears as of right now the only thing one can do is redirect the user to the authorization endpoint since we have no way of knowing if they are authorized or not.
The following two tables that ship with Hydra seem to be the source of truth for the data I am after: hydra_oauth2_access and hydra_oauth2_authentication_session. Does it ever make sense to query those directly if there is no supported HTTP API out of the box to see if a user has an active authentication session?
Sending an authentication request via a redirect to the Provider including prompt=none addresses this use case: it will silently login and return new tokens if there's an ongoing SSO session at the Provider, it will return an error code login_required if not.
Notice there will never be explicit user interaction in both cases so this is convenient (and meant) to run in an hidden iframe.
LOGGED IN STATE
An OAuth client is most commonly a UI application with multiple users. Each user's logged in state is represented by an Authorization Server session cookie that neither the application or user have access to:
The Authorization Server (AS) issues an SSO cookie, to be stored in the system browser for the AS domain
Both Web UIs and Native UIs send it implicitly on subsequent requests, when they invoke the system browser
AUTHORIZATION REDIRECTS
When an OAuth UI redirects the user, it is generally unknown whether:
The user will be prompted to login
The user will be signed in silently (eg the user could have signed in to another app)
For a Web UI it is possible to send an authorization redirect on a hidden iframe with a prompt=none parameter. If the user needs to sign in a login_required error code will be returned. See my Silent Token Renewal Page for further details.
This is not fully reliable however, and has some browser issues in 2020. Also it may be unsuitable if you are using a different type of client.
FEDERATED LOGINS
In some setups the AS redirects further to an Identity Provider (IDP), and the user's login state is further influenced by an IDP session cookie.
There is no way for an app to get hold of the user's IDP login state, since the app only ever interacts with the AS.
IS THERE A USABILITY PROBLEM?
If so, post back and we can discuss further ...
I've been following the really simple instructions here ("Integrating Google Sign-In into your web app").
<script src="https://apis.google.com/js/platform.js" async defer></script>
<meta name="google-signin-client_id" content="YOUR_CLIENT_ID.apps.googleusercontent.com">
<div class="g-signin2" data-onsuccess="onSignIn"></div>
Although it does work in Chrome 83, I get warnings in the JavaScript console about third party cookies. And indeed, when my users, some of whom have third-party cookies disabled, try the Login button, it flashes a window and nothing happens.
In the documentation under Troubleshooting, it says "If many of your users have this feature enabled ... another workaround is to implement server-side OAuth 2.0 flows."
OK. So what do they mean by server-side OAuth 2.0 flows?
(FWIW my app is a React single page app).
There's general information at https://developers.google.com/identity/protocols/oauth2/web-server. Here's one way to do it:
Your app provides a link to your users to log in. This link goes to https://accounts.google.com/signin/oauth?response_type=code&client_id=CLIENT_ID&scope=openid%20email&redirect_uri=REDIRECT_URI&state=STATE&nonce=NONCE where the capitalized words are:
CLIENT_ID - registered as part of a Google Cloud Project you own, using the Cloud Console (currently under APIs & Services/OAuth Consent Screen)
REDIRECT_URI - a URI in your application that must be registered in that project
STATE - I use this to hold the eventual URI I want my user to be sent to
NONCE - to prevent replay attacks
When the user navigates to that URI, they are taken through a Google signin process. On successful signing, they are redirected to REDIRECT_URI?state=STATE&code=CODE. STATE is the STATE you provided in the earlier link, CODE is an authentication code.
Your app processes the request to that REDIRECT_URI by making a server-side POST request to the Google OAuth token service at https://oath2.googleapis.com/token, passing the CODE, CLIENT_ID, CLIENT_SECRET (provided in the Cloud Console when registering the application), REDIRECT_URI, and GRANT_TYPE (the string authorization_code).
The JSON response to that request will include a field called id_token. That id_token is a JWT that includes, among other things, the user's verified email address in the sub field.
You can then establish your own session with that user information, and set a first party cookie for it. You can verify and parse that JWT with a Google auth library or a third party library.
Respond to the REDIRECT_URI with a redirect response that sets your session cookie, sending the user to the appropriate part of your app.
This is pretty verbose, but I did the above in a sample application I created and it worked for that. I hope it can be adapted to your needs.
I have created a Single Page Application with Angular and authentication/authorisation is managed by Azure AD. I have used MSAL.js to initiate the implicit flow.
Everything is working fine, but now my client wants to use her own identity provider (IDP) so that users have a single point of entry for all apps (including mine). This IDP is not mainstream, it is built in-house by the client;
I want to keep using Azure AD to manage authorisations (groups, roles...). I also want my application and its dedicated backend API to be registered in Azure AD, not in the third-party IDP.
Azure AD should remain responsible for providing the Access Token to the SPA in order to call the API.
Somehow, I should redirect the user to the third-party IDP login form and upon successful login it will redirect to my SPA, which should then associate the tokenID with an AzureAD account and retrieve the Access Token (I suppose I will have to create an account in Azure AD for users identified in the third-party provider)
However I'm having a hard time figuring out how to achieve this and if it is at all possible ?
What would be the recommended approach for this scenario ? Can I still use MSAL.js or do I have to rely on something else ?
ARCHITECTURE
Your goals are completely correct and you should not need to change a single line of code to integrate a new IDP - so you can continue to use MSAL.js.
PREREQUISITES
In order to integrate their own IDP into your system you need to insist on certain prerequisites:
The client needs to provide a Standards Compliant Identity Provider
Typically the IDP needs to communicate with your Authorization Server (Azure AD) via either Open Id Connect messages or SAML2P messages
A home grown IDP may not meet these prerequisites in which case you need to explain to the client that they need to get standards compliant.
HOW FEDERATION WORKS
Your UI will redirect to your AS
The AS will redirect to the IDP, when given a trigger
The user will authenticate in the IDP
The IDP will post a token to your AS to identify the user
The AS will issue another token to your UI
Note that there is no coding involved here - there is only standards based integration between vendor systems.
WHAT THE CLIENT WILL GIVE YOU
Client details are often supplied by giving you their metadata document, and these details are then configured in Azure AD as a trust entry:
The entity id of the IDP
The token signing public key for IDP tokens, so that your AS can validate them
A URL to redirect to
WHAT YOU WILL GIVE THE CLIENT
A similar trust entry will need to be configured in the client IDP so that it trusts requests and issues tokens - though no certificate is usually needed here:
The entity id of the AS
A URL to post tokens to
TRIGGERING THE REDIRECT FROM THE AS TO THE IDP
One option is to forward the entity id to the authorization server in Open Id Connect redirects. Often an 'idp' query parameter is used, something like this:
Client accesses your app with a bookmarked URL:
https://app.mycompany.com?idp=urn:client.com
You add an extra parameter to the Open Id connect redirect to tell it where authentication should happen:
https://login.mycompany.com/authorize?client_id=XX&idp=urn:client.com
AZURE AD SPECIFICS
Once you understand the high level process there is some technical stuff to configure the connection and you'll need to consult vendor documentation, such as this Microsoft Azure B2B article.
PRACTICE
If you haven't done this before then you need to invest some time to get a connection working and then document the process.
You can use Windows Server and ADFS to simulate a client connection, then integrate it as a SAML2P connection. There is a learning curve though, and you'll need infrastructure such as ADFS certificates.
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'ld like to implement SSO using SAML 2.0 in my web applications. I have seen spring-security-saml example [https://github.com/spring-projects/spring-security-saml.git]. There are a couple of things I wanted to know after I went through this sample:
Do I have to redirect all the user-registratons to the registration page of IDP as in this sample ? If not, how does the IDP know the credentials of the user?
Do the IDPs' like ssocircle (used in this sample) allow us to use customized attributes and change password kind of scenarios ?
What is the best IDP to use to implement saml sso in my application ?
Thanx in advance.
Q. Do I have to redirect all the user-registratons to the registration page of IDP as in this sample?
In SAML parlance, an application can be an identity provider (IDP) or a service provider (SP). An IDP authenticates users, which means that user identities and credentials are maintained by the IDP. An SP provides one or more service to the user.
From your question, it seems that you want to delegate the task of authenticating users of your application to an external party (the IDP). Therefore, your application will be the SP.
With that established, you will have to redirect all users to the IDP for authentication. The IDP's authentication page may have a link to the registration page, if required.
Q. How does the IDP know the credentials of the user?
The user must be registered with the IDP (after all, the purpose of the IDP is to authoritatively authenticate a user's identity, which it cannot do if the user is not registered with it). Users can be self-registered or registered by an administrator, such as, a Microsoft Active Directory Domain Administrator.
Q. What if I need to register the user in my system as well since I need to assign them roles specific to my system?
You can create your own implementation of org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler wherein you can check the authenticated user on successful single sign-on and register them with your application. Supply an instance of your implementation class as the redirect handler to the SAML entry point.
Do note that you will not have access to the user's password since that is stored by the IDP.
Q. Do the IDP's like SSOCircle allow us to use customized attributes?
SSOCircle is mostly a testing service for SSO (single sign-on). Although SAML supports custom attributes, SSOCircle only supports FirstName, LastName and EmailAddress (as of February 2016). Therefore no, you cannot use other custom attributes with SSOCircle.
Actual IDP's like Okta, OneLogin or Microsoft ADFS do support custom attributes. You must check their respective documentation for configuring and exchanging custom attributes between the IDP and the SP.
Q. Do the IDP's like SSOCircle support change-password kind of scenarios?
I am not sure about SSOCircle but an actual IDP will be a system that already has user identity management capabilities. Since password change is a common functionality for an identity management system, this should be supported with an actual IDP. However, you should consult the documentation for the actual IDP you use to make sure.
Q. What is the best IDP to use for my SAML application?
An IDP is not a product or a specification, making this question somewhat invalid. It is simply a type of actor in the SAML universe. If your users are part of a Microsoft Windows Active Directory forest, you can use Active Directory Federation Services (ADFS) to exchange SAML messages between Active Directory and your (SP) application(s).
If you want to support multiple Active Directory forests, or if you do not know in advance where your users will be, you can use delegation-based services like Okta or OneLogin, which allow your application to take incoming assertions from the delegation service.