Spring library with Service provider login page - spring

I have a requirement that needs to have login page at the service provider and I use java web app. Is there any way to use the spring SAML libraries to achieve this behaviour ? If so, what could be the steps? (it seems the default behavior of spring library is to redirect to IDP login page and I am not sure if we can configure to host login page on the service provider and relay that request to IDP)

I think what you're looking for is having two different ways to authenticate, one locally and one through SAML. I believe for having a login form, you would want to separate configurations with different AuthenticationEntryPoints, i.e. go to /login for local or /saml/login/alias/" + spAlias+ "?idp=" + spEntityID for direct login to SAML.
It sounds like right now you have SAML protecting any URL, which by default redirects you to the IDP since it's configured. The first step that I would take is getting user name and password authentication working with logins independently of SAML, then add SAML back in. Be sure to list whatever URL the login form uses as permit all so SAML doesn't kick in.

Related

Spring authorization server OAuth2 login from my own login page

I have a front end (angular) with login form, a back-end for that angular application as my OAuth client (spring dependency) then I have a third application that is the Authorization server and finally the forth is the ressources server.
So I want to know is there is any way to jump the redirect to /login from the authorization server?
I want to login the user with angular login page, then make a get with my OAuth client (spring) for the authorization code flow and then, since i'm not authenticated, instead of getting redirect, I want to get an error "401" and then send a post request with my OAuth client (spring) to the auth server again to login the user that have sent the data previously in angular login page.
Essentially I just wanted to login to my auth server with a custom page that exists in the front end application and let the backend build specially for that front, take over the flow.
You want seamless integration between login form and the rest of your Angular app? Share your CSS between Angular (public) client and authorization-server embedded (private) one, don't implement login in public client.
You might need to better grasp OAuth2 concepts.
Login, logout and user-registration are authorization-server business. Leave it there. Reasons are related to security and just being future-proof: what if you want to plug additional clients to your system (mobile apps for instance)? Are you going to implement login, logout and user-registration again and again? What if you have to introduce multi-factor authentication at some point? Would you break all clients at once?
Your "backend" (Spring REST API secured with OAuth2) is a resource-server, not a client. Make sure it is configured as so: depends on spring-boot-starter-oauth2-resource-server (directly or transitively). This is where the HTTP status for missing (or invalid) authorization is handled. The way to do it depends on your resource-server being a servlet or reactive app. The libs in the repo linked just before do what you want by default (401 instead of 302).
In your case, client is Angular app. I hope you use an OAuth2 client lib such as angular-auth-oidc-client to handle:
authorization-code flow (redirects to authorization-server, back from authorization-server with authorization-code and tokens retrieval with this authorization-code)
refresh-token flow (automatic access-token refreshing just before it expires)
requests authorization (add Bearer Authorization header with access-token on configured routes)
What my Angular apps do for login is just redirect users to authorization-server "authorization" end-point and then just wait for a redirect back to "post-login URL" with an authorization-code. How this code was obtained is none of their business (can be a login form, a "remember-me" cookie, some biometry, etc.).
Also, I have to admit that I don't use Spring's authorization-server. I prefer mature / feature-full solutions like Keycloak, Auth0, Okta, etc. which come with much more already implemented: multi-factor authentication, integration with LDAP, identity federation for "social" providers (Google, Facebook, Github, etc.), administration UI, ...
As ch4mp said, it's best to leave all the authentication and authorization logic and pages to the Spring Authorization Server, it's pretty easy to customize and configure all the user accessible pages (login, authorize, etc...) with Thymeleaf, you only have to bring in your CSS to unify the design.
There was a great demo in last year's Spring One which seems like something you'd like to achieve, you can find the code in this repo.
They used Spring Cloud Gateway as a means to run the Angular SPA in the flights-web app, configuring it as the OAuth client. Following this path you can route all calls to your backend API through the gateway's WebClient.

Spring SAML SSO do not share session

I have configured WSO2 Identity Server as IDP and have two applications configured as SP. All working fine, except few things:
when I logged out from one application, another application don't see, that I was logged out
when I login into one application, another application don't see, that I was logged in
IMHO, there is main principles of SSO and SLO.
When I check SecurityContextHolder.getContext().getAuthentication() there is no changes after logout or login in another app.
Maybe I should call WSO2 page /samlsso before every load url?
What can I do wrong? How to retrieve from another app, that user logged out/logged in?
EDIT:
For example, WSO2 API Manager Store have such mechanism:
when I logged out from my application and reload Store page, then going redirection to main not logged page in Store. Same with login.
UPDATE:
I found problem in class org.springframework.security.saml.websso.SingleLogoutProfileImpl. When logout request is coming from WSO2 IS, than objects Authentication and SAMLCredential are nulls and error No user is logged in is occured, but for real user still logged in in Spring SAML application.
Same discussion was here, but with no effect :\
You have to verify whether both apps are calling Identity Server (IS) using the same host name. E.g. https://is.blahblah.com/samlsso.
IS session is based on cookies ('commonAuthId' and 'samlssoTokenId' cookies to be specific). If apps are calling IS using two different host names, there will be two different sessions created at the IS side. For SSO and SLO to happen both apps must share a single IS session.
We are using travelocity.com and avis.com web app for test SAML2 sso. You can found the more details here[1]. Further you can checked this documentation[2] Registering the two service providers in the Identity Server and followed the 1 to 8 steps.
[1] https://docs.wso2.com/display/IS500/Configuring+Single+Sign-On+with+SAML+2.0
[2] https://docs.wso2.com/display/IS500/Customizing+Login+Pages

