Trying to setup a SSO for a Java web application built with Spring MVC.
I've registered my application to an OKTA server, got a Metadata URL and a SignOn URL. I'm using the SignOn URL from my application, authenticating with success, then a POST request is made with some form data that include a SAML Response object.
What should be the next step from here?
I've decoded the SAML response, and now from my understanding I need to get a token or a session ID that I'll need to use to my further requests to the OKTA server.
Edit 1:
Ran the spring-boot-saml-example, the authentication works as expected.
But, when trying to get the current session using OKTA Session API from the Spring application, an HTTP 404 code is returned. Fetching the current session using the browser work fine.
Take a look at this blog post, this example uses Spring Security and an Okta SAML app . Take a look at that, and if that doesn't help let us know.
You can use the spring-webmvc-pac4j security library which provides SAML authentication for Spring MVC (Boot) app.
Configuration is straightfoward for Okta like for any other SAML identity provider: https://github.com/pac4j/spring-webmvc-pac4j-demo/blob/master/src/main/webapp/WEB-INF/demo-servlet.xml#L44 + https://github.com/pac4j/spring-webmvc-pac4j-demo/blob/master/src/main/webapp/WEB-INF/demo-servlet.xml#L214
Related
Issue description:
Assuming I have one web application(Java+Saml2.0) who has a Sign in button to call ADFS(an identity provider) to authenticate.
It's using Javascript(Ajax has same issue) to call one endpoint of ADFS 2016. Since the request if sending from Javascript/Ajax, the browser would throw CORS error. (The ADFS2016 server side doesn't support modifying CORS header/response/origins)
And I heard from someone that one way to avoid the CORS error is to use redirect instead of using Ajax/Javascript to directly call one URL/endpoint.
Can someone give some insights for this situation? How can I modify my code to do such redirect without causing CORS?
PS: I don't want to lower browser security level to bypass CORS and I also don't want to upgrade to ADFS2019 though it supports customizing CORS origins.
Im not sure if you are trying to achieve some special case by using javascript like this. But normally when authenticating a using using SAML you issue a HTTP redirect from the backend as a response to the user clicking the login button.
To understand it all it is important to first understand the SAML authentication flow as I go through in this post.
The user triggers authentication by navigating to a protected page or in this case clicking a button
The application, or Service Provider(SP) in SAML speak, builds a SAML authentication request and sends it to the IdP by adding it as a URL parameter and sending a backend HTTP Redirect to the user. The authentication request can also be sent using HTTP POST explained here
The IdP authenticates the user in the way it sees fit.
The IdP send the user back to the SP using HTTP POST together with a SAML Response and SAML Assertion. This contain the result of the authentication as well as any extra information about the user.
The SP, you application, interprets the SAML Response and lets the user through to the protected application.
This redirect contains a encoded SAML authentication request in the URL that is parsed by ADFS to understand where the authentication request is coming from and how authenticates the user.
There are several libraries and frameworks for managing SAML trafic including the sending the messages using redirect or other methods. If you are using Java, Spring has SAML management as a part of their security framework. Another library is the PAC4J which provides a SAML module
While both of these work well for the most general use case of building a SP to integrate with a existing IdP, if you need to do more custom cases or build a IdP on your own OpenSAML can be an alternative.
OpenSAML is a more low level library for handling SAML. In this write up on my blog I show how to build and send a SAML authentication request using redirect from OpenSAML.
Below is a simplifies example for using OpenSAML. For a full example see the sample code here and here
The authentication request is build using OpenSAML
AuthnRequest authnRequest = OpenSAMLUtils.buildSAMLObject(AuthnRequest.class);
authnRequest.setIssueInstant(Instant.now());
authnRequest.setDestination(IPD_SSO_DESTINATION);
authnRequest.setProtocolBinding(SAMLConstants.SAML2_ARTIFACT_BINDING_URI);
authnRequest.setAssertionConsumerServiceURL(SP_ASSERTION_CONSUMER_SERVICE_URL);
authnRequest.setID(RANDOM_ID);
authnRequest.setIssuer(ISSUER);
authnRequest.setNameIDPolicy(NAME_ID_POLICY);
Add the message to a message context and set set destination
MessageContext context = new MessageContext();
context.setMessage(authnRequest);
SAMLPeerEntityContext peerEntityContext = context.getSubcontext(SAMLPeerEntityContext.class, true);
SAMLEndpointContext endpointContext = peerEntityContext.getSubcontext(SAMLEndpointContext.class, true);
endpointContext.setEndpoint(MESSAGE_RECEIVER_ENDPOINT);
Send the message using HTTP Redirect
HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
encoder.setMessageContext(context);
encoder.setHttpServletResponse(httpServletResponse);
encoder.initialize();
encoder.encode();
For those who want to dig in deeper I have have written a book on working with OpenSAML, A Guide to OpenSAML, as well as book on SAML as a framework, SAML 2.0: Designing secure identity federation.
I also have a ton resources on my blog
I am trying to secure my application using OAuth. I have client application(UI) build in react and back-end is in Spring Boot. I have an OAuth server configured which will be taking care of authenticating the user.
I am really confused if React application should talk to Auth server and get the token or Spring Boot should get the token.
After reading multiple articles I thought about flows:
User will go to ReactApp home page and ReactApp will redirect it to OAuth Server login page(/authorize)
OAuth server will authenticate the user credential and redirect the user to ReactApp home page with code
ReactApp will send the code to Spring Boot server using the API endpoint
Spring Boot server will use the code(along with client Id and client secret) and get the token from Auth Server and send that token to ReactApp for further communication
Question:
Is this the standard flow?
How secure the application is using this flow?
Is it a good idea to do some part in UI and another part of authentication in the backend ?(code in UI(ReactApp) and token in back-end(Spring Boot))?
Is there any better way than this?
Any help would be appreciated.
In one of my developments (using kerberos authentication to loginalong with HtmlUnit) its working fine in all cases , facing an issue after hitting SSO authenticated links where the SAML2 used.
I have searched all the way there is no proper explanation to get more info on SAML2 authentication for SSO secured pages.
I`m completely new for SSO authentication and SAML2 authentication,is there any separate API for this? help me to know on more on this.
Could you please help or suggest what is the best process to pass the user/password to get the authentication.
Thanks
Authentication itself is not part of SAMLv2 specification. SAMLv2 defines the exchange of information about authenticated subjects. Authentication happens at the SAMLv2 IdP. How this happens in detail is up to the IdP.
It could be that the following is possible in your case ...
Use HTTP POST to send credentials to the Login URL of the IdP. Capture the session cookie returned by the IdP. Send HTTP request to the endpoint of the IdP which allows so called IdP-initiated SSO and specify 'HTTP Redirect Binding' and the Meta Alias of the SP (this is the SSO-enabled app from SAML point of view). The IdP would return a 302 , follow the redirect, the SP should consume the SAML assertion included as a query parameter and you should be able to access the SSO-enabled app.
You may read SAMLv2 tech overview (http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0-cd-02.html) to get some idea.
I have a spring boot web app with spring security integrated with LDAP authentication. This web app internally makes REST calls. These REST calls are having username-password authentication. This username-password is the same used by spring security. Is there anyway I can get the username-password authenticated by spring security, so as to use in the REST calls. If not this way, is there any other way to achieve this.
Thanks in advance.
There is a quite nice way that I think fit your case.
By default Spring Security does not store the password in memory after authentication has been made, so you need to change that. With Java config, add in configure(AuthenticationManagerBuilder) method:
auth.eraseCredentials(false);
Then you can get the username and password for the current user with:
String username = SecurityContextHolder.getContext().getAuthentication().getName();
Object rawPassword = SecurityContextHolder.getContext().getAuthentication().getCredentials();
Spring Security is performed based on the rule in the security properties.
This means that you just need to have spring-security enabled, the only problem is that if not authorised it will go to the Not Authorised Page which a Restful client will not understand. But if the Restful client has authenticated and been granted a valid session then it will be able to get past the Security_check and access the protected page.
I guess Spring security is working like AOP so each protected page has a Security_check crosscut that only allows access to the page if the authentication is there.
Anyway, I solved the problem writing a custom AuthenticationProvider, which will perform the LDAP authentication and get the username-password for the future REST calls.
I'm going to rewrite my previous question.
Glassfish redirects after form login to the last accessed resource, how do I go about to turn this off?
Our problem is that we get 415 in FF and IE because if I have a JSESSION cookie Glassfish will redirect to the last resource I tried to access but does not switch content type from (x-form-urlencoded).
Pseudo example (requests are the browsers' XMLHttpRequest):
GET /secure/resouce1 (json) -> Response "you're not logged in."
GET /login.xhtml
POST /j_secure (x-form-urlencoded) -> New location /secure/resource1 (x-form-urlencoded)
GET /secure/resource1 (x-form-urlencoded) <- HTTP ERROR 415 content type not JSON.
You will probably need to write a Filter to check for and catch that case. I like this tutorial (hoping the translation to English is understandable).
In my opinion it is better to use Basic or Digest authentication over SSL for RESTful services. Other options are including the credentials as part of the payload or creating a dedicated login service, which accepts credentials and returns a token. There are various reasons why form based authentication is less suitable for RESTful service: it requires a session, it does not use the existing HTTP Authorization and more.
If you need to call your RESTful service using AJAX then using a cookie for authentication can be a valid solution. They should only affect if the user can make a call, but not how the server responds.
If you would like to keep using form based authentication for your application I would suggest adding an additional JAAS authentication provider which will handle the RESTful services authentication. You can read more about it here.
Another option, which should be easier than JAAS, would be using Spring Security or Apache Shiro instead of the container based authentication.
Here is an example of configuring form based authentication with Spring Security. This post shows an example of how to secure RESTful services using Spring Security.
in your login page
reset the JSESSIONID cookie to prevent redirect last page
// login_form.jsp
Cookie jsess = new Cookie("JSESSIONID", null);
jsess.setMaxAge(0);
jsess.setPath(pageContext.getServletContext().getContextPath());
response.addCookie(jsess);