Adding http headers to window.location.href in Angular app - angularjs

I have a angular app that I needed to redirect outside to a non angular html page, so I thought I could just use the $window.location.hrefto redirect the angular app to my external site. This actually works fine, however, I have a nodejs/express backend that checks for auth token before serving up any content(even static content).
This requires a auth token to be sent in the header of the http request. Now the question:
Can/How do you add an auth token to the request that is made by changing the $window.location.href before it is sent off?

When you use $window.location.href the browser is making the HTTP request and not your JavaScript code. Therefore, you cannot add a custom header like Authorization with your token value.
You could add a cookie via JavaScript and put your auth token there. The cookies will automatically be sent from the browser. However, you will want to review the security implications of using a cookie vs. a header. Since both are accessible via JavaScript, there is no additional attack vector there. Unless you remove the cookie after the new page loads, there may be a CSRF exploit available.

This answer is NOT a safe way, as the token is exposed in the URL, which is logged in browser history, access logs, etc. Use a domain cookie instead. I'll leave the answer as it can be an easy way to debug in your local setup.
I am using JWT as authentication on a Laravel PHP backend, and it works by putting ?token=... in the URL. For example, when using AngularJS with satellizer plug-in, I add ?token=' + $auth.getToken() to the URL.

Related

React frontend and REST API, CSRF

Using React on the frontend with a RESTful API as backend and authorisation by a JSON Web Token (JWT), how do we handle sessions? For example after login, I get a JWT token from REST. If I save it to localStorage I am vulnerable to XSS, if I save it to cookies, same problems except I set cookies to HttpOnly, but React can't read HttpOnly Cookies (I need to read cookie to take JWT from it, and use this JWT with REST requests), also I didn't mention the Cross Site Request Forgery (CSRF) problem. If you're using REST as backend, you can't use CSRF Tokens.
As a result, React with REST seems like a bad solution and I need to rethink my architecture. Is it possible to offer your users a secure React application that handles all business logic on the REST API side without fear of losing their data?
Update:
As far as I understood, it is possible to do this:
React makes an AJAX call to the REST API
React gets a JWT token from the REST API
React writes HttpOnly cookie
Because React can't read HttpOnly cookies, we use it as-is in all our REST calls where we need authentication
The REST API calls to check the XMLHttpRequest header, which is some kind of CSRF protection
The REST API side checks for cookie, reads JWT from it and does stuff
I lack theoretical knowledge here. The logic looks pretty secure, but I still need an answer to my questions and approve of this "workflow".
React makes AJAX call to REST API
assured, lots of restful resource client lib available
React gets JWT token from REST
assured, this is what JWT should do
React writes httponly cookie
I don't think so, It should not work, but session is not such a important thing, it'll soon get out of date, and recheck password on key operations, even the hackers got it in a very short time, you can bind session token together with IP when user login and check it in your backend apis. If you want it most secured, just keep token in memory, and redo login when open new page or page refreshes
Because react can't read httponly cookie, we use it as-is in our all REST call where we need authentication
assured, check user and permissions through login token, like csrf you can put your login token into your request header, and check it in your backend apis.
Bind login token to your own restful lib will save you a lot codes
REST on calls checks XMLHttpRequest header, what is some kind of CSRF protection
REST side check for cookie, read JWT from it and do stuff
assured, as most people do.
Also, bind csrf token to your own restful lib will save you a lot codes
use user token in header https://www.npmjs.com/package/express-jwt-token
Authorization JWT < jwt token >
use csrf token in header https://github.com/expressjs/csurf
req.headers['csrf-token'] - the CSRF-Token HTTP request header.
restful client https://github.com/cujojs/rest
react with jwt https://github.com/joshgeller/react-redux-jwt-auth-example
Your server can set the JWT cookie directly as a response to the login request.
The server responds to POST /login with Set-Cookie: JWT=xxxxxx. That cookie is http only and therefore not vulnerable to XSS, and will be automatically included on all fetch requests from the client (as long as you use withCredentials: true).
CSRF is mitigated as you mentioned, see OWASP for details.

how to keep a header parameter in Angularjs

I have made a JWT authentication for my rest api. now i can login in my service and set a token in header for my next angular requests. But when a reload my page browser lost my token. May sounds like ridiculous, but i want to know the elegant way to fix it.
You can store the JWT token in localStorage or sessionStorage and append it to the header when making requests.
https://developer.mozilla.org/en-US/docs/Web/API/Storage

how to implement csrf protection for cross domain requests

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

How to set $httpProvider default headers from my app config in AngularJS?

I'm trying to set my
$httpProvider.defaults.headers.common['X-CSRF-Token'] = $cookie.auth_token;
in my .config section of my app, but it doesn't seem like I can access the document/cookies just yet? Is there a better place to set this?
I'm doing this because I'm storing my users auth_token in a cookie so they don't need to login every time they use my mobile app.
Thanks!
As described in $http docs:
... Angular provides a mechanism to counter XSRF. When performing XHR
requests, the $http service reads a token from a cookie called
XSRF-TOKEN and sets it as the HTTP header X-XSRF-TOKEN.
... To take advantage of this, your server needs to set a token in a
JavaScript readable session cookie called XSRF-TOKEN on the first HTTP
GET request
So if you set your CSRF token in cookie name XSRF-TOKEN then no adjustments are needed on Angular side. and your code should work as is.

Handling Page Reloads With OAuth Access Code In URI

I've run into an issue when using OAuth 2 authorization codes in an web app's URL, such as is returned by Google's OAuth method (https://developers.google.com/accounts/docs/OAuth2Login).
I've been using the google redirect method; where you redirect the user to a Google URL, passing in client_id and redirect_uri. The user authenticates and the authorization code is passed to the redirect_uri as a
The issue is that the access code stays in the page URL, so if the user bookmarks or posts the URL, they are sending an invalid Authorization Code.
Eg:
http://myapp.com/?code=kACASDSDdAS81J5B8M_owCyUNgV46XdZaqBBMh4T8OJFEKPRrgN7gtiFOcMW5Fv3gk
What is the best way to handle this case? Ideally, I would like to send the authorization code in a POST body as it isn't visible to the player?
I've spent a bit of time looking at Google App Engine (the platform I'm using) to redirect the user, but can't seem to send a POST body in a redirect.
After the user is directed to your app with the authorization code in the URL query parameter, you should:
1) Exchange the authorization code for an access token by making a HTTPs POST to Google's OAuth 2.0 token endpoint and save that access token as appropriate (datastore, memcache, etc)
2) Redirect the user to a URL without the ?code. You can't send a POST body in a redirect (HTTP doesn't allow it), but that shouldn't be necessary if you store the access token server-side for making API calls.
If you must make the token accessible client-side, you can:
a) Send it back as a cookie along with the redirect (which exposes it to the client, though you could encrypt it) OR
b) Generate a HTML form, with JavaScript for auto-submitting it instead of doing the redirect. Kind of ugly, but common.

Resources