Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
AngularJS Authentication and CORS

Single Page Apps are ruling the world and AngularJS is leading the charge. But many of the lessons we learned in the Web 2.0 era no longer apply, and few are as drastically different as authentication.

CORS

CORS is an oft-misunderstood feature of new browsers that is configured by a remote server. CORS stands for Cross-Origin-Resource-Sharing, and was designed to make it possible to access services outside of the current origin (or domain) of the current page.

Like many browser features, CORS works because we all agree that it works. So all major browsers like Chrome, Firefox, and IE support and enforce it. By using these browsers, you benefit from the security of CORS.

That means certain browsers do not enforce it, so it is not relevant there. One large example is a native Web View for things like Cordova and Phonegap. However, these tools often have configuration options for whitelisting domains so you can add some security that way.

Configuring CORS on the Server

The way CORS works is the server decides which domains it will accept as clients. This means an open API like Twitter might allow any clients, or a closed API might decide to only allow access from the domain of the running client app.

I won't get into the details of configuring CORS on the server side, but it's really just setting some headers. Here's how you might do it in nginx.

There is one header in particular you must have if you want to do session based authentication in a single page app: Access-Control-Allow-Credentials: true which we show next.

AngularJS Auth

If you use the standard $http service to access remote APIs, it will Just Work as long as the server is configured to allow requests from your domain.

But for many applications, we also need to set and store cookie information for things like logins. By default this is not allowed in most browsers and you'll be smashing your head wondering why the cookie information isn't being saved!

Enter: withCredentials. withCredentials is a flag set on a low-level XMLHttpRequest (AJAX) object, but in Angular we can configure our $http requests to set this flag for everything by doing:

angular.module('myApp')

.config(['$httpProvider', function($httpProvider) {
  $httpProvider.defaults.withCredentials = true;
}])

As for CSRF, we can tell $http to set the correct header for CSRF (might depend on your server framework, this one is for Django) using the specific cookie name:

angular.module('myApp', ['ngCookies'])

.run(['$http', '$cookies', function($http, $cookies) {
  $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
}]);

Credentials and CORS

One thing to note when using withCredentials: true in your app and configuring the server for CORS is that you may not have your Access-Control-Allow-Origin header set to '*'. It must be configured to a few select origins. If you absolutely must have this set to *, then I suggest doing something beyond cookie based authentication, such as token-based authentication.

@Martinspire

This comment has been minimized.

Copy link

Martinspire commented Sep 24, 2014

Nice, but how do you set the credentials it should send with the HTTP header in Angular? I'm guessing enabling it, would require you to save them somewhere?

@BrianHoldsworth

This comment has been minimized.

Copy link

BrianHoldsworth commented May 11, 2015

The browser takes care of including the credentials for you. Your application never needs to see them.

@andrhahn

This comment has been minimized.

Copy link

andrhahn commented Oct 21, 2015

$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;

This will not work. Cookies cannot be accessed when performing cross-domain requests.

@GuitMAN

This comment has been minimized.

Copy link

GuitMAN commented Jun 2, 2016

Good for you the author! A lot of good!!! I fuck for the fourth day with authorization. And then all is solved in two lines.

@sky-admin

This comment has been minimized.

Copy link

sky-admin commented Jul 5, 2016

you say it must be configured to a few select origins, why when i set it like this:
response.setHeader("Access-Control-Allow-Origin", "http://localhost:9000,http://localhost:9001");

and browser show : XMLHttpRequest cannot load http://xxxxxxxx:8081/login?username=123&password=456. The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:9000,http://localhost:9001', but only one is allowed. Origin 'http://localhost:9001' is therefore not allowed access.

@sky-admin

This comment has been minimized.

Copy link

sky-admin commented Jul 5, 2016

ok i find how to fixed it.

@dushujun

This comment has been minimized.

Copy link

dushujun commented Aug 19, 2016

thanks!!! I solved my problem by your solution!

@jdkb123

This comment has been minimized.

Copy link

jdkb123 commented Sep 1, 2016

I am using angular2 rc4. I have a SPA application (domain - foobar1.com) that sends http requests to foobar2.com using angular $http. The response contains cookies (setcookie a=b). If I just set withCredentials=true in all my http requests, will the subsequent requests contain the cookie? Or do I have to use something like angular2-cookie module ?

@cuervotronic

This comment has been minimized.

Copy link

cuervotronic commented Feb 15, 2018

You save my week!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.