{"id":142,"date":"2014-09-15T08:00:00","date_gmt":"2014-09-15T08:00:00","guid":{"rendered":"http:\/\/localhost\/?p=142"},"modified":"2017-01-09T06:47:44","modified_gmt":"2017-01-09T06:47:44","slug":"angularjs-authentication","status":"publish","type":"post","link":"https:\/\/ionic.io\/blog\/angularjs-authentication","title":{"rendered":"Cookie-based Authentication in AngularJS"},"content":{"rendered":"<p>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.<\/p>\n<p>Depending on where you build and release your AngularJS app, there are different ways to handle authentication and I hope this post clears some of that up.<\/p>\n<h3 id=\"cors\">CORS<\/h3>\n<p>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.<\/p>\n<p><!--more--><\/p>\n<p>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.<\/p>\n<p>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 (and hence, Ionic apps). However, these tools often have configuration options for whitelisting domains so you can add some security that way.<\/p>\n<h3 id=\"configuringcorsontheserver\">Configuring CORS on the Server<\/h3>\n<p>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.<\/p>\n<p>I won&#8217;t get into the details of configuring CORS on the server side, but it&#8217;s really just setting some headers. Here&#8217;s how you might do it <a href=\"https:\/\/gist.github.com\/michiel\/1064640\">in nginx<\/a>.<\/p>\n<p>There is one header in particular you must have if you want to do session based authentication in a single page app: <code>Access-Control-Allow-Credentials: true<\/code> which we show next.<\/p>\n<h3 id=\"angularjsauth\">AngularJS Auth<\/h3>\n<p>If you use the standard <code>$http<\/code> service to access remote APIs, it will Just Work as long as the server is configured to allow requests from your domain and you don&#8217;t need to store cookies.<\/p>\n<p>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&#8217;ll be smashing your head wondering why the cookie information isn&#8217;t being saved!<\/p>\n<p>Enter: <code>withCredentials<\/code>. <code>withCredentials<\/code> is a flag set on a low-level <code>XMLHttpRequest<\/code> (AJAX) object, but in Angular we can configure our <code>$http<\/code> requests to set this flag for everything by doing:<\/p>\n<pre><code class=\"javascript\">angular.module(&#039;myApp&#039;)\n\n.config([&#039;$httpProvider&#039;, function($httpProvider) {\n  $httpProvider.defaults.withCredentials = true;\n}])\n<\/code><\/pre>\n<h3 id=\"csrf\">CSRF<\/h3>\n<p>Many servers use CSRF as a security feature and you can certainly keep this feature in a hybrid app if you wish. CSRF is a way to ensure the client making a request is the same one that the server expects to make the request. This keeps someone from sniffing your cookie session data and making requests pretending to be you (and changing your password, for example).<\/p>\n<p>To make for CSRF, we can tell <code>$http<\/code> to set the correct header for CSRF (might depend on your server framework, this one is for Django) using the specific cookie name:<\/p>\n<pre><code class=\"javascript\">angular.module(&#039;myApp&#039;, [&#039;ngCookies&#039;])\n\n.run([&#039;$http&#039;, &#039;$cookies&#039;, function($http, $cookies) {\n  $http.defaults.headers.post[&#039;X-CSRFToken&#039;] = $cookies.csrftoken;\n}]);\n<\/code><\/pre>\n<p>While I&#8217;ve found this to work pretty well, if the CSRF token changes mid-session (for example if a new user signs up) the token won&#8217;t update. To fix this, we can use an HTTP Interceptor to always set the correct CSRF header value before each request:<\/p>\n<pre><code class=\"javascript\">angular.module(&#039;myApp&#039;)\n\n.provider(&#039;myCSRF&#039;,[function(){\n  var headerName = &#039;X-CSRFToken&#039;;\n  var cookieName = &#039;csrftoken&#039;;\n  var allowedMethods = [&#039;GET&#039;];\n\n  this.setHeaderName = function(n) {\n    headerName = n;\n  }\n  this.setCookieName = function(n) {\n    cookieName = n;\n  }\n  this.setAllowedMethods = function(n) {\n    allowedMethods = n;\n  }\n  this.$get = [&#039;$cookies&#039;, function($cookies){\n    return {\n      &#039;request&#039;: function(config) {\n        if(allowedMethods.indexOf(config.method) === -1) {\n          \/\/ do something on success\n          config.headers[headerName] = $cookies[cookieName];\n        }\n        return config;\n      }\n    }\n  }];\n}]).config(function($httpProvider) {\n  $httpProvider.interceptors.push(&#039;myCSRF&#039;);\n});\n<\/code><\/pre>\n<p>This will set the CSRF request header to the current value of the CSRF cookie for any request type not in <code>allowedMethods<\/code>. <\/p>\n<h3 id=\"credentialsandcors\">Credentials and CORS<\/h3>\n<p>One thing to note when using <code>withCredentials: true<\/code> in your app and configuring the server for CORS is that you may not have your <code>Access-Control-Allow-Origin<\/code> header set to <code>&#039;*&#039;<\/code>. It must be configured to a few select origins. If you absolutely must have this set to <code>*<\/code>, then I suggest doing something beyond cookie based authentication, such as token-based authentication.<\/p>\n<h3 id=\"tokenauth\">Token Auth<\/h3>\n<p>The methods described above work for cookie-based authentication that is common in most server-side setups. However, some APIs expect HTTP Basic Authentication or use a token-based system.<\/p>\n<p>While the correct use of CORS will avoid cross-domain pitfalls of cookie-based authentication, those methods may be a better fit for your use case. In that case, take a look at <a href=\"https:\/\/auth0.com\/blog\/2014\/01\/07\/angularjs-authentication-with-cookies-vs-token\/\">this great post<\/a> on token authentication with AngularJS.<\/p>\n<p>We may revisit this topic in the future to add our thoughts on Token-based authentication.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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. Depending on where you build and release your AngularJS app, there are different ways to handle authentication and I [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"publish_to_discourse":"","publish_post_category":"","wpdc_auto_publish_overridden":"","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"","discourse_permalink":"","wpdc_publishing_response":"","wpdc_publishing_error":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[2,3],"class_list":["post-142","post","type-post","status-publish","format-standard","hentry","category-all","tag-angularjs","tag-ionic"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.0 (Yoast SEO v23.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Cookie-based Authentication in AngularJS - Ionic Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ionic.io\/blog\/angularjs-authentication\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Cookie-based Authentication in AngularJS\" \/>\n<meta property=\"og:description\" content=\"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. Depending on where you build and release your AngularJS app, there are different ways to handle authentication and I [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ionic.io\/blog\/angularjs-authentication\" \/>\n<meta property=\"og:site_name\" content=\"Ionic Blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-09-15T08:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-01-09T06:47:44+00:00\" \/>\n<meta name=\"author\" content=\"Max Lynch\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@maxlynch\" \/>\n<meta name=\"twitter:site\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Max Lynch\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/ionic.io\/blog\/angularjs-authentication#article\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/angularjs-authentication\"},\"author\":{\"name\":\"Max Lynch\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/91f360cffbd804a464b0c4a87b5c5f1e\"},\"headline\":\"Cookie-based Authentication in AngularJS\",\"datePublished\":\"2014-09-15T08:00:00+00:00\",\"dateModified\":\"2017-01-09T06:47:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/angularjs-authentication\"},\"wordCount\":713,\"commentCount\":20,\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"keywords\":[\"angularjs\",\"Ionic\"],\"articleSection\":[\"All\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/ionic.io\/blog\/angularjs-authentication#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ionic.io\/blog\/angularjs-authentication\",\"url\":\"https:\/\/ionic.io\/blog\/angularjs-authentication\",\"name\":\"Cookie-based Authentication in AngularJS - Ionic Blog\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/#website\"},\"datePublished\":\"2014-09-15T08:00:00+00:00\",\"dateModified\":\"2017-01-09T06:47:44+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/ionic.io\/blog\/angularjs-authentication#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ionic.io\/blog\/angularjs-authentication\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/ionic.io\/blog\/angularjs-authentication#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/ionic.io\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cookie-based Authentication in AngularJS\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ionic.io\/blog\/#website\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"name\":\"ionic.io\/blog\",\"description\":\"Build amazing native and progressive web apps with the web\",\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ionic.io\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/ionic.io\/blog\/#organization\",\"name\":\"Ionic\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"width\":1920,\"height\":854,\"caption\":\"Ionic\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/ionicframework\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/91f360cffbd804a464b0c4a87b5c5f1e\",\"name\":\"Max Lynch\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/05\/max-avatar-150x150.jpg\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/05\/max-avatar-150x150.jpg\",\"caption\":\"Max Lynch\"},\"description\":\"CEO\",\"sameAs\":[\"http:\/\/twitter.com\/maxlynch\",\"https:\/\/x.com\/maxlynch\"],\"url\":\"https:\/\/ionic.io\/blog\/author\/max\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Cookie-based Authentication in AngularJS - Ionic Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ionic.io\/blog\/angularjs-authentication","og_locale":"en_US","og_type":"article","og_title":"Cookie-based Authentication in AngularJS","og_description":"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. Depending on where you build and release your AngularJS app, there are different ways to handle authentication and I [&hellip;]","og_url":"https:\/\/ionic.io\/blog\/angularjs-authentication","og_site_name":"Ionic Blog","article_published_time":"2014-09-15T08:00:00+00:00","article_modified_time":"2017-01-09T06:47:44+00:00","author":"Max Lynch","twitter_card":"summary_large_image","twitter_creator":"@maxlynch","twitter_site":"@ionicframework","twitter_misc":{"Written by":"Max Lynch","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ionic.io\/blog\/angularjs-authentication#article","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/angularjs-authentication"},"author":{"name":"Max Lynch","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/91f360cffbd804a464b0c4a87b5c5f1e"},"headline":"Cookie-based Authentication in AngularJS","datePublished":"2014-09-15T08:00:00+00:00","dateModified":"2017-01-09T06:47:44+00:00","mainEntityOfPage":{"@id":"https:\/\/ionic.io\/blog\/angularjs-authentication"},"wordCount":713,"commentCount":20,"publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"keywords":["angularjs","Ionic"],"articleSection":["All"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ionic.io\/blog\/angularjs-authentication#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ionic.io\/blog\/angularjs-authentication","url":"https:\/\/ionic.io\/blog\/angularjs-authentication","name":"Cookie-based Authentication in AngularJS - Ionic Blog","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/#website"},"datePublished":"2014-09-15T08:00:00+00:00","dateModified":"2017-01-09T06:47:44+00:00","breadcrumb":{"@id":"https:\/\/ionic.io\/blog\/angularjs-authentication#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ionic.io\/blog\/angularjs-authentication"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/ionic.io\/blog\/angularjs-authentication#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ionic.io\/blog"},{"@type":"ListItem","position":2,"name":"Cookie-based Authentication in AngularJS"}]},{"@type":"WebSite","@id":"https:\/\/ionic.io\/blog\/#website","url":"https:\/\/ionic.io\/blog\/","name":"ionic.io\/blog","description":"Build amazing native and progressive web apps with the web","publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ionic.io\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ionic.io\/blog\/#organization","name":"Ionic","url":"https:\/\/ionic.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","width":1920,"height":854,"caption":"Ionic"},"image":{"@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/ionicframework"]},{"@type":"Person","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/91f360cffbd804a464b0c4a87b5c5f1e","name":"Max Lynch","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/05\/max-avatar-150x150.jpg","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/05\/max-avatar-150x150.jpg","caption":"Max Lynch"},"description":"CEO","sameAs":["http:\/\/twitter.com\/maxlynch","https:\/\/x.com\/maxlynch"],"url":"https:\/\/ionic.io\/blog\/author\/max"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/142","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/comments?post=142"}],"version-history":[{"count":0,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/142\/revisions"}],"wp:attachment":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media?parent=142"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/categories?post=142"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/tags?post=142"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}