Add Firebase Token to Angular $HTTP header - angularjs

So I want to add a firebase token to all http requests. I am using the angularJS 1.X framework.
I have an interceptor function which normally I would just add it like this:
.factory('Interceptor', function () {
interceptorFactory.request = function (config) {
config.token = firebaseToken;
return config;
};
return interceptorFactory;
})
.config(function ($httpProvider) {
$httpProvider.interceptors.push('Interceptor');
});
But the issue is the only way to get the firebase token is through a promise, so for that I would need to do something like this:
.factory('Interceptor', function () {
interceptorFactory.request = function (config) {
getFirebaseToken().then(function(token){
config.token = token;
return config;
});
};
return interceptorFactory;
})
.config(function ($httpProvider) {
$httpProvider.interceptors.push('Interceptor');
});
The problem though, is because the token is retrieved Asyncronously, the factory interceptor does not wait for promise to resolve, so the request is sent without the token. If anyone knows how to get around this that would be help full.
Also, I know I could just get the token before I make every http request but then that would cause a lot of duplicate code, and I can't get the token on application startup and just store it cause it has an expiration.

Related

AngularJs http request priorities and http interceptors

I have been looking at an application I made a while back and there is a particular page where the details are being loaded last. Because of this, it seems to be queuing the request (there are more than 6 others before it) and that is causing the page to be slow.
I figured I could find a solution to prioritize these requests and I found this:
How to prioritize requests in angular $http service?
So I created my version of it and added it to my interceptors:
// Add our auth interceptor to handle authenticated requests
$httpProvider.interceptors.push('authInterceptor');
$httpProvider.interceptors.push('httpPriorityInterceptor');
The interceptor looks like this:
function factory($injector, $q) {
var requestStack = [], // request stack
$http = null; // http service to be lazy loaded
return {
request: request,
responseError: responseError
};
//////////////////////////////////////////////////
function request(config) {
// Lazy load $http service
if (!$http) {
$http = $injector.get('$http');
}
if (!config.hasBeenRequested) {
config.hasBeenRequested = true;
config.priority = config.priority || 3;
console.log(config);
// add a copy of the configuration
// to prevent it from copying the timeout property
requestStack.push(angular.copy(config));
// sort each configuration by priority
requestStack = requestStack.sort(sort);
// cancel request by adding a resolved promise
config.timeout = $q.when();
}
// return config
return config;
}
function responseError(rejection) {
// check if there are requests to be processed
if (requestStack.length > 0) {
requestStack.reduceRight(function(promise, config) {
return promise.finally(function() {
return $http(config);
});
}, $q.when());
requestStack.length = 0;
}
// return rejected request
return $q.reject(rejection);
}
//////////////////////////////////////////////////
function sort(config1, config2) {
return config1.priority < config2.priority;
}
}
The problem is, it seems to be intercepting template requests too. I have no issue with that, but they are not resolving. Instead I get a lot of errors:
Error: [$templateRequest:tpload] Failed to load template: app/accounts/accounts.html (HTTP status: -1 )
Has anyone encountered this before? Is there something I can do to fix this?
you should know that every request such as html files , css file and ... comes into interceptor.
in your case you dont need to prioritize this files. so you can filter your request like:
if (config.url.toString().toLowerCase().includes("api")) {
//place your functionality
}

Simple interceptor that will fetch all requests and add the jwt token to its authorization header

