Code Monkey home page Code Monkey logo

angular-digest-auth's Introduction

This library is deprecated. Sorry guys I have no time to maintain it. Check my new project @layerr

AngularJS HTTP Digest Authentication

Build Status

It is an AngularJS module to manage HTTP Digest Authentication in the REST API web apps. It provides functionality to avoid the default form of browsers and use your own. The login and logout are based on digest access authentication and the module helps to manage the user identity in the client side. You can use this module in order to protect your app and authorize the user to navigate inside it.

Features

  • Using your own login and logout
  • Interceptor to pass the authorization in all further requests after the login
  • Protection for login with a limitation for the number of requests
  • Storage for reusing credentials
  • Managing identity with authIdentity service
  • Authorization checking as promise with dgAuthService
  • Custom header to parse server information(realm, opaque, domain, etc...)
  • Custom callbacks to handle all authorization states(login successful, login error, login required, etc...)

Installation

You can download this by:

After installation, import the module in your app.

var app = angular.module('myApp', ['dgAuth']);

Dependencies

This module depends by angular, angular-state-machine and angular-md5.

Configuration

You have to provide a few configurations in order to work.

Login and logout

Create the services to sign in and sign out in order to simulate the login and the logout in your app. signin service should return the JSON of the user identity. You can use the user identity with authIdentity service.

app.config(['dgAuthServiceProvider', function(dgAuthServiceProvider)
{
    dgAuthServiceProvider.setConfig({
        login: {
            method: 'POST',
            url: '/signin'
            ...
            //Other HTTP configurations.
        },
        logout: {
            method: 'POST',
            url: '/signout'
            ...
            //Other HTTP configurations.
        }
    });
}]);

Header

How to configure the header to parse server information. You should define a custom header in the server side in order to avoid the browser form and use your custom login form.

app.config(['dgAuthServiceProvider', function(dgAuthServiceProvider)
{
    /**
     * Specifies the header to look for server information.
     * The header you have used in the server side.
     */
    dgAuthServiceProvider.setHeader('Your-Header-For-Authentication');
}]);

Limit

How to configure the limit of number requests to sign in. When the limit is exceeded limit of login callbacks is invoked. The default limit is 4. N.B.: the limit includes the request to sign in place during the invocation of the start method.

app.config(['dgAuthServiceProvider', function(dgAuthServiceProvider)
{
    /**
     * Sets the limit to 5 requests.
     * 4 requests after the invocation of start method.
     */
    dgAuthServiceProvider.setLimit(5);

    /**
     * Sets the limit of requests to infinite.
     */
    dgAuthServiceProvider.setLimit('inf');
}]);

Callbacks

How to configure what happens at the user login and/or logout.

app.config(['dgAuthServiceProvider', function(dgAuthServiceProvider)
{
    /**
     * You can add the callbacks to manage what happens after
     * successful of the login.
     */
    dgAuthServiceProvider.callbacks.login.push(['serviceInject', function(serviceInject)
    {
        return {
            successful: function(response)
            {
                //Your code...
            },
            error: function(response)
            {
                //Your code...
            },
            required: function(response)
            {
                //Your code...
            },
            limit: function(response)
            {
                //Your code...
            }
        };
    }]);

    //This is the same for the logout.

    /**
     * You can add the callbacks to manage what happens after
     * successful of the logout.
     */
    dgAuthServiceProvider.callbacks.logout.push(['serviceInject', function(serviceInject)
    {
        return {
            successful: function(response)
            {
                //Your code...
            },
            error: function(response)
            {
                //Your code...
            }
        };
    }]);
}]);

Storage

By default, after the user has made the login, the credentials are stored in sessionStorage and the module processes all further requests with this credentials. If you want to restore the user credentials when he returns in your app, you can specify the localStorage as default storage.

