I am new to AngularJS. What I want is getting a token coming from a server with $http post and then use that token coming from the request to use as an authorization header for access in other page and following data requests to the server. Here is my existing code:
var peopleApp = angular.module('peopleApp', ['ngRoute', 'ngAnimate']);
peopleApp.config(function($interpolateProvider, $httpProvider) {
// Change template tags
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
// Enabling CORS
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
// $httpProvider.defaults.withCredentials = true;
});
peopleApp.controller('formController', function($scope, $http, $location) {
$scope.logIn = function(json, url){
$http.post(url, json)
.then(function(response){
token = response.data.token;
window.location.href = 'crew-menu';
},function(response){
alert('Please check the following validations on the next alert and contact the creators regarding this error');
alert(JSON.stringify(response.data.errors));
});
}
});
P.S.
I am aware that this can be done by using the .run like this:
peopleApp.run(function($http) {
$http.defaults.headers.common.Authorization = 'YmVlcDpib29w';
});
However the token Authorization will be coming from a login authentication via post request
Step 1
Take the token from login response and save it somewhere in the app, most common solution is to store it in local storage so it will be available after browser restart.
$scope.logIn = function(json, url){
$http.post(url, json)
.then(function(response){
localStorageService.set('authorizationData', { token: response.data.token });
window.location.href = 'crew-menu';
},function(response){
alert('Please check the following validations on the next alert and contact the creators regarding this error');
alert(JSON.stringify(response.data.errors));
});
}
Step 2
Use angularjs $http interceptor to automatically add authentication header to every http request:
app.factory('authInterceptorService', ['$q', '$location', 'localStorageService', function ($q, $location, localStorageService) {
var authInterceptorServiceFactory = {};
var _request = function (config) {
config.headers = config.headers || {};
var authData = localStorageService.get('authorizationData');
if (authData) {
config.headers.Authorization = 'Bearer ' + authData.token;
}
return config;
}
var _responseError = function (rejection) {
if (rejection.status === 401) {
$location.path('/login');
}
return $q.reject(rejection);
}
authInterceptorServiceFactory.request = _request;
authInterceptorServiceFactory.responseError = _responseError;
return authInterceptorServiceFactory;
}]);
Or put it manualy every time you make http request:
function buildConfig() {
var c = {};
var authData = localStorageService.get('authorizationData');
if (authData) {
c.headers.Authorization = 'Bearer ' + authData.token;
}
return c;
}
function post(url, model) {
return $http.post(url, model, buildConfig());
}
More info: here and
my angular webapi project
Already solved it. The solution is to store the token in a localstorage first then use run function for it be a default. Here is the code:
var peopleApp = angular.module('peopleApp', ['ngRoute', 'ngAnimate']);
peopleApp.config(function($interpolateProvider, $httpProvider) {
// Change template tags
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
// Enabling CORS
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
// $httpProvider.defaults.withCredentials = true;
});
peopleApp.controller('formController', function($scope, $http, $location, $window) {
$scope.logIn = function(json, url){
$http.post(url, json)
.then(function(response){
token = response.data.token;
$window.localStorage.token = token;
window.location.href = 'crew-menu';
},function(response){
alert('Please check the following validations on the next alert and contact the creators regarding this error');
alert(JSON.stringify(response.data.errors));
});
}
});
peopleApp.run(function($window, $http){
if ($window.localStorage.token){
$http.defaults.headers.common.Authorization = "Token "+$window.localStorage.token;
}
});
Related
What is wrong with the code it's not working, I am trying to request call web service from backend written in spring, the value passing from backend is token wrapped, I am trying to run the code on client side but form is not passing any value.
auth.js
'use strict';
angular. module('app')
.factory('Auth', [ '$http', '$rootScope', '$window', 'Session', 'AUTH_EVENTS',
function($http, $rootScope, $window, Session, AUTH_EVENTS) {
var authService = {};
this.isLoggedIn = function isLoggedIn(){
return session.getUser() !== null;
};
//the login function
authService.login = function(user, success, error) {
$http.post('URL: http://xxx.xxx.x.xx:xxxx/xxxx/authenticateUser').success(function(authData) {
//user is returned with his data from the db
var users = data.users;
if(users[user.username]){
var loginData = users[user.username];
//insert your custom login function here
if(user.username == loginData.username && user.password == loginData.username){
localStorageService.set(['userInfo'],
{ token: result.access_token, userName: loginData.userName });
//delete password no/t to be seen clientside
delete loginData.password;
//update current user into the Session service or $rootScope.currentUser
//whatever you prefer
Session.create(loginData);
//or
$rootScope.currentUser = loginData;
//fire event of successful login
$rootScope.$broadcast(AUTH_EVENTS.loginSuccess);
//run success function
success(loginData);
} else{
//OR ELSE
//unsuccessful login, fire login failed event for
//the according functions to run
$rootScope.$broadcast(AUTH_EVENTS.loginFailed);
error();
}
}
});
};
//check if the user is authenticated
authService.isAuthenticated = function() {
return !!Session.user;
};
//check if the user is authorized to access the next route
//this function can be also used on element level
//e.g. <p ng-if="isAuthorized(authorizedRoles)">show this only to admins</p>
authService.isAuthorized = function(authorizedRoles) {
if (!angular.isArray(authorizedRoles)) {
authorizedRoles = [authorizedRoles];
}
return (authService.isAuthenticated() &&
authorizedRoles.indexOf(Session.userRole) !== -1);
};
//log out the user and broadcast the logoutSuccess event
authService.logout = function(){
Session.destroy();
localStorageService.removeItem("userInfo");
$rootScope.$broadcast(AUTH_EVENTS.logoutSuccess);
}
return authService;
} ]);
authInterceptor
(function () {
'use strict';
var app = angular.module('app');
var factoryId = 'authInterceptor';
app.factory(factoryId, authInterceptor);
authInterceptor.$inject = ['$q', '$location', 'localStorageService', $rootScope, $http];
function authInterceptor($q, $location, localStorageService) {
var service = {
request: request,
responseError: responseError,
};
return service;
function request(config) {
config.headers = config.headers || {};
var authData = localStorageService.get('authorizationData');
if (authData) {
config.headers.Authorization = 'Bearer ' + authData.token;
}
return config;
}
function responseError(error) {
var loggedIn = false;
var authData = localStorageService.get('authorizationData');
if (authData) {
loggedIn = true;
}
//We only want to go to the login page if the user is not
//logged in. If the user is logged in and they get a 401 is
//because they don't have access to the resource requested.
if (error.status === 401 && !loggedIn) {
$location.path('/login').replace();
}
return $q.reject(error);
}
}
})();
Using AngularJS for my application and for http post the server needs a token that we can get by http get. But I want to run the token_generate() function before each http call, because sometimes the token expires
token = function() {
var api = AuthService.getToken();
api.success(function (response) {
var token = response.token;
$http.defaults.headers.common['X-CSRF-TOKEN'] = token;
});
};
token();
You need to register an $http interceptor:
(function(window, angular) {
function tokenizerConfig($httpProvider) {
function registerInterceptors($q, $http, AuthenticationService) {
var interceptors = {};
interceptors.request = function(configs) {
if(AuthenticationService.isTokenValid) {
return $q.when(configs);
}
var qs = {};
return $http
.get(TOKEN_API, { cache: false, params: qs})
.then(function(result) {
AuthenticationService.setToken(result.data.token);
return configs;
})
;
};
return interceptors;
}
$httpProvider.interceptors.push(['$q', '$http', 'AuthenticationService', registerInterceptors]);
}
angular
.module('tokenizer', [])
.config(['$httpProvider', tokenizerConfig])
})(window, window.angular);
I am creating a simple login application using HTTP Auth Interceptor Module.
in my LoginController I have:
angular.module('Authentication')
.controller('LoginController',
['$scope', '$rootScope', '$location', 'AuthenticationService',
function ($scope, $rootScope, $location, AuthenticationService) {
// reset login status
AuthenticationService.ClearCredentials();
$scope.login = function () {
$scope.dataLoading = true;
AuthenticationService.Login($scope.username, $scope.password, function (response) {
if (response.success) {
AuthenticationService.SetCredentials($scope.username, $scope.password);
$location.path('/');
} else {
$scope.error = response.message;
$scope.dataLoading = false;
}
});
};
}]);
and following is the simple service for it:
angular.module('Authentication')
.factory('AuthenticationService',
['Base64', '$http', '$cookieStore', '$rootScope', '$timeout',
function (Base64, $http, $cookieStore, $rootScope, $timeout, $scope) {
var service = {};
service.Login = function ($scope, username, password, callback) {
$http
.get('http://Foo.com/api/Login',
{ username: username, password: password } , {withCredentials: true}).
then(function (response) {
console.log('logged in successfully');
callback(response);
}, function (error) {
console.log('Username or password is incorrect');
});
};
service.SetCredentials = function (username, password) {
var authdata = Base64.encode(username + ':' + password);
$rootScope.globals = {
currentUser: {
username: username,
authdata: authdata
}
};
$http.defaults.headers.common['Authorization'] = 'Basic ' + authdata;
$http.defaults.headers.common['Content-Type'] = 'application/json'
$cookieStore.put('globals', $rootScope.globals);
};
service.ClearCredentials = function () {
$rootScope.globals = {};
$cookieStore.remove('globals');
$http.defaults.headers.common.Authorization = 'Basic ';
};
return service;
}])
This is my login page:
as I try to test this in browser, instead of successful login or even receiving an error, I get this popup:
what I don't get is that why the credential passed from the login form is not taken into account. and how can I get rid of this popup.
as I cancel this popup, again instead of getting the error for http request, in console I get 401 (Unauthorized) Error.
What am I missing?
I also ran in in Emulator and instead of getting any error, the application stays on loading part.
Change your URL to something like
.get('https://username:password#Foo.com/api/Login',...
use the following sample to handle 401 error:
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.withCredentials = true;
$httpProvider.interceptors.push(['$q', function ($q) {
return {
'responseError': function (rejection) {
if (rejection.status === 401) {
console.log('Got a 401');
}
return $q.reject(rejection)
}
}
}])
}])
Here is the working code snippet. Just copy paste from here.
routerApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.withCredentials = true;
$httpProvider.interceptors.push(['$q', function ($q) {
return {
'responseError': function (rejection) {
if (rejection.status === 401) {
window.console.log('Got a 401');
}
return $q.reject(rejection);
}
};
}]);
}]);
I am building a simple Client App which is talking to a rest api and getting information about the user. I am implementing Resource Owner Password Credentials Flow of OAuth.
I have been struggling with how to send my client ID and Secret in Authorization header in an angular app.
I have built an authService and an interceptor service to handle my login.
my app.js
'use strict';
var app = angular.module('AngularAuthApp', ['ngRoute', 'LocalStorageModule', 'angular-loading-bar']);
app.config(function ($routeProvider) {
$routeProvider.when("/home", {
controller: "homeController",
templateUrl: "/views/home.html"
});
$routeProvider.when("/login", {
controller: "loginController",
templateUrl: "/views/login.html"
});
$routeProvider.otherwise({ redirectTo: "/home" });
});
app.run(['authService', function (authService) {
authService.fillAuthData();
}]);
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptorService');
});
this is my authService.js
app.factory('authService', ['$http', '$q', 'localStorageService', function ($http, $q, localStorageService) {
var serviceBase = 'http://url/oauth/';
var authServiceFactory = {};
var _authentication = {
isAuth: false,
userName : ""
};
var _login = function (loginData) {
var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password ;
var deferred = $q.defer();
$http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
deferred.resolve(response);
}).error(function (err, status) {
_logOut();
deferred.reject(err);
});
return deferred.promise;
};
authServiceFactory.login = _login;
return authServiceFactory;
}]);
and authInterceptorService.js
app.factory('authInterceptorService', ['$q', '$location', 'localStorageService', function ($q, $location, localStorageService) {
var authInterceptorServiceFactory = {};
var _request = function (config) {
config.headers = config.headers || {};
var authData = localStorageService.get('authorizationData');
if (authData) {
config.headers.Authorization = 'Bearer ' + authData.token;
}
return config;
}
var _responseError = function (rejection) {
if (rejection.status === 401) {
$location.path('/login');
}
return $q.reject(rejection);
}
authInterceptorServiceFactory.request = _request;
authInterceptorServiceFactory.responseError = _responseError;
return authInterceptorServiceFactory;
}]);
My curl request which throws me an access token is
curl -X POST -vu sampleapp:samplekey http://sampleurl/oauth/token -H "Accept: application/json" -d "password=pwd&username=uname&grant_type=password&scope=read%20write&client_secret=samplekey&client_id=sampleapp"
So, I am guessing that I need to send the clientID and clientSecret but am not sure how to implement it or where to add it. I have looked into documents saying that we might need to add to authorization header but I don't think I'm doing it right. Also, do I need to encode it or anything ? This is not a JWT token but a simple token. Do I also need to send in the scope ?
I am getting a 401 error of Full authentication is required to access this resource as of now.
I'm trying to authenticate user through token. if i login then token will be created and stored in local storage. whenever there is a change in route I'm hitting the api which is built in express js , gives me decoded user value. everything works without refresshing page. Once I refresh the page I'm not able to hit the API. in order to get decoded user value i suppose to click on login button which is there in header , which triggers the route change then again everything works fine. Please help me out .
.controller('mainController', function($rootScope, $location, $window ,Auth){
var vm = this;
$rootScope.loggedIn = Auth.isLoggedIn();
$rootScope.$on('$locationChangeStart', function(){
$rootScope.loggedIn = Auth.isLoggedIn();
Auth.getUser()
.then(function(data){
$rootScope.user = data.data;
});
});
vm.login = function(){
......
}
vm.logout = function(){
......
}
})
Service
.factory('Auth', function($http, $q, AuthToken){
var authFactory = {};
authFactory.login = function(username, password){
return $http.post('/api/login', {
username: username,
password: password
})
.success(function(data){
AuthToken.setToken(data.token);
return data;
});
};
authFactory.logout = function(){
AuthToken.setToken();
};
authFactory.isLoggedIn = function(){
if(AuthToken.getToken()){
return true;
} else {
return false;
}
};
authFactory.getUser = function(){
if(AuthToken.getToken()){
return $http.get('/api/me');
} else {
return $q.reject({ message: "User has no token"});
}
};
return authFactory;
})
factory for setting token and interceptor code
.factory('AuthToken', function($window){
var authTokenFactory = {};
authTokenFactory.getToken = function(){
return $window.localStorage.getItem('token');
};
authTokenFactory.setToken = function(token){
if(token){
$window.localStorage.setItem('token', token);
} else {
$window.localStorage.removeItem('token');
}
};
return authTokenFactory;
})
.factory('AuthInterceptor', function($q, $location, AuthToken){
var interceptorFactory = {};
interceptorFactory.request = function(config){
var token = AuthToken.getToken();
if(token){
config.headers['x-access-token'] = token;
}
return config;
};
interceptorFactory.responseError = function(response){
if(response.status == 403){
$location.path('/login');
}
return $q.reject(response);
};
return interceptorFactory;
});
It may be that you have to reset the $http default headers on refresh. Using cookies in my case, I make a call to the following function at the beginning of $on('$stateChangeStart'):
service.RefreshGlobalVars = function () {
if ($http.defaults.headers.common.RefreshToken == null) {
$http.defaults.headers.common.Authorization = "Bearer " + $cookieStore.get('_Token');
$http.defaults.headers.common.RefreshToken = $cookieStore.get('_RefreshToken');
}
};
edit- to clarify, since I haven't seen your setToken() function, your implementation may vary, but that's pretty much the gist of it.
I got answer, solved it by checking route change in the main app.js, inside run block.
MyApp.run(function ($rootScope, $location, Auth){
$rootScope.loggedIn = Auth.isLoggedIn();
$rootScope.$on('$locationChangeStart', function(){
$rootScope.loggedIn = Auth.isLoggedIn();
Auth.getUser()
.then(function(data){
$rootScope.user = data.data;
});
});