In my efforts to setup login required to protected pages and reroute to the login page if not authorized, while using Django REST Framework and DRF-JWT, I am trying to go through the following tutorial:
https://www.octobot.io/blog/2016-11-11-json-web-token-jwt-authentication-in-a-djangoangularjs-web-app/
I am not sure what this looks like in step 3 of the front-end section.
// Add a simple interceptor that will fetch all requests and add the jwt token to its authorization header.
Can someone provide an example?
Also, my original post regarding the issues I am having setting this up in general.
Trying to get login required to work when trying to access protected pages
Thanks!
The interceptors are service factories that are registered with the
$httpProvider by adding them to the $httpProvider.interceptors array.
The factory is called and injected with dependencies (if specified)
and returns the interceptor.
The basic idea behind intercepter is that it will be called before each $http request and you could use a service to check if user is logged in and add a token or anything else that needs to be added into the header.You could also add some logic for response for each $http request, like handling the response based on status code.
Here is how you can use it in angular for adding the access token for each http request.
angular.module('myapp')
.run(['$rootScope', '$injector', function($rootScope,$injector) {
$injector.get("$http").defaults.transformRequest = function(data, headersGetter) {
if (sessionService.isLogged()) {
headersGetter()['Authorization'] = "Bearer " + sessionService.getAccessToken();
}
if (data) {
return angular.toJson(data);
}
};
});
Here is how you can use response intercepter:
angular.module('myapp')
.factory('authHttpResponseInterceptor', function($q, $location, sessionService, $http) {
return {
response: function(response) {
//some logic here
return response || $q.when(response);
},
responseError: function(rejection) {
if (rejection.status === 401) {
//some logic here
}
return $q.reject(rejection);
}
}
});

sending headers using $resource in angular js

I want to send headers each time for CRUD operation from factory side.
Here is my factory
var appangular.module("LifeStyleFactModule",["ngResource"]);
app.constant("RES_URL", "http://localhost:9090/")
app.factory("CategoryFactory",function($resource,RES_URL){
var categoryinfo;
var categoryresource=$resource(RES_URL+"category/:id",{"id":"#id"},{update:{method:"PUT"}});
return{
getcategory:function(){
categoryinfo=categoryresource.query();
return categoryinfo;
},
addcategoryItem:function(categoryItem){
var category = new categoryresource(categoryItem);
category.$save(function(respdata){
categoryinfo.push(respdata);
},function(respdata){
});
},
deletecategoryItem:function(idx,id){
var category=new categoryresource({"id":id});
category.$delete(function(){
categoryinfo.splice(idx,1);
},function(){
})
},
updatecategoryItem:function(categoryItem,idx){
var category=new categoryresource(categoryItem);
category.$update({"id":categoryItem._id},function(data){
categoryinfo[idx]=data;
},function(){
})
}
}
})
the above functionality is working well. Now i want to send the token in the headers. How can i do that.
I have tried to do it by the following way
var categoryresource=$resource(RES_URL+"category/:id",{"id":"#id"},{update:{method:"PUT"},headers:{"token":"#token}});
but not getting how to send the token for CRUD operation.
Is procedure is correct, if so how can i send tokens.
Else let me know the way.
Instead of above method i tried the following way as
$resource(RES_URL+"category",{},{query:{method:"get",isArray:true,headers:{"token":token}}}).query({},function(res){});
this is working but the procedure for the first procedure.
Please after answering mark it as duplicate or down vote
dont say ( / { such things are missing.
The best solution as to me is to use interceptor. Here is a way to send token in headers, I've used in one of my projects.
angular
.module('app.core')
.config(config);
config.$inject = ['$httpProvider'];
function config($httpProvider) {
$httpProvider.interceptors.push(interceptor);
}
interceptor.$inject = ['$q', '$injector', 'AuthModel'];
function interceptor($q, $injector, AuthModel) {
return {
request: function (config) {
config.headers.Authorization = AuthModel.token;
return config;
},
responseError: function (rejection) {
}
};
}
Added a jsfiddle to demonstrate
https://jsfiddle.net/Sergey_Mell/c47js1zc/
Just click the Send button and check the request headers in developer tools

AngularJS, $http and interceptor - every request received twice in nodejs

I'm trying to use AngularJS' $http interceptor for adding a token on every API call.
This is my code (http://pastebin.com/x1EMGcVE):
.factory('authInterceptor', function(authorization, API) {
return {
request: function(config) {
var token = authorization.getToken();
if (config.url.indexOf(API) === 0 && token) {
config.headers.Authorization = token;
}
return config;
}
}
})
On my nodes backend I'm receiving the call with express:
app.route('/API-CALL')
.get(function(req, res) {
...
My problem is that every API request is received twice in nodejs, one request without the token added in Authorization and one with the token added.
Is this an issue with the interceptor? Outputting the config from the interceptor seems to show no issues and only the correct number of requests with the token added.
If I remove the:
$httpProvider.interceptors.push('authInterceptor');
calls are only made once, but of course without the token added.

AngularJS $resource interceptors

How do I add interceptors to a $resource call?
Let's say I have a resource factory called Users, like so;
app.factory('Users', ['$resource', 'resourceInterceptor',
function ($resource, resourceInterceptor) {
return $resource(
'users/:user_id',
{
user_id: '#id'
},
{
query: {
method: 'GET', // Not changing the default method, just adding an interceptor
interceptor: resourceInterceptor // Is there any better way to do this.. like globally?
},
save: {
method: 'POST', // Same here
interceptor: resourceInterceptor // Again...
},
..., // And so on
}
);
}]);
and my resourceInterceptor service looks like;
app.factory('resourceInterceptor', ['$rootScope',
function ($rootScope) {
return {
request: function () {
// This function isn't executed at all?
$rootScope.loading = true;
},
response: function () {
$rootScope.loading = false;
},
responseError: function () {
$rootScope.loading = false;
}
};
}]);
First of all, the request intercept function is never executed, why not?
Secondly, having to hardcode the interceptor to existing $resource methods is very tedious , is there a way to easier assign interceptors to specific $resource calls, or maybe even assign an interceptor to all $resource calls?
To use an interceptor in a resource you should:
1 - Make an httpInterceptor with you request, response, responseError:
app.factory('myInterceptor', function () {
//Code
//return { request:...,
});
2 - Config this Interceptor in your app:
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
}]);
Right now as you have config your httpProvider to has an interceptor wherever you inject $http you will use this provider so... you will excute your request, response and responseError funciton.
3 - Using it in a resource.
As $resource use $http and you have config a httpProvider globaly you will call your interceptors' func when you use your resource.
Second question:
You can not set an interceptor to a concrete $http object, they (interceptors) are set globally.
(Even if you set the interceptor before your module definition and then you remove it, you can not know the execution order)
What you can do if you do not want to override the interceptor property in each $resource action (as you write in your question) you can improve your interceptor.
app.factory('userLoadingInterceptor', function () {
//Code
return {
request: function(){
//Check if your are working with a url related with users
// and if so do things...
}
});
From the docs:
The interceptor object has two optional methods - response and responseError
I don't know what you want to achieve but generic HTTP interceptors might be an alternative.
A generic HTTP Interceptor should do what you want. You can find a sample here: Handle HTTP 302 response from proxy in angularjs.

Resources