app.config(['dgAuthServiceProvider', function(dgAuthServiceProvider)
{
    /**
     * Uses localStorage instead the sessionStorage.
     */
    dgAuthServiceProvider.setStorage(localStorage);
}]);

Obviously, if you want to specify your own storage object, you can :).

Usage

For basic usage, you can launch the start() when your app goes run.

app.run(['dgAuthService', function(dgAuthService)
{
    /**
     * It tries to sign in. If the service doesn't find
     * the credentials stored or the user is not signed in yet,
     * the service executes the required function.
     */
    dgAuthService.start();
}]);

In your login controller you should provide the credentials submitted by user. Then you have to sign in another time.

$scope.submit = function(user)
{
    dgAuthService.setCredentials(user.username, user.password);
    dgAuthService.signin();
};

If the login is successful, all further requests, for the API in the domain specified by the server header, contains the authentication to authorize the user.

Authorization

You can use a functionality of dgAuthService to authorize the user to navigate in your app.

app.config(['$routeProvider', function($routeProvider)
{
    /**
     * Use a variable in resolve to authorize the users.
     * The method 'isAuthorized()' returns a promise
     * which you can use to authorize the requests.
     */
    $routeProvider.when('some/path', {
        ...
        resolve: {
            auth: ['dgAuthService', '$q', '$location', function(dgAuthService, $q, $location)
            {
                var deferred = $q.defer();

                dgAuthService.isAuthorized().then(function(authorized)
                {
                    if(authorized)
                        deferred.resolve();
                    else
                        deferred.reject();
                },
                function(authorized)
                {
                    deferred.reject();
                });

                return deferred.promise;
            }]
        }
    });
}]);

License

MIT

angular-digest-auth's People

Contributors

bitdeli-chef avatar tafax avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

angular-digest-auth's Issues

Support npm installs

Using npm to install could be supported fairly trivially, and npm is sometimes preferable to using bower.

For example, the 0.4.3 tagged version of this module can be installed using npm using:

npm install 'git+https://[email protected]/tafax/angular-digest-auth.git#v0.4.3' --save

The main problem I can see here is that although the bower.json and README.md file lists dependencies on angular, angular-state-machine and angular-md5, the package.json file doesn't.

Consequentially, installing using npm like this doesn't get these required dependencies.

Adding support would be simple, the bower.json dependencies attribute can almost be used literally, except that angular-state-machine is not available on npm, so unless you publish that it must also be referenced via git:

"dependencies": {
  "angular-cookies": "*",
  "angular-md5": "*",
  "angular-state-machine": "git+https://[email protected]/tafax/angular-state-machine.git",
  "angular": "*"
},

