angularjs: $http basic authentication

NaN picture NaN · Apr 8, 2015 · Viewed 13.6k times · Source

I tried angular.js and started with a web-ui for a restful api (using http basic auth). It is really nice and all except the authorization works.

Up to now I am using $http.defaults.headers.common.Authorization to set the password, but mostly the browser opens his default login-form for http-basic-auth. Another strange behaviour is that the angular-request does not contain a Authorisation-Header (neither OPTIONS nor the GET-request). I also tried to set this header on each request with the header-config, but this also didn't work.

Are there some special headers I have to set? Or do I have to set $http.defaults.headers.common.Authorization in a special context?

tools.factory('someFactory', function ($http, Base64) {

  //...

  factory.checkAuth = function (username, password) {
    storeCredentials(username, password);
    factory.initConnection();
    return factory.getData();
  };

  factory.initConnection = function(){
    var credentials = loadCredentials();

    factory.authHeader = 'Basic ' + Base64.encode(credentials.username + ':' + credentials.password);

    $http.defaults.headers.common.Authorization = factory.authHeader;
  };

factory.getData = function () {
    return $http({
      method: 'GET',
      url: urlBase + '/happening',
      headers: {
      //  'Authorization': factory.authHeader
      }
    });
  };

Request header:

OPTIONS /v8/happening HTTP/1.1
Host: api.gospry.com
Connection: keep-alive Access-Control-Request-Method: GET
Origin: http://web.gospry.com
User-Agent: [..] Access-Control-Request-Headers: accept, authorization
Accept: */*
Referer: http://web.gospry.com/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

Response header:

The backend was slightly modified to support CORS (Access-Control-headers and preflight-request-support).

HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Access-Control-Allow-Origin: http://web.gospry.com
Access-Control-Allow-Methods: POST, GET, PUT, PUSH, OPTIONS, DELETE
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Authorization
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Set-Cookie: JSESSIONID=2DDC92A1B0DC57C221CDC3B7A5DC1314; Path=/v8/; Secure; HttpOnly
WWW-Authenticate: Basic realm="Realm"
X-Content-Type-Options: nosniff
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length: 0
Date: Wed, 08 Apr 2015 18:04:04 GMT

Answer

Cerad picture Cerad · Apr 8, 2015

I use an interceptor. I can't spot the issue in your code but here is what I am using:

authModule.factory('CeradAuthInterceptor', 
['CeradAuthManager', function ( authManager) 
{
  return {
    request: function (config) 
    {
      config.headers = config.headers || {};
      if (authManager.authToken) 
      {
        config.headers.Authorization = 'Bearer ' + authManager.authToken;
      }
      return config;
    }
  };
}]);

appModule.config(['$httpProvider', function ($httpProvider) {
  $httpProvider.interceptors.push('CeradAuthInterceptor');
}]);