An authentication and authorization helper service for Angular client applications.
Dependencies
- AngularJS - http://angularjs.org
- Lodash - http://lodash.com
Basic Setup
Add this module to your app as a dependency:
var app = angular.module('yourApp', ['authentication.service']);
Inject $authentication as a parameter in declarations that require it:
app.controller('yourController', function($scope, $authentication){ ... });
Configuration Options
To override the default configuration options, configure the module with an options argument during application configuration and provide overrides for any of the following options.
app.config(['$authenticationProvider', function ($authenticationProvider) { $authenticationProvider.configure({ authCookieKey: undefined, storageService: undefined, profileStorageKey: '$authentication.user.profile', lastAttemptedUrlStorageKey: '$authentication.last-attempted-url', onLoginRedirectUrl: '/', onLogoutRedirectUrl: '/', notAuthorizedRedirectUrl: '/', notAuthenticatedRedirectUrl: '/', trackLastAttemptedUrl: true, userRolesProperty: 'roles', extensions: undefined, expirationProperty: undefined, events: { loginConfirmed: 'event:auth-loginConfirmed', loginRequired: 'event:auth-loginRequired', logoutConfirmed: 'event:auth-logoutConfirmed', notAuthenticated: 'event:auth-notAuthenticated', notAuthorized: 'event:auth-notAuthorized' }, rolesFunction: function (userProfile) { if (_.has(userProfile, this.userRolesProperty)) { var roles = userProfile[this.userRolesProperty]; return _.isArray(roles) ? roles : [roles]; } return []; }, validationFunction: function (userRoles, allowedRoles) { return !_.isEmpty(userRoles) && !_.isEmpty(allowedRoles) && (_.find(allowedRoles, function (role) { return _.includes(userRoles, role); }) !== undefined); }, reauthentication: { fn: function () {}, timeout: 1200000, timer: undefined } });}]);
Extensions
All properties (own and inherited) of the extensions object will be available as native to the $authentication service API. The extensions object is applied using the _.defaults(...) method and cannot overwrite any of the existing API properties. This is intended to provide implementors with a way to add objects or functions that are application specific and should fall within the context of the authentication service to expose, e.g., functions to check if a profile has specific roles.
Storage Service Option
If you do not provide a storage service then a simple, in-memory dictionary will be used.
You can provide any storage service or object that supports the following API:
any get(key)
boolean has(key)
void remove(key)
void set(key, value)
To configure a storage service for the authentication provider you provide the service name:
app.config(['$authenticationProvider', function ($authenticationProvider) { $authenticationProvider.configure({ storageService: '$store' });}]);
or an object that provides the expected functionality:
app.config(['$authenticationProvider', function ($authenticationProvider) { $authenticationProvider.configure({ storageService: new CustomStorageService() });}]);
The ng-authentication-service was designed in tandem with the ng-local-storage-service.
API
isAuthenticated()
// Returns true if there is a user profile loaded in local storage, false otherwise.$authentication.isAuthenticated();
isAuthCookieMissing()
// Returns true if the authCookieKey is defined and no auth cookie is present, false otherwise.$authentication.isAuthCookieMissing();
isProfileExpired()
// Returns true if there is a user profile and it has an expiration value in the past, false otherwise.$authentication.isProfileExpired();
loginConfirmed(data)
// Store the profile (data) in local storage, notify all listeners of login, and redirect to:// 1. lastAttemptedUrl if defined and trackLastAttemptedUrl is true// 2. onLoginRedirectUrl if defined// 3. do not redirect$authentication.loginConfirmed({ ... });
Broadcast via: event:auth-loginConfirmed
with the data
parameter as an argument.
checkAndBroadcastLoginConfirmed()
// Check whether a user is logged in and broadcast the auth-loginConfirmed event, if so.$authentication.checkAndBroadcastLoginConfirmed();
loginRequired()
// Notify all listeners that authentication is required.$authentication.loginRequired();
Broadcast via: event:auth-loginRequired
.
logoutConfirmed(doNotRedirect)
// Remove any existing profile from local storage, notify all listeners of logout, and redirect to:// 1. do not redirect if @doNotRedirect === true// 2. lastAttemptedUrl if defined and trackLastAttemptedUrl is true// 3. onLogoutRedirectUrl if defined// 4. do not redirect$authentication.logoutConfirmed();
Broadcast via: event:auth-logoutConfirmed
.
allowed(...)
// Return true if the user is unauthenticated, false otherwise.$authentication.allowed('anonymous'); // Return true if the user is authenticated, false otherwise.$authenticated.allowed('all'); // Return true if the configured validationFunction returns true, false otherwise.$authenticated.allowed('role1', 'role2', ...); // will flatten provided arrays that are any depth in the arguments list$authentication.allowed('X', ['Y', 'Z'], [['A']]) === $authentication.allowed('X', 'Y', 'Z', 'A')
profile()
// Get or set the current user profile from local storage.// If data is provided then it overwrites the existing user profile before returning it.$authentication.profile(data);
roles()
// Return the current collection of roles of the user profile from local storage if it exists.$authentication.roles();
isInAllRoles(...)
// Return true if the current user profile is in all of the specified roles, false otherwise.$authentication.isInAllRoles('role1', 'role2', ...); // will flatten provided arrays that are any depth in the arguments list$authentication.isInAllRoles('X', ['Y', 'Z'], [['A']]) === $authentication.isInAllRoles('X', 'Y', 'Z', 'A')
isInAnyRoles()
// Return true if the current user profile is in at least one of the specified roles, false otherwise.$authentication.isInAnyRoles('role1', 'role2', ...); // will flatten provided arrays that are any depth in the arguments list$authentication.isInAnyRoles('X', ['Y', 'Z'], [['A']]) === $authentication.isInAnyRoles('X', 'Y', 'Z', 'A')
permit(...)
// Determine if the current user profile is allowed and redirect to either notAuthorizedRedirectUrl or notAuthenticatedRedirectUrl if not.$authentication.permit('role1', 'role2', ...); // will flatten provided arrays that are any depth in the arguments list$authentication.permit('X', ['Y', 'Z'], [['A']]) === $authentication.permit('X', 'Y', 'Z', 'A')
getConfiguration()
// Return the configuration object.$authentication.getConfiguration();
getLastAttemptedUrl(fallback)
// Return the last attempted url value, or fallback if value is undefined or tracking is disabled,.$authentication.getLastAttemptedUrl();
setLastAttemptedUrl(value)
// Set and return the last attempted url value.$authentication.setLastAttemptedUrl();
store()
// Returns the configured storage service.$authentication.store();
reauthenticate()
// Enable re-authentication via the configured reauthentication.fn at reauthentication.timeout intervals.$authentication.reauthenticate();
$onLoginConfirmed(handler)
// Sets the provided function handler as a listener to the event: 'event:auth-loginConfirmed'.// The event data is the data provided to the loginConfirmed call that triggered this event.$authentication.$onLoginConfirmed(function (event, data) { ... });
$onLoginRequired(handler)
// Sets the provided function handler as a listener to the event: 'event:auth-loginRequired'.$authentication.$onLoginRequired(function (event) { ... });
$onLogoutConfirmed(handler)
// Sets the provided function handler as a listener to the event: 'event:auth-logoutConfirmed'.$authentication.$onLogoutConfirmed(function (event) { ... });
$onNotAuthenticated(handler)
// Sets the provided function handler as a listener to the event: 'event:auth-notAuthenticated'.// The event data is the array of arguments provided to the permit call that triggered this event.$authentication.$onNotAuthenticated(function (event, data) { ... });
$onNotAuthorized(handler)
// Sets the provided function handler as a listener to the event: 'event:auth-notAuthorized'.// The event data is the array of arguments provided to the permit call that triggered this event.$authentication.$onNotAuthorized(function (event, data) { ... });
Development
After forking you should only have to run npm install
from a command line to get your environment setup.
After install you have two gulp commands available to you:
gulp js:lint
gulp js:test