Spring Security SAML extension ADFS

I've been working whit the SAML extension to connect to an ADFS server. I've hacked the sample application to use my ADFS server and everything went well, but I would like to know if there is a way to connect to an IDP without using the loging page of the IDP. I mean if there is a way to do this process in background for the end-user. I am thinking about doing a query to ADFS or something like to get the users and do authentication from the SP login page, avoiding the need for the user to authenticate in the IDP login page.
The purpose of federated authentication is to delegate it to a centralized server in such a way that the relaying parties/service providers do not have access to user's credentials. Enabling authentication directly in your application would violate this principle and for this reason is not supported by neither Spring SAML nor ADFS.
If you want to authenticate your users directly, use authentication directly against Active Directory instead of ADFS. This will fully support your use-case.

In GWT: how to bookmark a page and be able to be redirected to it after authentication?

I have implemented an OAuth2 authentication mechanism in my GWT app. The OAuth2 server is based on Spring framework 3.x (using its Spring security OAuth2 implementation).
I am using the OAuth2 "Authorization code flow" to get the user authenticated (though implicit flow may have been a better choice in our case). So at first, the user is redirected to the OAuth2 server authentication page, he enters his credentials and if he is successfully authenticated, he is redirected back to a url with an oauth code. He will then make a second call to get an access token from the OAuth2 server.
Now, the issue is, we would like the user to be able to bookmark a page in the application and directly access it. If he has already authenticated then he would have direct access to it (no more auth involved). Otherwise, he would have to go into the OAuth2 authentication flow but in the end, should be redirected back to the bookmarked page he intended to access at the beginning.
How can I store this page url and get redirected to it after the user successfully authenticates ?
any help would be appreciated. Thanks!
EDITED
The initial url redirection is done via javascript's document.location.href
The way to maintain the original URI in an OAuth 2.0 Authorization Grant flow is to pass it in the state parameter so that the redirection endpoint can use it, after it exchange the authorization code for an access token, to redirect the user back to that URI.
FYI, this is exactly what Google suggests in the examples in their OAuth 2.0 documentation, e.g. https://developers.google.com/accounts/docs/OAuth2Login
Original answer:
The problem is using the hash part of the URL for the place, which is not sent to the server and thus cannot be used in the redirection to the OAuth2 server authentication page.
You have 2 (maybe 3) solutions:
stop using the hash for the place and switch to HTML5 History; either through gwt-pushstate at the History level, or a custom PlaceHistoryHandler.Historian if you use the Places API. That limits your audience though: http://caniuse.com/history
stop using an HTTP redirect, and instead use JavaScript so you can put the hash in the OAuth2 redirect_uri. So instead of redirecting, send an error page with the appropriate scripts bits.
some browsers append the hash to the URL after a redirection, so your OAuth2 server might be able to pick it (in JavaScript) and append it to the redirect_uri. That might depend on the HTTP status code used for redirecting (from experience, it works with a 301, but you don't want a 301 here). Needs testing.
You can do this using GWT activities and places.

Spring security, AJAX and SiteMinder

I am implementing Spring Security login and I am trying to understand something, here is the scenario I want to implement:
For initial login show login page and let user in.
If after some inactivity session expired and user makes some action show him popup window to authenticate (js-based popup in browser). Continue with the action like there was no login form.
Implementing form is easy, but how do I make the popup work - let's say I make the request to some protected URL after session expired, how do I make sure it's not forwarded to login page, but to my login handler that shows popup window?
Another issue - I need to integrate with SiteMinder, so I would need to read the Login/Password combination and after it's read, forward to SiteMinder for authentication, after that's done I want to return without forwarding.
Answer to SiteMinder issue:
Siteminder is generally installed on a Webserver behind your servlet container.
Also, Siteminder manages the authentication and an application does not have access to a user password at all.
To integrate with Siteminder use this filter:
http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#d0e6295.
Answer to the login with the popup issue: since you need to integrate with Siteminder, I would not recommend to implement the login via the popup.
The sample given on the above springsource website is quite primitive and can break in several use cases. Using the SM_USER header alone has several caveats, see my answer here: How to validate SM_USER header in Spring Security preauthentication for siteminder
CA SSO aka SiteMinder, as well as other traditional html-form-request-response SSO systems, have a hard time dealing with Single Page Applications and protecting the web services that you invoke via AJAX, without breaking the flow of your application.

Resources