Skip to content

cloudspace/angular_devise

Repository files navigation

AngularDevise Build Status

A small AngularJS Service to interact with Devise Authentication.

Requirements

This service requires Devise to respond to JSON. To do that, simply add

# config/application.rbmoduleRailsAppclassApplication < Rails::Application# ...config.to_preparedoDeviseController.respond_to:html,:jsonendendend

Additionally, if you have CSRF Forgery Protection enabled for your controller actions, you will also need to include the X-CSRF-TOKEN header with the token provided by rails. The easiest way to include this is to follow this post:

angular_rails_csrf.

Downloading

AngularDevise is registered as angular-devise in bower.

bower install --save angular-devise

You can then use the main file at angular-devise/lib/devise-min.js.

Rails Assets

To get AngularDevise via Rails Assets add to your Gemfile:

source"https://rails-assets.org"dogem"rails-assets-angular-devise"end

Then bundle. Finally, to require the JS:

//= require angular-devise

Usage

Just register Devise as a dependency for your module. Then, the Auth service will be available for use.

angular.module('myModule',['Devise']).config(function(AuthProvider){// Configure Auth service with AuthProvider}).controller('myCtrl',function(Auth){// Use your configured Auth service.});

Auth.currentUser()

Auth.currentUser() returns a promise that will be resolved into the currentUser. There are three possible outcomes:

  1. Auth has authenticated a user, and will resolve with that user.
  2. Auth has not authenticated a user but the server has a previously authenticated session, Auth will attempt to retrieve that session and resolve with its user. Then, a devise:new-session event will be broadcast with the current user as the argument.
  3. Neither Auth nor the server has an authenticated session, and a rejected promise will be returned. (see Interceptor for for custom handling.)
angular.module('myModule',['Devise']).controller('myCtrl',function(Auth){Auth.currentUser().then(function(user){// User was logged in, or Devise returned// previously authenticated session.console.log(user);// =>{id: 1, ect: '...'}},function(error){// unauthenticated error});});

Auth._currentUser

Auth._currentUser will be either null or the currentUser's object representation. It is not recommended to directly access Auth._currentUser, but instead use Auth.currentUser().

angular.module('myModule',['Devise']).controller('myCtrl',function(Auth){console.log(Auth._currentUser);// => null// Log in user...console.log(Auth._currentUser);// =>{id: 1, ect: '...'}});

Auth.isAuthenticated()

Auth.isAuthenticated() is a helper method to determine if a currentUser is logged in with Auth.

angular.module('myModule',['Devise']).controller('myCtrl',function(Auth){console.log(Auth.isAuthenticated());// => false// Log in user...console.log(Auth.isAuthenticated());// => true});

Auth.login(creds, config)

Use Auth.login() to authenticate with the server. Keep in mind, credentials are sent in plaintext; use a SSL connection to secure them. creds is an object which should contain any credentials needed to authenticate with the server. Auth.login() will return a promise that will resolve to the logged-in user. See Auth.parse(response) to customize how the response is parsed into a user.

Upon a successful login, two events will be broadcast, devise:login and devise:new-session, both with the currentUser as the argument. New-Session will only be broadcast if the user was logged in by Auth.login({...}). If the server has a previously authenticated session, only the login event will be broadcast.

Pass any additional config options you need to provide to $http with config.

angular.module('myModule',['Devise']).controller('myCtrl',function(Auth){varcredentials={email: '[email protected]',password: 'password1'};varconfig={headers: {'X-HTTP-Method-Override': 'POST'}};Auth.login(credentials,config).then(function(user){console.log(user);// =>{id: 1, ect: '...'}},function(error){// Authentication failed...});$scope.$on('devise:login',function(event,currentUser){// after a login, a hard refresh, a new tab});$scope.$on('devise:new-session',function(event,currentUser){// user logged in by Auth.login({...})});});

By default, login will POST to '/users/sign_in.json' using the resource name user. The path, HTTP method, and resource name used to login are configurable using:

angular.module('myModule',['Devise']).config(function(AuthProvider){AuthProvider.loginPath('path/on/server.json');AuthProvider.loginMethod('GET');AuthProvider.resourceName('customer');});

Auth.logout()

Use Auth.logout() to de-authenticate from the server. Auth.logout() returns a promise that will be resolved to the old currentUser. Then a devise:logout event will be broadcast with the old currentUser as the argument.

Pass any additional config options you need to provide to $http with config.

angular.module('myModule',['Devise']).controller('myCtrl',function(Auth){varconfig={headers: {'X-HTTP-Method-Override': 'DELETE'}};// Log in user...// ...Auth.logout(config).then(function(oldUser){// alert(oldUser.name + "you're signed out now.");},function(error){// An error occurred logging out.});$scope.$on('devise:logout',function(event,oldCurrentUser){// ...});});

By default, logout will DELETE to '/users/sign_out.json'. The path and HTTP method used to logout are configurable using:

angular.module('myModule',['Devise']).config(function(AuthProvider){AuthProvider.logoutPath('path/on/server.json');AuthProvider.logoutMethod('GET');});

Auth.parse(response)

This is the method used to parse the $http response into the appropriate user object. By default, it simply returns response.data. This can be customized either by specifying a parse function during configuration:

angular.module('myModule',['Devise']).config(function(AuthProvider){// Customize user parsing// NOTE: **MUST** return a truth-y expressionAuthProvider.parse(function(response){returnresponse.data.user;});});

or by directly overwriting it, perhaps when writing a custom version of the Auth service which depends on another service:

angular.module('myModule',['Devise']).factory('User',function(){// Custom user factory}).factory('CustomAuth',function(Auth,User){Auth['parse']=function(response){returnnewUser(response.data);};returnAuth;});

Auth.register(creds)

Use Auth.register() to register and authenticate with the server. Keep in mind, credentials are sent in plaintext; use a SSL connection to secure them. creds is an object that should contain any credentials needed to register with the server. Auth.register() will return a promise that will resolve to the registered user. See Auth.parse(response) to customize how the response is parsed into a user. Then a devise:new-registration event will be broadcast with the user object as the argument.

Pass any additional config options you need to provide to $http with config.

angular.module('myModule',['Devise']).controller('myCtrl',function(Auth){varcredentials={email: '[email protected]',password: 'password1',password_confirmation: 'password1'};varconfig={headers: {'X-HTTP-Method-Override': 'POST'}};Auth.register(credentials,config).then(function(registeredUser){console.log(registeredUser);// =>{id: 1, ect: '...'}},function(error){// Registration failed...});$scope.$on('devise:new-registration',function(event,user){// ...});});

By default, register will POST to '/users.json' using the resource name user. The path, HTTP method, and resource name used to register are configurable using:

angular.module('myModule',['Devise']).config(function(AuthProvider){AuthProvider.registerPath('path/on/server.json');AuthProvider.registerMethod('GET');AuthProvider.resourceName('customer');});

Auth.sendResetPasswordInstructions(creds)

Use Auth.sendResetPasswordInstructions() to send reset password mail to user. Keep in mind, credentials are sent in plaintext; use a SSL connection to secure them. creds is an object that should contain the email associated with the user. Auth.sendResetPasswordInstructions() will return a promise with no params. Then a devise:send-reset-password-instructions-successfully event will be broadcast.

angular.module('myModule',['Devise']).controller('myCtrl',function(Auth){varparameters={email: '[email protected]'};Auth.sendResetPasswordInstructions(parameters).then(function(){// Sended email if user found otherwise email not sended...});$scope.$on('devise:send-reset-password-instructions-successfully',function(event){// ...});});

By default, sendResetPasswordInstructions will POST to '/users/password.json'. The path and HTTP method used to send the reset password instructions are configurable using:

angular.module('myModule',['Devise']).config(function(AuthProvider){AuthProvider.sendResetPasswordInstructionsPath('path/on/server.json');AuthProvider.sendResetPasswordInstructionsMethod('POST');});

Auth.resetPassword(creds)

Use Auth.resetPassword() to reset user password. Keep in mind, credentials are sent in plaintext; use a SSL connection to secure them. creds is an object that should contain password, password_confirmation and reset_password_token. Auth.resetPassword() will return a promise that will resolve to the new user data. See Auth.parse(response) to customize how the response is parsed into a user. Then a devise:reset-password-successfully event will be broadcast.

angular.module('myModule',['Devise']).controller('myCtrl',function(Auth){varparameters={password: 'new_password',password_confirmation: 'new_password',reset_password_token: 'reset_token',};Auth.resetPassword(parameters).then(function(new_data){console.log(new_data);// =>{id: 1, ect: '...'}},function(error){// Reset password failed...});$scope.$on('devise:reset-password-successfully',function(event){// ...});});

By default, resetPassword will PUT to '/users/password.json'. The path and HTTP method used to reset password are configurable using:

angular.module('myModule',['Devise']).config(function(AuthProvider){AuthProvider.resetPasswordPath('path/on/server.json');AuthProvider.resetPasswordMethod('PUT');});

Interceptor

AngularDevise comes with a $http Interceptor that may be enabled using the interceptAuth config. Its purpose is to listen for 401 Unauthorized responses and give you the ability to seamlessly recover. When it catches a 401, it will:

  1. create a deferred
  2. broadcast a devise:unauthorized event passing:
    • the ajax response
    • the deferred
  3. return the deferred's promise

Since the deferred is passed to the devise:unauthorized event, you are free to resolve it (and the request) inside of the event listener. For instance:

angular.module('myModule',[]).controller('myCtrl',function($scope,Auth,$http){// Guest user// Catch unauthorized requests and recover.$scope.$on('devise:unauthorized',function(event,xhr,deferred){// Disable interceptor on _this_ login request,// so that it too isn't caught by the interceptor// on a failed login.varconfig={interceptAuth: false};// Ask user for login credentialsAuth.login(credentials,config).then(function(){// Successfully logged in.// Redo the original request.return$http(xhr.config);}).then(function(response){// Successfully recovered from unauthorized error.// Resolve the original request's promise.deferred.resolve(response);},function(error){// There was an error logging in.// Reject the original request's promise.deferred.reject(error);});});// Request requires authorization// Will cause a `401 Unauthorized` response,// that will be recovered by our listener above.$http.delete('/users/1',{interceptAuth: true}).then(function(response){// Deleted user 1},function(error){// Something went wrong.});});

The Interceptor can be enabled globally or on a per-request basis using the interceptAuth setting on the AuthIntercept provider.

angular.module('myModule',['Devise']).config(function(AuthInterceptProvider){// Intercept 401 Unauthorized everywhereAuthInterceptProvider.interceptAuth(true);}).controller('myCtrl',function($http){// Disable per-request$http({url: '/',interceptAuth: false,// ...});});

AuthProvider

By default, AngularDevise uses the following HTTP methods/paths:

MethodHTTP MethodHTTP Path
loginPOST/users/sign_in.json
logoutDELETE/users/sign_out.json
registerPOST/users.json
sendResetPasswordInstructionsPOST/users/password.json
resetPassword POST/users/password.json

All credentials will be under the users namespace, and the following parse function will be used to parse the response:

function(response){returnresponse.data;};

All of these can be configured using a .config block in your module.

angular.module('myModule',['Devise']).config(function(AuthProvider,AuthInterceptProvider){// Customize loginAuthProvider.loginMethod('GET');AuthProvider.loginPath('/admins/login.json');// Customize logoutAuthProvider.logoutMethod('POST');AuthProvider.logoutPath('/user/logout.json');// Customize registerAuthProvider.registerMethod('PATCH');AuthProvider.registerPath('/user/sign_up.json');// Customize the resource name data use namespaced under// Pass false to disable the namespace altogether.AuthProvider.resourceName('customer');// Also you can change host URL for backend calls// (for example if it's on another server than your angular app)AuthProvider.baseUrl('http://localhost:3000');// Customize user parsing// NOTE: **MUST** return a truth-y expressionAuthProvider.parse(function(response){returnresponse.data.user;});// Intercept 401 Unauthorized everywhere// Enables `devise:unauthorized` interceptorAuthInterceptProvider.interceptAuth(true);});

Credits

Cloudspace

AngularDevise is maintained by Cloudspace, and is distributed under the MIT License.

About

A small AngularJS Service to interact with Devise Authentication.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 18