This is the implementation of the concept described in Authentication in AngularJS (or similar) based application.
There are releases for both AngularJS 1.0.x and 1.2.x, see releases.
Launch demo here or switch to gh-pages branch for source code of the demo.
bower install --save angular-http-auth
npm install --save angular-http-auth
angular.module('myApp', ['http-auth-interceptor'])
This module installs $http interceptor and provides the authService
.
The $http interceptor does the following:
the configuration object (this is the requested URL, payload and parameters)
of every HTTP 401 response is buffered and everytime it happens, the
event:auth-loginRequired
message is broadcasted from $rootScope.
The authService
has only 2 methods: loginConfirmed()
and loginCancelled()
.
You are responsible to invoke loginConfirmed()
after user logs in. You may optionally pass in
a data argument to this method which will be passed on to the loginConfirmed
$broadcast. This may be useful, for example if you need to pass through details of the user
that was logged in. The authService
will then retry all the requests previously failed due
to HTTP 401 response.
You are responsible to invoke loginCancelled()
when authentication has been invalidated. You may optionally pass in
a data argument to this method which will be passed on to the loginCancelled
$broadcast. The authService
will cancel all pending requests previously failed and buffered due
to HTTP 401 response.
In the event that a requested resource returns an HTTP 403 response (i.e. the user is
authenticated but not authorized to access the resource), the user's request is discarded and
the event:auth-forbidden
message is broadcast from $rootScope.
Sometimes you might not want the interceptor to intercept a request even if one returns 401 or 403. In a case like this you can add ignoreAuthModule: true
to the request config. A common use case for this would be, for example, a login request which returns 401 if the login credentials are invalid.
$http(...).then(function(response) { do-something-with-response })
is invoked,http-auth-interceptor
captures the initial request and broadcasts event:auth-loginRequired
,authService.loginConfirmed()
,function(response) {do-something-with-response}
will fire,You can supply additional data to observers across your application who are listening for event:auth-loginConfirmed
and event:auth-loginCancelled
:
$scope.$on('event:auth-loginConfirmed', function(event, data){
$rootScope.isLoggedin = true;
$log.log(data)
});
$scope.$on('event:auth-loginCancelled', function(event, data){
$rootScope.isLoggedin = false;
$log.log(data)
});
Use the authService.loginConfirmed([data])
and authService.loginCancelled([data])
methods to emit data with your login and logout events.
Successful login means that the previous request are ready to be fired again, however now that login has occurred certain aspects of the previous requests might need to be modified on the fly. This is particularly important in a token based authentication scheme where an authorization token should be added to the header.
The loginConfirmed
method supports the injection of an Updater function that will apply changes to the http config object.
authService.loginConfirmed([data], [Updater-Function])
//application of tokens to previously fired requests:
var token = response.token;
authService.loginConfirmed('success', function(config){
config.headers["Authorization"] = token;
return config;
})
The initial failed request will now be retried, all queued http requests will be recalculated using the Updater-Function.
It is also possible to stop specific request from being retried, by returning false
from the Updater-Function:
authService.loginConfirmed('success', function(config){
if (shouldSkipRetryOnSuccess(config))
return false;
return config;
})