Is there a way to set the $httpProvider headers outside of angular.module('myApp', []).config()?
I'm getting an Auth-Token from the server after I login the user, and I need to add it as a HTTP Header to all following requests.
You can use default headers for angular 1.0.x:
$http.defaults.headers.common['Authentication'] = 'authentication';
or request interceptor for angular 1.1.x+:
myapp.factory('httpRequestInterceptor', function () {
return {
request: function (config) {
// use this to destroying other existing headers
config.headers = {'Authentication':'authentication'}
// use this to prevent destroying other existing headers
// config.headers['Authorization'] = 'authentication';
return config;
}
};
});
myapp.config(function ($httpProvider) {
$httpProvider.interceptors.push('httpRequestInterceptor');
});
Since factories/services are singletons, this works as long as you do not need to dynamically change your 'authentication' value after the service has been instantiated.
$http.defaults.headers.common['Auth-Token'] = 'token';
It seems headers() normalizes the key names.
Adding to above responses of #Guria and #Panga
config.headers['X-Access-Token'] = $window.sessionStorage.token;
One can use x-access-token in header as JWT(jsonwebtoken).
I store JWT in the session storage when a user authenticate first time.
Related
We are in the middle of converting our entire web infrastructure to use JWT as our Bearer auth tokens and I added a global interceptor on our $httpProvider that will read the token from a service that was previously (in a resolve for the root state of our app) fetched from our Auth server.
The problem is that I get a circular dependency because the initial call to GET /api/oauth/token uses the $http service which uses my interceptor. Therefore, the only way I think I can do this is to not use $http in that initial request, right?
What is the correct way to do this? It feels wrong to use jQuery here to make the AJAX call, but is that the best way?
app.factory('AuthProvider', function($http, $q){
var service = {};
var _token = null;
service.getToken = function(){
var deferred = $q.defer();
// the use of $http here is what causes this issue
$http({
method:'GET',
url:'/api/oauth/token'
}).then(function(res){
_token = res.result;
deferred.resolve(_token);
}, function(res){
deferred.reject(res);
});
return deferred.promise;
}
service.readToken = function(){
return _token;
}
return service;
});
i have developed single page application in angularjs. i have implemented the refresh token mechanism. refresh token suppose to refresh every 30 minutes. I am trying to handle refresh token in responseError of interceptor. I m trying to hold request if it returns 401 unauthorised error. Is there any mechanism to hold all the request once it return 401 error then refresh token and resume all request with new token.
Is it right way to handle the refresh token, here is sample code
$provide.factory('httpTokenInterceptor', function ($q, $injector, $cookies) {
return {
// On request sending
request: function (config) {
config.headers = config.headers || {};
// get this data from $cookies
var globals = $cookies.getObject('globals') || {};
//console.log(globals);
if (globals.authData)
config.headers.Authorization = 'Bearer ' + globals.authData.access_token;
return config;
},
// On response failure
responseError: function (rejection) {
console.log('AuthTokenHttpInterceptor responseError');
console.log(rejection);
if (rejection.status === 401) {
//hold current and all pending request
var aService = $injector.get('authenticationService');
aService.getRefreshToken().then(function(response) {
//need to resume all the request here
deferred.resolve(response);
});
return deferred.promise;
}
return $q.reject(rejection);
}
};
});
In short, you don't want to hold up any of your HTTP calls like that.
Your solution will go and refresh your token after one of your HTTP calls already failed. Also, just to be clear, your code is adding Authorization header even on HTTP calls that are getting resources like HTML templates. If you don't want to do this, then you should restrict that as well.
For one solution, check out this link. It doesn't use any particular library for handling JWT tokens, but you will have to create a wrapper around this implementation to use it wherever you need to do a HTTP call.
My suggestion (and personal preference when handling JWT tokens) is using the angular-jwt library. It's really easy to set up and you can check it out here.
There more complex libraries like auth0, which can do a lot of other stuff, and can be used in conjuction with angular-jwt library. Check out this link to see how to handle token refreshing both prior to a HTTP call and on page refresh.
Hope this helps.
You can hold requests and resume them using AngularJS Interceptors.
authInterceptor.$inject = ['$q', '$rootScope'];
function authInterceptor($q, $rootScope) {
return {
request: function(config) {
var deferred = $q.defer();
$rootScope.$watch('continue', function(value) {
if(value === true)
deferred.resolve(config);
});
return deferred.promise;
}
};
}
In the above example all of the requests hold until $rootScope.continue becomes true. Otherwise they will wait forever.
My API uses the Accept-Language header to get it's current language which returns the json translated. Never mind that.
How can i change the header with angularJS/Javasctipt. I tried this:
$http.defaults.headers.post["Accept-Language"] = "bs-Latn-BA";
but it doesn't seem to work, are there any other alternatives?
The default headers sent for every single request live in the $httpProvider.defaults.headers.common object.
You can change or augment these headers using the .config() function for every request, like so:
angular.module('myApp', [])
.config(function($httpProvider) {
$httpProvider.defaults.headers
.common['Accept-Language'] = 'bs-Latn-BA';
});
We can also manipulate these defaults at run time using the defaults property of the $http object. For instance, to add a property for dynamic headers, we can set the header property like so:
$http.defaults
.common['Accept-Language'] = "bs-Latn-BA";
AngularJS you can set common headers by using $httpProvider. Angularjs
Example:
var app = angular.module("app", []);
app.config(["$httpProvider", function($httpProvider) {
// set Accept-Language header on all requests to
$httpProvider.defaults.headers.common["Accept-Language"] = "bs-Latn-BA";
}]);
I'm using Angular.js to build a client side application with Restangular.
The problem is, I implemented a digest authentication with a wsse header which i have to generate at each request to my REST Server.
I saw that Restangular provide a function : addFullRequestInterceptor().
So now, i'm trying to use it inside my RestangularProvider to configure it in this file restangular.js :
// Config Restangular
app.config(function(RestangularProvider) {
RestangularProvider.setBaseUrl(applicationConfig.SERVER_URL);
RestangularProvider.setDefaultHeaders({'Content-Type': 'application/json'});
RestangularProvider.addFullRequestInterceptor(
function (element, operation, route, url, headers, params, httpConfig) {
// Here is my header generation.
$http.defaults.headers.common['X-WSSE'] =
TokenHandler.getCredentials(
AuthHandler.authentication.user.username,
AuthHandler.authentication.secret);
return {
element: element,
headers: headers,
params: params,
httpConfig: httpConfig
};
});
});
But i have an injection problem and i can't find out how to inject my TokenHandler service & my AuthHandler service to be able to know if the user is already loggedin or not and if he has localstroage or not.
Thanks for the help ;)
The problem is that in the .config phase the services, like AuthHandler and TokenHandler are not yet instantiated, so you need to instantiate them (and their dependencies) manually with $injector (which is injectable into config blocks):
app.config(function(RestangularProvider,
$injector,
AuthHandlerProvider,
TokenHandlerProvider) {
var AuthHandler = $injector.instantiate(AuthHandlerProvider.$get);
var TokenHandler = $injector.instantiate(TokenHandlerProvider.$get);
//...
});
I'm trying to write a $http interceptor which will attach a header in order to authorize the application with a token.
I have an auth service which requests and stores the token for future use.
In the application config, I'm configuring $httpProvider and pushing a new interceptor onto the array.
The interceptor depends on my Auth service, in order to get hold of the token to send each time. In turn, the Auth service depends on $http in order to send the initial request to authenticate and retrieve the auth token.
I end up with a circular dependency graph that looks something like:
$httpProvider
^ \
/ v
$http <- Auth Service
Auth depends on $http, and through $httpProvider, $http depends on Auth.
Is there an elegant way to get around this? I thought about using an intermediate service, but ultimately, that would just be extending the dependency graph. Something needs to be fundamentally changed.
Is it possible to do something like resolve and reconfigure $http after the auth token has been retrieved?
You want to use $injector to manually get a hold of your authentication service.
angular.module('app.services.authentication')
.factory('AuthenticationHeaderInterceptor', ['$injector', AuthenticationHeaderInterceptor]);
function AuthenticationHeaderInterceptor ($injector) {
var service = {
request: addAuthenticationHeader
};
return service;
function addAuthenticationHeader (config) {
var token = null;
// Need to manually retrieve dependencies with $injector.invoke
// because Authentication depends on $http, which doesn't exist during the
// configuration phase (when we are setting up interceptors).
// Using $injector.invoke ensures that we are provided with the
// dependencies after they have been created.
$injector.invoke(['Authentication', function (Authentication) {
token = Authentication.getAuthenticationHeaders();
}]);
if (token) {
angular.extend(config.headers, token);
}
return config;
}
}