I'm setting up a simple authentication service for my angular website using Spring for my backend and I have a following problem.
When I send a cross domain get request with credentials (REST controller on backend), I get authorized by Spring Security, I get a JSESSION cookie and all is fine. What's not fine is that the cookie isn't saved and I can't access it in any way I could think of to save it manually.
Am I missing something here? If you need additional information, I'd be glad to provide it.
#Edit
I have Set-Cookie header in my response:
(...)
Server
WildFly/8
Set-Cookie
JSESSIONID=CODE; path=/PATH
(...)
Related
I'm at a loss - I have a django backend and react frontend. On the frontend, I have a login page that sets a JWT token, and I use that token to query data from the django backend. This all works perfectly.
But I also have direct views to these APIs via something simple as http://localhost:8000/tables/data which will just show me a default django view of these tables (ie: a paginated "select * from data" call) ... and hooked in through a genericListAPIView.
Now, as I said, everything works fine when feeding it via a curl command (or postman, or whatnot). I get the JWT token, set it the Authorization access in the subsequent call to the API, and get the data back and do something with in in React.
What I can't seem to figure out is how to hoo that same JWT token when calling trying to access the generic view. When I browse to it, I get
HTTP 401 Unauthorized
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
WWW-Authenticate: JWT realm="api"
{
"detail": "Authentication credentials were not provided."
}
Which I guess make sense since I'm not going through any React authentication. Yet, it's the same server. Should be same authentication (and in fact the login accounts are being managed by django).
I've googled, and read (and tried) a bunch of different things and can't seem to wrap my head around what I am doing wrong. Any help, or any direction, would be much appreciated.
When you make a request from a browser, you can only rely on session cookies. The browser is not able to automatically add an access token to the request. In order to make a request with an access token, you have to make it using Javascript.
I have a backend using Java which produces JSON for the services, which client will need to login/be authenticated using cookies based (JSESSIONID in Java).
I manage to receive JSESSIONID from server, however concecutive $http.get from client does not include previous generated JSESSIONID which I supposed to be automated handle by $http ?
The case:
Step 1
When I tested my login page using $http.post using valid user id and password, I can get an expected result from my server, I can get a generated JSESSIONID from the server, i.e.:
set-cookie:JSESSIONID=0a624257d0f704840bf6d8c8cc31; Path=/tmh-web; HttpOnly
(pls refer to screenshot in Response Header)
after call Login & been auhthenticated screenshot
Step 2
After been authenticated, when tried to call another URL service which requires authentication, I got an error: "403 Forbidden"
And I suspected this is because $http does not send the JSessionID it has received on Step 1.
(pls refer to screenshot in Request Header, there is no JSessionID has been sent back to server)
call next service which requires authentication
Has anyone experienced this problem with Java as the backend server ?
Use / for path attribute of the cookie.
I have two web apps, one for the Web UI in AngularJS and one for the REST webservices in Java. Both are deployed on separate domains.
The applications uses cookie for authentication. Whenever user enters a valid username and password, server returns a http only cookie back containing the token and that cookie is passed across all requests. I have enabled CORS on both apps, thats why the session cookie is working properly.
Now, I am trying to add CSRF protection for this. I was trying to use the csrf cookie where in the server will send the csrf cookie(not httponly) as part of REST response and the UI will read the value from the cookie and pass that in a csrf token header for the other REST calls.
The problem with this approach I am facing is that since the server is in different domain, I cannot read the cookie using $cookies in AngularJs. Is there a way to read a value of that cookie?
If not, then can I implement CSRF in some other way?
I also tried to implement the creation of the csrf cookie on the Web UI itself in the browser but the browser does not send the cookie to the webservice as its in different domain.
So, my question is how to implement csrf protection for this kind of situation?
You were on the right track with this:
I also tried to implement the creation of the csrf cookie on the Web UI itself in the browser but the browser does not send the cookie to the webservice as its in different domain.
The CSRF cookie isn't meant to be "sent" to the server, it is meant to be read by the client and then supplied in a custom HTTP request header. Forged GET requests (triggered by HTML tags such as <img src="">) from other domains cannot set custom headers, so this is how you assert that the request is coming from a javascript client on your domain.
Here is how you can implement the idea you were working on, imagine you have api.domain.com and ui.domain.com:
1) User loads the Angular client from ui.domain.com
2) User posts authentication information from Angular client to api.domain.com
2) Sever replies with an HttpOnly authentication cookie, called authCookie, and a custom header e.g. X-Auth-Cookie, where the value of this header is a unique value that is linked to the session that is identified by the authCookie
3) The Angular client reads the X-Auth-Cookie header value and stores that value in a XSRF-TOKEN cookie on its domain, ui.domain.com
So now you have:
XSRF-TOKEN cookie on ui.domain.com
authCookie cookie on api.domain.com
4) User makes a request of a protected resource on api.domain.com. The browser will automatically supply the authCookie value, and Angular will automatically send the X-XSRF-TOKEN header, and will send the value that it reads from the XSRF-TOKEN cookie
5) Your server asserts that the value of X-XSRF-TOKEN is linked to the same session that is identified by the value of the authCookie
I hope this helps! I've also written about token authentication for Angular, Token Based Authentication for Single Page Apps (SPAs) (Disclaimer: I work at at Stormpath)
Angularjs has built-in support for CSRF but unfortunately it doesn't work cross domain, so you have to build your own.
I managed to get it working by first returning a random token in the headers and cookies on the first request. In order to read the header you need to add it to Access-Control-Expose-Headers. This is then added to all posts
$http.get('url').
success(function(data, status, headers) {
$http.defaults.headers.post['X-XSRF-TOKEN'] = headers('XSRF-TOKEN');
});
Then on the server you can compare the cookie value with the value in the header to ensure they are the same.
$http docs : Angular provides a mechanism to counter XSRF. When performing XHR requests, but will not be set for cross-domain requests.
This is a small lib put together might help you https://github.com/pasupulaphani/angular-csrf-cross-domain
I have a problem with communication between angular and laravel.
Its about mobile application that needs to log in to a laravel framework and get some data.
Mobile application is angularjs based, and for login i user standard $httpd function.
Login works fine, and i get expected response from laravel, but when i make another request assuming that im loged in, laravel returns NULL for session and auth. When I upload mobile app to a server where laravel is installed all works like a charm. But my app needs to be on mobile device, so thats not a solution.
I assume that the problem is in cors or cross domain communication. It seems that laravel destroys session made from cross origin requests, because that session is not accessible from another request, and on another request laravel tries to make a new one.
I need help solving that session problem (access session after login or keep session), i hope some of you have some kind of a solution.
i tried :
changing headers in my login controller
changing get to post
adding content type to my angular http req (Content-Type': 'application/x-www-form-urlencoded)
tried requerst with jquery ajax
changed laravels app/config/session.php values of driver, cookie, domain...
setting vendor/laravel/framework/src/illuminate/http/frameGuard.php x-frame options to false
no luck!
Use json web tokens, and simply set it up so that you request a JWT on login, and you can share that token around - the only way it invalidates, is either if you lose the token, or it times out.
What I have:
-API Rest in Symfony2 using friendsofsymfony/rest-bundle exposing some resources.
-Oauth2 server in Symfony2 using FOSOAuthServerBundle.
-Client in Angular.js doing requests to the API Rest. This client currently gets to login via the authorization code grant (using Hello.js with a custom module), and gets the access token effectively.
I want these API resources secured, so:
-On API Rest app: I implemented the AuthenticationEntryPointInterface which I set as the entry_point in security.yml, to return 401 code and application/json content-type on rejected.
-Client intercepts 401 responses and sends the user to the login form.
-Client sends api rest requests with X-Access-Token set on header.
My current issues:
1) I'm not sure whether I should be setting X-Access-Token on client for requests, I understand this is the right way? Or should I leave it all to hello.js api methods?
2) I have no idea how to make the API Rest app "ask" the oauth server "is this token ok? who does it belong to?" Is this already solved in Symfony?
Thanks a lot for any answer or guideline. Feel free to require any further information or code for what I describe.
For anyone else facing a similar issue:
1) As for the client authenticated requests after login, I let hello.js hello(provider).api methods solve it. It sends access_token as a param. I didn't have to set X-Access-Token on the header or any other "hand made" touch.
2) I didn't find an out of the box solution by symfony for this. But this is what I did:
-Configured a before filter for the protected controller (see doc)
-In that method, I made a call to the API held on the OAuthServer (using this bundle)