I have an angularjs app, in which I have an interceptor that adds the authorization token to the header of each request.
However, somewhere in the application I need to use and external API where the interceptor ruins it, because it adds this authorization header which is not acceptable by this external API provider. How can I make angularjs HTTP skip the interceptor, only on this one specific case?
The interceptor code is below:
app.factory('authInterceptorService', ['$q', '$injector', '$location', 'localStorageService', function ($q, $injector, $location, localStorageService) {
var authInterceptorServiceFactory = {};
var $http;
var _request = function (config) {
config.headers = config.headers || {};
var authData = localStorageService.get('authorizationData');
if (authData) {
//console.log("token: " + authData.token.substring(0, 10));
//console.log("user: " + authData.userName);
config.headers.Authorization = 'Bearer ' + authData.token;
}
return config;
}
var _responseError = function (rejection) {
var deferred = $q.defer();
if (rejection.status === 401) {
var authService = $injector.get('authService');
authService.refreshToken().then(function (response) {
_retryHttpRequest(rejection.config, deferred);
}, function () {
authService.logOut();
$location.path('/login');
deferred.reject(rejection);
});
} else {
deferred.reject(rejection);
}
return deferred.promise;
}
var _retryHttpRequest = function (config, deferred) {
console.log('retrying');
$http = $http || $injector.get('$http');
$http(config).then(function (response) {
deferred.resolve(response);
//console.log("success:" +response);
}, function (response) {
deferred.reject(response);
//console.log("error:" + response);
});
}
authInterceptorServiceFactory.request = _request;
authInterceptorServiceFactory.responseError = _responseError;
return authInterceptorServiceFactory;
}]);
Easy
$http.get("url" , {noAuth : true}).then(success(),error());
In the Interceptor
var _request = function (config) {
config.headers = config.headers || {};
var authData = localStorageService.get('authorizationData');
if (authData && !config.noAuth) {
//console.log("token: " + authData.token.substring(0, 10));
//console.log("user: " + authData.userName);
config.headers.Authorization = 'Bearer ' + authData.token;
}
return config;
}
Simple. Change this line
if (authData) {
to
if (authData && !config.headers.hasOwnProperty('Authorization')) {
And for any request where you do not want the header applied, use
$http({
headers { Authorization: null },
// and the rest
})
Write like this :-
var _request = function (config) {
if (config.url.indexOf('yourExternalApiUrl') > -1) {
return config;
} else {
config.headers = config.headers || {};
var authData = localStorageService.get('authorizationData');
if (authData) {
//console.log("token: " + authData.token.substring(0, 10));
//console.log("user: " + authData.userName);
config.headers.Authorization = 'Bearer ' + authData.token;
}
return config;
}
}
For more details you can see : http://www.codemosquitoes.com/2016/06/using-angularjs-interceptors-with-http.html
If you are looking for the auth0 interceptor:
export class InterceptorService implements HttpInterceptor {
constructor(private auth: AuthService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
var allow = ['/assets/i18n/de.json', '/assets/i18n/en.json'];
if (allow.includes(req.url)) {
const noToken = req.clone();
return next.handle(noToken);
}
return this.auth.getTokenSilently$().pipe(
mergeMap(token => {
const tokenReq = req.clone({
setHeaders: { Authorization: `Bearer ${token}` }
});
return next.handle(tokenReq);
}),
catchError(err => throwError(err))
);
}
}
Related
I have problem to override header token with AngularJS becauase already set with AuthInterceptor.
app.factory('authInterceptor', function ($rootScope, $q, $window) {
return {
request: function (config) {
config.headers = config.headers || {};
if (localStorage.getItem("token")!=='') {
config.headers.Authorization = 'Bearer ' + localStorage.getItem("token");
}
return config;
},
};
});
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
});
I would access another third party URL where using another Token,but always failed, because Token back to current Token in localStorage. I have used TransformRequest, but not work too, what is best practice to solve the problem?
You could check that the URL in the intercepted request is a URL that you want to pass an authorization token. For instance, if the URL to your own API always starts with https://api.myapp.com, you could do it like this:
app.factory('authInterceptor', function ($rootScope, $q, $window) {
var urlForAuthorization = 'https://api.myapp.com';
return {
request: function (config) {
config.headers = config.headers || {};
if (config.url.startsWith(urlForAuthorization)
&& localStorage.getItem("token") !== '') {
config.headers.Authorization = 'Bearer ' + localStorage.getItem("token");
}
return config;
}
};
});
I'm having trouble bypassing my auth interceptor:
request: function (config) {
if (config.headers["NoAuth2"] !== null) return config;
config.headers = config.headers || {};
var authData = localStorageService.get('authorizationData');
if (authData) {
config.headers.Authorization = 'Bearer ' + authData.token;
} else {
var authService = $injector.get('authService');
authService.logOut();
$location.path('/login');
}
return config;
}
Ideally, when the headers have NoAuth2 present in it's collection, I'd like to bypass adding the token and just return the config via something like:
$http.post(config.url + "pubrequest", request, { headers : {NoAuth2 : 1}})
From my controller.
However, I can't seem to get it to work despite several SOE examples on it, any ideas?
My Issue
Everything working fine with $post but when I update it to $resource,
I am getting error of unsupported_grant_type.
I tried many solutions from SO, but unable to resolve this issue.
Below is my code.
Controller
$scope.login = function () {
authService.login($scope.loginData).promise.then(function (response) {
if (document.referrer != "" && document.referrer != window.location.href) {
window.location.href = document.referrer;
}
else {
window.location.href = "/Roles/Index"
}
}
};
Service
app.factory('authService', ['$http', '$q', 'localStorageService', '$resource', '$rootScope',
function ($http, $q, localStorageService, $resource, $rootScope) {
var authServiceFactory = {};
var _authentication = {
isAuth: false,
userName: ""
};
var url = function (relativeUrl) {
return $rootScope.apiBaseUrl + '/api/' + relativeUrl;
};
var authResource = $resource(url('account/:id'), null, {
register: {
method: 'POST',
url: url('account/register')
},
login: {
method: 'POST',
url: $rootScope.apiBaseUrl + '/token'
}
},
{
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/x-www-form-urlencoded'
}
});
var _login = function (loginData) {
// var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
loginData.grant_type = "password";
var deferred = $q.defer();
authResource.login($.param(loginData)).$promise
.then(function (response) {
localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
deferred.resolve(response);
});
return deferred;
};
var _fillAuthData = function () {
var authData = localStorageService.get('authorizationData');
if (authData) {
_authentication.isAuth = true;
_authentication.userName = authData.userName;
}
}
authServiceFactory.saveRegistration = _saveRegistration;
authServiceFactory.login = _login;
authServiceFactory.logOut = _logOut;
authServiceFactory.fillAuthData = _fillAuthData;
authServiceFactory.authentication = _authentication;
return authServiceFactory;
}]);
What I found from so many tries?
I found that, My request does not have any headers.
I have written an auth interceptor that adds auth token to the request and handles auth errors if the user is not logged in.
var storeApp = angular.module('storeApp');
storeApp.factory('authInterceptor', function ($q, $window) {
return {
request: function (config) {
config.headers = config.headers || {};
if ($window.sessionStorage.token) {
config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
}
return config;
},
response: function (response) {
return response || $q.when(response);
},
responseError: function (response) {
if (response.status === 401 || response.data.error === 'token_not_provided') {
console.log('auth error');
}
return $q.reject(response);
}
};
});
storeApp.config(function ($httpProvider) {
$httpProvider.defaults.withCredentials = true;
$httpProvider.interceptors.push('authInterceptor');
});
The issue is the auth interceptor is added to every request, regardless the request requires authentication or not. What is the best way to create an auth interceptor that only intercepts when the route requires authentication?
You need the filter out the requests you want in the authInterceptor factory methods
['/whatever/1', '/whatever/2', '/whatever/3'].forEach(function(value){
if (response.config.url.startsWith(value)) {
// do something
}
})
return response;
I have the following code for token based authentication with my backend api in AngularJS:
$httpProvider.interceptors.push(['$q', '$location', '$localStorage', function($q, $location, $localStorage) {
return {
'request': function (config) {
config.headers = config.headers || {};
if ($localStorage.token) {
config.headers.Authorization = 'Bearer ' + $localStorage.token;
}
return config;
},
'responseError': function(response) {
if(response.status === 401 || response.status === 403) {
$location.path('/signin');
}
return $q.reject(response);
}
};
}]);
This sets the "Authorization" header to my token.
How do I have to modify my code to use an URL parameter (named "access_token") instead of an header?
You need to use the argument params – {Object.} of config object:
params – {Object.<string|Object>} – Map of strings or objects which will be turned to ?key1=value1&key2=value2 after the url. If the value is not a string, it will be JSONified.
AngularJS reference guide
$httpProvider.interceptors.push(['$q', '$location', '$localStorage', function($q, $location, $localStorage) {
return {
'request': function (config) {
//config.headers = config.headers || {};
config.params = config.params || {};
if ($localStorage.token) {
config.params.access_token = $localStorage.token;
//config.headers.Authorization = 'Bearer ' + $localStorage.token;
}
return config;
},
'responseError': function(response) {
if(response.status === 401 || response.status === 403) {
$location.path('/signin');
}
return $q.reject(response);
}
};
}]);