Although of course, constraints to ensure obtaining a working version number as per the (docs)[https://docs.npmjs.com/files/package.json#dependencies] is good practice. Publishing this package to the npm manager allows other to do the same with this module.

Oh, I also notice that your bower.json states a dependency on angular-cookies, but your README.md does not.

Cheers!

Error in value pattern

var _valuePattern = /([a-zA-Z]+)="?([a-zA-Z0-9/\s]+)"?/; is wrong as nonce can have '=' sign.

TypeError: header.split is not a function

After calling dgAuthService.start(); I always get the error on console header.split is not a function.

Tracking down this error on the source code, I came to this line. I added console.info(header); right before it to check it's content, and the contents of this variable is not a String as probably expect, but an Object with the following structure:

Object {content-type: "text/html; charset=utf-8"}

I'm on Angular 1.4.6. How can I fix this bug? Thanks.

Documentation could be better.

After weeks of having to do something else for work I have returned to this. I am still trying to get a hang of Angular and while I thought I had it set up correctly when I add the callbacks I get errors in the console. A full example instead of segments would be helpful. I've added my code maybe you can tell me what I am doing wrong.

(function($){

  /**
   * example of http digest injection.
   */
  app = angular.module('authMain', ['dgAuth']);


  app.config(['dgAuthServiceProvider', function(dgAuthServiceProvider)
  {
      dgAuthServiceProvider.setConfig({
          login: {
              method: 'POST',
              url: '/api/user/authenticate'
          },
          logout: {
              method: 'POST',
              url: '/api/user/deauthenticate'
          }
      });

      // dgAuthServiceProvider.setHeader('');
      dgAuthServiceProvider.setLimit(5);
      dgAuthServiceProvider.setStorage(localStorage);

      /**
       * You can add the callbacks to manage what happens after
       * successful of the login.
       */
      dgAuthServiceProvider.callbacks.login.push(['serviceInject', function(serviceInject)
      {
          return {
              successful: function(response)
              {
                console.write('login success');
              },
              error: function(response)
              {
                console.write('login error');
              },
              required: function(response)
              {
                console.write('login requried');
              },
              limit: function(response)
              {
                console.write('login limit');
              }
          };
      }]);

      //This is the same for the logout.

      /**
       * You can add the callbacks to manage what happens after
       * successful of the logout.
       */
      dgAuthServiceProvider.callbacks.logout.push(['serviceInject', function(serviceInject)
      {
          return {
              successful: function(response)
              {
                console.write('logout success');
              },
              error: function(response)
              {
                console.write('logout fail');
              }
          };
      }]);

  }]);

  app.run(['dgAuthService', function(dgAuthService)
  {
      /**
       * It tries to sign in. If the service doesn't find
       * the credentials stored or the user is not signed in yet,
       * the service executes the required function.
       */
      dgAuthService.start();
  }]);


  app.controller("LoginController", ['dgAuthService', function(dgAuthService){

    this.user = {};

    this.doLogin = function()
    {
      console.log(this.user);
      dgAuthService.setCredentials(this.user.emailAddress, this.user.password);
      dgAuthService.signin();
    }

  }]);

})(jQuery);

WWW-Authenticate challenge may be parsed incorrectly

In my project I am using angular-digest-auth to talk to a Restlet 2.3 based webserver (Java 7).

The authentication would not work correctly. It would always be rejected, even with the correct credentials.

I tracked this down and discovered a discarded exception in the Restlet server. This showed that the reason was that the response to the challenge sent by angular-digest-auth was incorrect - the server expected a nonce which matched the one it sent, and was a valid base64 encoding (which means it must be the correct length).

Checking the angular-digest-auth code, I noticed that the parseHeader() function's regex did not permit = characters in the values, which is what base64 uses to pad an encoded string to the required length. In fact the regex discarded the trailing = characters silently.

An example of the challenge sent by Restlet:

Digest realm="redacted realm", domain="/", nonce="MTQ0NzE3NDIzNjA2ODpmMzIxZTgzyzczYjq5NjU2ZDcyZGY3OTYxMjhiNGViYQ==", algorithm=MD5, qop="auth"

A trivial fix is possible just by permitting this character, but inspecting the regex I see it would not cope with other legal challenges. In particular, any empty parameter value would not get parsed correctly, nor any unquoted values, nor quoted values containing a comma or a quote character. Not to mention multiple challenges embedded in one header.

See https://tools.ietf.org/html/rfc2617#section-1.2 and https://tools.ietf.org/html/rfc2616#section-2.1

This doesn't seem to follow the protocol for http digest or am I missing something?

Why is there a signin/signout URL? HttpDigest requires that the auth details be sent with every request to the server in the protected area. My REST API expects this to pass the credentials with every request for data and to evaluate it's authenticity with every request as the HttpDigest protocol. Is there a way to use this with a proper HttpDigest setup?

Error when start() method is called

Hello.

When the melhod "dgAuthService.start()" is called in my app.js, the following error is showed on console.

http://errors.angularjs.org/1.2.23/$injector/unpr?p0=serviceInjectProvider%20%3C-%20serviceInject
at VALIDITY_STATE_PROPERTY (http://localhost:63342/myproject-web/app/bower_components/angular/angular.js:78:12)
at http://localhost:63342/myproject-web/app/bower_components/angular/angular.js:3802:19
at Object.getService as get
at http://localhost:63342/myproject-web/app/bower_components/angular/angular.js:3807:45
at getService (http://localhost:63342/myproject-web/app/bower_components/angular/angular.js:3930:39)
at Object.invoke (http://localhost:63342/myproject-web/app/bower_components/angular/angular.js:3957:13)
at b.getCallbacks (http://localhost:63342/myproject-web/app/bower_components/angular-digest-auth/dist/angular-digest-auth.min.js:8:7035)
at c.a.config.loggedIn.action (http://localhost:63342/myproject-web/app/bower_components/angular-digest-auth/dist/angular-digest-auth.min.js:8:2618)
at Object.invoke (http://localhost:63342/myproject-web/app/bower_components/angular/angular.js:3966:17)
at c.send (http://localhost:63342/myproject-web/app/bower_components/angular-state-machine/dist/angular-state-machine.min.js:8:2700)
(anonymous function) angular.js:10061
$get angular.js:7357
deferred.promise.then.wrappedCallback angular.js:11564
(anonymous function) angular.js:11647
$get.Scope.$eval angular.js:12673
$get.Scope.$digest angular.js:12485
$get.Scope.$apply angular.js:12777
done angular.js:8371
completeRequest angular.js:8585
xhr.onreadystatechange angular.js:8524

Example app ?

I'd like to know if there is any example app using the angular-digest-auth module. It would help a lot :)

Storage of username and password in local storage is insecure.

I was reading through the code and noticed that you are storing in plain text the username and password in local storage. That's not secure. Instead you should be storing the ha1 hash in local storage, and storing the ha1 hash in your password database that way you aren't storing plain text passwords in your database. Yes it means a username change would result in having to ask for the password and rebuild the password hash but how often to people change usernames.

tests seem to fail?

I'm attempting to submit a patch for the WWW-Authenticate parser function. As part of that I'd like to add a test. However, the tests don't seem to run for me.

There are no instructions and I'm a little new to the grunt/bower/npm toolchain so there's some guesswork involved. But, on the current master branch (i.e. no changes added by me):

grunt karma

Fails because:

  • Opera is not installed.

Specifically:

ERROR [launcher]: Cannot start Opera
    Can not find the binary opera
    Please set env variable OPERA_BIN

Removed 'Opera' from browsers list in karma.conf.js for now.

  • Missing dependencies. Due to non-existant libs/ dir. Requires running bower install, ran that manually for now.

e.g.

 Firefox 42.0.0 (Ubuntu) ERROR
    ReferenceError: angular is not defined
    at src/angular-digest-auth.js:7
  • SyncStrategy is not defined

Specifically:

Firefox 42.0.0 (Ubuntu) angular-digest-auth tests with no server info or credentials stored should ask for the info and credentials and then sign in FAILED
    ReferenceError: SyncStrategy is not defined
    StateMachineProvider/this.$get<@/home/nick/tmp/angular-digest-auth/lib/angular-state-machine/src/services/state-machine.js:121:9
    e@/home/nick/tmp/angular-digest-auth/lib/angular/angular.min.js:39:191
    [...]

Likewise for npm test, which runs grunt travis --verbose. This does not seem to be a problem

Additionally, the pull requests I submitted fail to build; this may be because of a different reason, the error seems to be:

Fatal error: Arguments to path.join must be strings
npm ERR! Test failed.  See above for more details.
npm ERR! not ok code 0

(See here; Googling finds this which suggests grunt-bower needs to be updated)

Anyway, advice welcome.

Thanks

How to use a controller method to authenticate?

Hi, good morning.

I found this module fantastic and I'm really excited to see it working, but until now I could not configure and use it properly.

Can you provide a simple web-app as a sample?

My problem is when I try to load the function $scope.submit nothing happens.

Anyway, here is what I'm doing:

PHP auth service extracted from here:
<?php
header('Access-Control-Allow-Origin: *');
$realm = 'Restricted area';

//user => password
$users = array('admin' => 'mypass', 'guest' => 'guest');

if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Digest realm="'.$realm.
           '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');

    die('Text to send if user hits Cancel button');
}

// analyze the PHP_AUTH_DIGEST variable
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
    !isset($users[$data['username']]))
    die('Wrong Credentials!');

// generate the valid response
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);

if ($data['response'] != $valid_response)
    die('Wrong Credentials!');

// ok, valid username & password
//echo 'You are logged in as: ' . $data['username'];
echo json_encode(array('user' => 'admin', 'role' => array('VIEW_ALL', 'CREATE_ALL')));


// function to parse the http auth header
function http_digest_parse($txt)
{
    // protect against missing data
    $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
    $data = array();
    $keys = implode('|', array_keys($needed_parts));

    preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);

    foreach ($matches as $m) {
        $data[$m[1]] = $m[3] ? $m[3] : $m[4];
        unset($needed_parts[$m[1]]);
    }

    return $needed_parts ? false : $data;
}
?>
My app.js
var app = angular.module('app', ['dgAuth']);

app.config(['$routeProvider', 'dgAuthServiceProvider',
  function($routeProvider, dgAuthServiceProvider) {

    dgAuthServiceProvider.setHeader('PHP_AUTH_DIGEST');

    dgAuthServiceProvider.setConfig({
        login: {
            method: 'POST',
            url: 'http://localhost/digest/digest-auth.php'
        },
        logout: {
            method: 'POST',
            url: '/signout'
            //Other HTTP configurations.
        }
    });

    dgAuthServiceProvider.callbacks.login.push(['', function()
    {
        return {
            successful: function(response)
            {
                console.log("Worked man: " + response);
            },
            error: function(response)
            {
                console.log("Ops, did not work: " + response);
            },
        }
    }]);

    $routeProvider.
      when('/', {
        templateUrl: 'partials/login/login.html',
        controller: 'loginController'
      }).
        when('/main', {
        templateUrl: 'partials/main/main.html',
        resolve: {
    auth: ['dgAuthService', '$q', '$location', function (dgAuthService, $q, $location)
        {
            var deferred = $q.defer();

            dgAuthService.isAuthorized().then(function (authorized)
            {
                if (authorized)
                    deferred.resolve();
                else
                    deferred.reject();
                    $location.path('/');
            },
            function (authorized)
            {
                deferred.reject();
            });

            return deferred.promise;
        }]
}
      }).
      when('/logout', {
        templateUrl: 'partials/logout/logout.html'
      }).
      otherwise({
        redirectTo: '/'
      });
  }]);

app.run(['dgAuthService', function(dgAuthService)
{
    dgAuthService.start();
}]);
My controller.js
app.controller('loginController', function ($scope, dgAuthService){

    $scope.submit = function() {
        console.log($scope.username,$scope.password);
        dgAuthService.setCredentials($scope.username,$scope.password);
        dgAuthService.signin();
    }
});
My auth form:
<div class="loginContainer center-block">
    <div class="panel panel-primary">
        <div class="panel-heading">User Information</div>
            <div class="panel-body">
                <form data-ng-submit="submit()">
                    <div class="form-group">
                        <label for="usename">User Name</label>
                        <input class="form-control col-sm-1 col-md-1" id="usename" type="text" placeholder="Username" data-ng-model="username">
                    </div>
                    <div class="form-group">
                        <label for="password">Password</label>
                        <input type="password" class="form-control col-sm-1 col-md-1" id="password" placeholder="Password" data-ng-model="password">
                    </div>
                    <input type="submit" class="btn btn-lg btn-primary btn-block col-sm-1 col-md-1" value="Sign in"/>
                </form>
            </div>
    </div>
</div>

Cross Domain calls not working, every time 401 only getting even though Authorization header is added

There are 2 local sites that are running on different ports one is for server and one is UI. The server has enabled the CORS using the following settings.

1. <add name="Access-Control-Allow-Origin" value="http://localhost" />
2.  <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,PATCH,OPTIONS" />
3.  <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept, Authorization" />
 4.  <add name="Access-Control-Allow-Credentials" value="true" />

and also enabled the digest authentication in the IIS.

Now coming to the UI, i created the angular module as per the guidelines provided in the Readme file. Following is my code.


var app = angular.module("poc", ["dgAuth"]);
app.config(['dgAuthServiceProvider', function (dgAuthServiceProvider) {
    dgAuthServiceProvider.setHeader('WWW-Authenticate');
    dgAuthServiceProvider.setLimit('inf');
    dgAuthServiceProvider.setConfig({
        login: {
            method: 'GET',
            url: 'http://localhost:1111/api/values',
            withCredentials: true,
            headers: {
                'Content-Type': 'application/json; charset=utf-8'
            }
        },
        logout: {
            method: 'GET',
            url: 'http://localhost:1111/api/values'
        }
    });
    dgAuthServiceProvider.callbacks.login.push(function (AuthenticationSvc) {
        return {
            successful: function (response) {
                console.log(response);
            },
            error: function (response) {
                console.log(response);
            },
            required: function (response) {
                console.log(response);
            },
            limit: function (response) {
                console.log(response);
            }
        };
    });

    dgAuthServiceProvider.callbacks.logout.push(function (AuthenticationSvc) {
        return {
            successful: function (response) {
                console.log(response);
            },
            error: function (response) {
                console.log(response);
            }
        };
    });
    // dgAuthServiceProvider.setStorage(localStorage);
}]);
app.controller("first", function ($scope, dgAuthService, $http) {
    $scope.userName = "";
    $scope.password = "";
    $scope.login = function () {
        dgAuthService.setCredentials($scope.userName, $scope.password);
        dgAuthService.signin();
        dgAuthService.isAuthorized().then(function (response) {
            $http({
                url: 'http://localhost:1111/api/values/get',
                method: "GET",
                withCredentials: true,
                headers: {
                    'Content-Type': 'application/json; charset=utf-8'
                }
            }).then(
                function (response) {
                    console.log(response)
                },
                function (response) {
                    console.log(response)
                }
                )
        });
    }
});
app.run(['dgAuthService', function (dgAuthService) {
    /**
     * It tries to sign in. If the service doesn't find
     * the credentials stored or the user is not signed in yet,
     * the service executes the required function.
     */
    dgAuthService.start();

}]);

I am getting status as -1 in all the request errors. Getting unauthorized when checked in the browser console.
Highly appreciable if any one provide the solution ASAP.

Note : I downloaded the reference files directly from the bower.

Calling Post on Start Up

Hi

I notice that when calling dgAuthService.start(); a post request is made to the login
login: {
method: 'Post',
url: '/api/signin'
}

I had expected this call would only be made on signin.submit();

Further I was wondering if you had a sample angularJS webapp that I could use to get started.
Thanks for your help

Andrew

Logout keeps credentials

How can we support logout of a user and then optionally logging as a different user?

What I see now is that credentials of the first successfully logged user are used always including after logout in case of access to protected URL.

using scope in callback

Hello, how can use $scope in success or any callback, when i try to inject fails.

thanks.

Is this module still being supported?

Can't seem to get it working. It sends the login request, but that seems to be it. No callbacks, no signin, nothing. So I wanted to ask whether any help is available or whether I should look somewhere else?

angular-cookies dependency: is it really used?

I was wondering why one needs cookies for anything HTTP-Digest related, is this dependency actually required?

So I looked and could not see any use of $cookies. The last use of it is in commit d66924, so I think this is no longer a dependency.

Demo site?

Do you have a demo site where one can see your library in action? I can't seem to get it to work with my own code and I am wondering if I am misinterpreting your setup instructions somehow.

dgAuthService.start() and POST without username and password data

Hi, I think I don't really understand the way angular-digest-auth works I have an API that auths via URL "/api/authenticate" that expects a POST with JSON body with username and password, I configured the angular-digest-auth to that URL but on my angular app.run() when I do a dgAuthSercive.start() it calls my API URL via POST but without pass any body or any username and password via another way. Is there a example app configured so I can figure out how it really works?

Can this module support a standard http-digest exchange which uses WWW-Authenticate?

The README says:

You should define a custom header in the server side in order to avoid the browser form and use your custom login form.

This seems to imply that is the WWW-Authenticate header is present, the usual browser prompt will appear? However, if the server does not use WWW-Authenticate then arguably it isn't using standard HTTP-Digest authentication, but a non-standard variation of it.

Also, I'm not clear if this is required just for the sign-in URL, or all URLs (I would assume the latter, but that makes the whole API exposed by the server non-standard, not just one URL, which would allow the rest of the API to stick to the standards and thereby interoperate with other clients besides the AngularJS UI using this module).

Can you clarify: can this module be used with standard http-digest with WWW-Authenticate, or does some or all occurrences of the WWW-Authenticate header need to be prevented for it to work?

Thanks!

authIdentity.get() is not always the information obtained from the signin URL

This is a hard issue to describe in a way you can replicate, without sending you my entire application. If I get time later I may attempt to construct a simple example. Nevertheless, for now, this is what I know.

The symptom: authIdentity.get() sometimes does not return user identity information obtained from the signin URL configured via dgAuthServiceProvider.setConfig(), as I believe it is meant to. Instead it contains the response to another URL, which varies depending on the circumstance.

This manifests in my app as being shown as logged in by no-one, or some nonsensical user depending on the URL data we actually get. In my app this is repeatable by logging out (which calls the dgAuthService.signout() method), reloading the browser page and then logging in again.

The cause. Inspecting the code and debugging, what seems to be happening is that the signin url is never actually requested, because within the authRequests.signin() function, there is a cached request to another URL obtained at line 1172. The response from this is what gets set into the authIdentity object.

The cached request is made by the application following an event broadcast by the successful callback bound to dgAuthServiceProvider.callbacks.login. It is intended to update my application's data structures. Apparently it may get invoked before authRequsts.signin() does.

In other words, what I think is happening is that angular-auth-digest is caching the failed API calls meant to update my application's data structures, and then when the user has entered their login, it replays them instead of calling the configured signin URL, and the authIdentity object is set by the first result to come back.

The sequence of events I see in my console log output is as follows:

  • authRequests.signin() called: (angular-digest-auth.js line 1168)
  • This gets my signin URL "/api/user" -> 401 Unauthorized
  • Login dialog opened
  • Credentials entered, dialog submitted
  • my application attempts to update its data from "/api/foo"-> 401 Unauthorized
  • authRequests.signin() called: (angular-digest-auth.js line 1168)
  • request to "/api/foo" is resent -> 200 OK, returns the response object FOO
  • loggedIn action sets authIdentity to FOO (angular-digest-auth.js line 230)
  • loggedIn action also sets credentials with { username="Controllis", password="Controllis" (angular-digest-auth.js line 235)
  • loggedIn action calls login.successful callback with FOO (angular-digest-auth.js line 240)
  • Promise returned for request to "/api/foo" is resolved successfully and the callback invoked in my application.

The docs mention authIdentity but not authService.getCredentials(), thus I assume authService.getCredentials() is internal. However it does seem to be more reliable, in the current scheme, so I am using this as an alternative to authIdentity.get() for now. More explanation of authIdentity and its purpose would be welcome!

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.