I'm trying to make a webapp that will run on a single HTML page that will allow users to interact with the server through JavaScript and ajax. I'd like to make my requests safe against csrf attacks by including a csrf token in each request.
Because my webapp will only be operating on a single page, I can't use the ${_csrf.token} (or something like that) syntax in the view because the view is going to be a json object. Instead I'd like to have a url like "/security/csrf" that returns a token associated with the user's session. (Yes, this won't be a restful service exactly.)
Is there some way for me to generate a csrf token that Spring Security will be able to access when verifying a log-in? And additionally, is there a flaw in using csrf tokens in this way?
Token per request will kill caching. Token per session is just as safe.
In your first html response, include the csrf token in a meta tag, like the docs say: http://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html#csrf-include-csrf-token-ajax
You can use the same token across requests (in the same session)
Related
While implementing Azure OAuth flow I have used state parameter, Azure docs says about state param:
A value included in the request that is also returned in the token response. It can be a string of any content that you wish. A randomly generated unique value is typically used for preventing cross-site request forgery attacks. The value can also encode information about the user's state in the app before the authentication request occurred. For instance, it could encode the page or view they were on.
So, My web application is already generating such unique string and that is a CSRf token (UUID). So I used the same CSRF token (UUID) and passed to state parameter. When response comes from OAuth provider I have crossed with the CSRF token from session.
But, recently security team in my company said CSRF token should not used in this way. According to them
A CRSF token is a secret that should not be shared. Using it as a state value is therefore improper use of the CSRF token and introduces a (small) security risk.
But, if I look closely at other normal (non-Oauth) requests then the same CSRF token is passed in request header, so I asked them that if CSRF token is secret then why it is being passed in request header that could also "introduces a (small) security risk." the answer I received is not convincing. Hence asking this question on this large forum:
Can we use CSRF token as a value for state parameter in OAuth request? Is there any security risk involve if we use CSRF token as state parameter?
I am developing a website using Spring Boot 1.5.7 as back-end and Angular 2 as front-end.
I am a newbie on both technologies, and it's the very first time I try to develop a website. So I am a bit confused on many things.
I have implemented user authentication through JWT.
When the user logins through credentials, the backend verifies them and then creates a JWT and returns it to the frontend: the token is added to the header this way:
Authorization - Bearer <jwt token>
In the frontend I check out if that key is in the post response. If it is there, I add it along with the username to the localStorage.
private authUrl = 'http://localhost:8080/login';
private headers = new Headers({
'Content-Type': 'application/json',
'Accept': 'application/json'
});
constructor(private http: Http) { }
login(username: string, password: string): Observable<void> {
let loginRequest = JSON.stringify({ username: username, password: password });
return this.http.post(this.authUrl, loginRequest, { headers: this.headers })
.map((response: Response) => {
let token = response.headers.get('Authorization');
// If token is not null, empty or undefined.
if (token) {
localStorage.setItem('jwt', JSON.stringify({ username: username, token: token }));
}
});
}
When the user is logged in, everytime he accessed a protected resource, a token will be retrieved from the localStorage and sent back to the backend for validation.
The whole thing works. JWT are immune to CSRF, so I can disable that in the back-end,
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
...
but I have read (for instance, here) that there are vulnerabilities when using localStorage.
In particular the localStorage is accessible through JavaScript on the same domain, exposing to XSS attacks.
To resolve it seems I could use a JWT Cookie. As written in the link before, I could set the HttpOnly cookie flag to avoid cookies to be accessed through JavaScript.
But, with cookies I am now vulnerable to CRSF attacks.
Now, here, I have read Angular 2+ provides built-in, enabled by default, anti XSS.
So the question is. I should use localStorage and just use the embedded Angular 2 anti XSS feature, or is that not enough and then I should store JWTs on cookies to get protection against XSS attacks and then implement on top of it some kind of CRSF protection backend side using Spring Boot configuration?
Thank you
EDIT: the website is a sort of shopping cart. The user can view almost all
pages, but to pay he needs to log in.
Aniruddha Das approach is fine but client application will lost the token if user will refresh the browser because DOM will be reloaded with browser refresh and all memory data including token will be lost.
Now come back to your approach-
Local storage - CSRF attack is not possible using this approach and application will be stateless but it is prone to XSS attack. By default Angular do the output encoding to prevent the XSS attack but risk is still there with server side Angular template. To mitigate the XSS attack, you can reduce the token expiry time and encrypt it, if there is some sensitive information.
Cookie approach - HTTP cookie will mitigate the XSS attack but you have to implement the CSRF protection. You have to use the API gateway pattern to make the application stateless.
Both approach have prons/cons and you have to select depending on your application. If your application is related to financial domain then I would suggest cookie based approach.
In angular you can hold your token in service and use it when ever it required. Like pojo in java in angular you can create a angular service with getter and setter to hold the token. Provide that service to the module and it will available in all component and directives.
The token will be in memory while the application is open in the browser and will be be stored in the browser.
I would say use a observable/Subject type variable so that it will wait until the token is extracted from server and use that to do stuffs.
As restful service stateless, it don't maintain any interaction of user, so i want to know if multiple user accessing same restful service, then how restful service identify which user interact with which method ? and is it possible to make restful service as stateful ?
Which user:
By using a shared secret (a line of chars), created on the server, and returned with every next request.
It's "saved" in a cookie and returned by the client, using either a cookie or a HTTP(S) header.
Which method:
This depends on the framework you use. But eventually it comes down to mapping URI's to your methods.
and is it possible to make restful service as stateful ?
You can make stateful apps, then they are not restful. A restful app is stateless. That's the definition, so you can make stateful apps, but you can never create a stateful rest-app, as rest is stateless.
tl;dr
The client must store its own session state and pass it around to the server in each request.
The stateless constraint
The stateless constraint of the REST architectural style is define as follows:
5.1.3 Stateless
[...] each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client. [...]
Authentication
If the client requests protected resources that require authentication, every request must contain all necessary data to be properly authenticated/authorized. See this quote from the RFC 7235:
HTTP authentication is presumed to be stateless: all of the information necessary to authenticate a request MUST be provided in the request, rather than be dependent on the server remembering prior requests.
And authentication data should belong to the standard HTTP Authorization header. From the RFC 7235:
4.2. Authorization
The Authorization header field allows a user agent to authenticate itself with an origin server -- usually, but not necessarily, after receiving a 401 (Unauthorized) response. Its value consists of credentials containing the authentication information of the user agent for the realm of the resource being requested. [...]
The name of this HTTP header is unfortunate because it carries authentication instead of authorization data.
For authentication, you could use the Basic HTTP Authentication scheme, which transmits credentials as username and password pairs, encoded using Base64:
Authorization: Basic <credentials>
If you don't want to send the username and password in each request, the username and password could be exchanged for a token (such as JWT) that is sent in each request. A JWT token can contain the username, an expiration date and any other metadata that may be relevant for your application:
Authorization: Bearer <token>
See this answer for more details.
According to my point of view Restful web service make as a stateless.it's architectural style which have set of constraints and properties so stateless is its properties we cannot change its properties so its doesn't mean that restful service is stateful .
we can mapped URI's to your method then restful know which user is calling which method.
I'm developing a web application (Back end : JAVA/ stateless REST API) (Front end : Angular) which eventually be placed inside another web application.(let's say parent app).
The parent app which is session based handles authentication by username/password and create token for each user. Once a user is able to login the parent application he or she should also able to access my application. It is good to mention the token can also be used to retrieve user data by a SOAP call from my application.
My idea is to get this token with my front end component and send it to my REST Api. I'm going to keep those tokens inside a concurrent hash map and for each call coming from FE I'll check the token on BE for authorization. I wonder if it is a correct approach?
When the parent app's session expires or the user logs out is the token invalidated?
If yes, how does your app know the token was invalidated? Is that the check the token on the BE? (which would need to be done for every request)
If a shared session is not an option then your approach is reasonable.
Also, for security the REST calls should always be HTTPS (refuse the request if not), and consider passing the token in a header instead of on the URL as a query parameter.
I went through a similar question here. But I am yet not clear over concepts. Here is my scenario...
My client (a mobile device app) has a login screen to enter username, password. After submission, he should see the list of books in the database plus the list of books subscribed by that user.
I am having a /LoginService which accepts username, password & checks a mysql database for credential validation. Only after authorization....I have a /BookService ; GET on which returns all the books in database.
Should I use GET, POST or PUT on my loginservice ? Since a login request is a read-only operation, I should use GET - but this sounds stupid for browser(as the submitted data is visible).
What are accesstokens (mentioned in the linked answer above), and how to generate them using Java ? I am using Jersey for development. Are they a secure way of authorization ?
Thanks !
As far as I understand you are trying to implement stetefull communication between client and server. So you login with first request and then use some kind of token to make further requests.
Generally I can recommend you to have stateless communication. This means, that you authenticate and authorize each request. In this scenario you don't need LoginRestService. Important points here are:
Client can provide userName and password through HTTP Headers (non-standard, something like UserName: user and Password: secret).
At the server side you can use
Use AOP: just wrap you BooksService with AuthAdvice (which you should write yourself). In advise you access somehow (with Jersey functionality) HTTP request, take correspondent headers from it, authenticate and authorize user (that you load from DB), put user in ThreadLocal (so that it would be available to the rest of your app) if needed and just invoke correspondent method or throw exception if something wrong with credentials.
Use Jersey functionality: (sorry I'm not very familliar with Jersey, I'm using CXF, but conceptually it should be the same) just create some kind of AuthHendler and put it in request pre-processing pipeline. In this handler you need tho make exactly the same as in AuthAdvice
Now each of your request would be authenticated and authorized when it reaches BooksService. Generally stateless implementation is much better for scalability.
If you want to go statefull way, than you can just use HttpSession. LoginService.login() should be POST request because you actually making some side-effects at the server. Service will perform authentication of your user according to provided username and password and put loaded User object to session. At this point, the server side session is created and client has session ID in the cookies. So further requests should automatically send it to the server. In order to authorize requests to BooksService you still need some kind of Advice of Handler (see stateless solution). The only difference: this time user is taken from the HttpSession (you should check that you are logged in!).
Update: And use HTTPS! :)
I've got nothing to dispute in Easy Angel's answer, but got the impression you'd like some additional comment on the concepts too.
The problem is clearer if you think in terms of resources rather than services. Think of your proposed login as generating a new authorization resource, rather than querying a login service. Then you see that POST makes perfect sense.
The authorization token would be a key for your user into the session object (as explained in EA's answer). You'd probably want to generate it by concatenating some information that uniquely identifies that user and hashing it. I certainly agree that a stateless authentication method would be preferable, if you're aiming to get all the benefits of REST.
Use what is available in HTTP: HTTP AUTH over SSL.
Protect all your resources with HTTP AUTH and the browser will take care of providing a login for the user.
If you need session information on top of that, use cookies or a session parameter.
Cookies were made for exactly these kinds of purposes and usually work well.