I am developing a web application using AngularJS and Spring (4.1.0.RELEASE) as the backend. Everything is currently working great. Now that the functionality is done, I would like to add Spring Security (3.2.5.RELEASE) to the project, to both authenticate, and then authorize all of the requests. As I am using Angular, all of my views are static, and never rendered by the server. Therefore, the typical Spring Security setup (with a login jsp), will not work. I have looked at many examples, and none fit my needs. I do not want to use any external frameworks like Jersey to help with the authentication, or any server-rendered views, e.g. jsps.
When I enable Spring Security, my GET requests still work fine, but my POST requests, such as my login requests, no longer work, and return a 404 error. The controllers are correctly mapped, and the URLs are valid, so I know it must have something to do with Spring Security intercepting the request and deeming it invalid. I am not sure why this is, but I think it may have something to do with the requests not having the proper headers and Spring's CSRF protection. I do not want to disable this protection. My question is, how can I define a custom login url with Spring Security, that will authenticate my login POST request, and then send back all headers necessary to enable future, authenticated requests?
EDIT: I have gotten the url to work. Is there any way to retrieve the CSRF token from an ajax call? My views are all static, and the server is first hit on the login request, so there are no jsps, and no way to get the csrf token from the server via the jsp tag libraries. The suggestion in the first answer assumes that we are on a jsp, which is not the case. Is there any way to allow CSRF protection, or do I need to disable it and perform my own request validation?
With Spring security enabled, you'll need to add the CSRF token to all POST, PATCH, PUT and DELETE requests. This can be sent in a request header and you should be able to use a GET request to get the token. The default header is X-CSRF-TOKEN=<tokenvalue>.
Source: http://docs.spring.io/spring-security/site/docs/3.2.0.CI-SNAPSHOT/reference/html/csrf.html
(This is an older version of the docs, but includes a very relevant section on Ajax and Json requests.)
If you want to disable CSRF protection for a specific URL, you'll need to write a custom RequestMatcher that excludes your login URL.
In XML configuration it would look like:
<csrf request-matcher-ref="myCustomRequestMatcher"/>
See: http://blogs.sourceallies.com/2014/04/customizing-csrf-protection-in-spring-security/
Related
I have a Spring Boot GraphQL application that is using Spring Security to authenticate via an OAuth2 provider.
Since graphql requires POST requests with query/mutations as request body; my initial unauthenticated request is a POST. This does not work with the default WebSessionServerRequestCache because it only caches the initial request if it is a GET request.
Is there a way to configure the application so that upon successful login, the user is redirected to the original POST request they made (including the body)? Or does this require a custom Request Cache implementation?
I should add, I found this issue: https://github.com/spring-projects/spring-security/issues/9690 which is basically the exact functionality that I'm looking for but for a different reason (SAML login). And it was closed because they determined they could do things differently for their implementation. However, this application of spring security to a GraphQL application seems common enough that I thought I might be missing something obvious.
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 learning Spring and trying to implement Springs Security. I am not able to understand how it works. I read tutorials from which I understood the following:
we have to configure web.xml for delegating proxy and pattern
we need to add intercepts to dispatcher-servlet.xml
When request is made it triggers intercepts but after that I am unable to understand how it works. It would be helpful if somebody could provide a list of steps to be followed. I am using Hibernate and Spring (both with annotations), I want to authenticate users using Hibernate.
A detailed article can be found here: Code Project Or a tutorial with MVC and Spring Security here.
I tried to illustrate the process a little bit:
The user sends a HTTP-Request to the server
The server processes the request according to the web.xml
The web.xml contains a filter (AKA interceptor) and passes the request through this filter.
Because the user is unknown/not authenticated, Spring Security does its best to get more details.Depending on the config, it
sends an HTTP header, so that a login popup pops up in the browser (client side).
redirects to a form where you can enter username and password.
does a lot of hidden interaction between server and browser to guarantee a "Single-Sign-On" (SSO)
Except for SSO the user enters her/his/its credentials and create an additional request.
Spring Security realizes the login attempt and authenticates the user against a
file with user and passwords
a built-in XML structure in a spring config file
a database
an LDAP
When the access is granted, it assignes the necessary roles...
...and redirects to hard-coded "home page". (Spring Security let's you adjust this behaviour.)
In your application you can check the authorization for certain actions
.....
The user clicks on "logout" or the session expires. With the next request the process starts again.
Annotations
I found a tutorial here (Link).
I understood/assume the following facts:
The filters still must be defined in the web.xml.
You can annotate your classes/methods with
#Controller (API)
#Secured (API)
#RequestMapping (API)
I admit that I only gave you a rough overview, because your question is not that specific.
Please let me know what you want to learn in detail (re-recognize users, authenticate against different resources, do a SSO, create a secured area on your webpage,...)
Spring uses a dispatcher servlet for delegating the request. Spring security filters the request and checks if a valid security context is established. If so the request is passed to the dispatcher and it passes the request forward to the corresponding controller. If no security context is established, Spring security intercepts the request which means he could manipulate the request before the diespatcher servlet could process it. During this interception the request dispatcher (Servlet Specification) will be assigned to forward the request to a login page.
I think you don't have to bother with xml anymore. Now you can use Spring Boot + annotation based configuration. One of the best tutorial I found is this one: A good spring security tutorial
There are some good step-by-step tutorials on how to integrate spring security. For example:
For Java config: http://jtuts.com/2016/03/03/spring-security-login-form-integration-example-with-java-configuration/
For XML config: http://jtuts.com/2016/03/02/spring-security-login-form-integration-example-with-xml-configuration/
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);
I'm hosting a REST web service in a Grails application, using Spring Security, i.e.:
#Secured(['IS_AUTHENTICATED_REMEMBERED'])
def save = {
println "Save Ride REST WebMethod called"
}
I'm calling it from an Android app. (Calling the unsecured service works just fine.)
To call the service, I'm manually building up a request (HttpUriRequest) and executing it with an HttpClient.
I'm wondering what the best practices are, and how to implement them... Specifically, should I:
Perform a login once, to retrieve a JSESSION_ID, then add a header containing it into the HttpUriRequest for each subsequent request?
Or (not sure how I would even do this) include the login and password directly on each request, foregoing the cookie/server-side session
I think I can get option 1 working, but am not sure if Spring Security permits (2), if that's the way to go... Thanks!
--also, there isn't any library I'm missing that would do all this for me is there? :)
Spring security does support both basic authentication and form based authentication (embedding the username/password in the URL).
A REST service is generally authenticated on each and every request, not normally by a session. The default spring security authentication (assuming you're on 3.x) should look for basic authentication parameters or form parameters (j_username and j_password) (in the form http://you.com/rest_service?j_username=xyz&j_password=abc).
Manually tacking the j_username/j_password onto the URL, adding them as post parameters (I believe), or setting the basic authentication username/password should all work to authenticate a REST service against the default Spring Security interceptors, right out of the box.
I will admit that I haven't tried this on REST services, though I do clearly recall reading exactly this in the docs as I did the same for basic page logins on spring security recently. Disclaimer over.
I think you can use a login-once-and-get-a-token method that's similar to how oauth works.
sending username and password across the network outside of secured channel(https/ssl) is a terrible idea. anyone on the network can sniff your request package and see the clear text password.
on the other hand, if you use a token method, since the token string is randomly generated, even the token is compromised, the worst case is someone can use the token accessing your REST API.
another solution is going through ssl tunnel(HTTPS). i have actually done a comparison and result shows: 80 requests/min(https) vs 300 requests/min(http)