I'm trying to make a request to an API service that has a dynamic 'authorization' header.
var domain = "http://www.externalapi.com",
actions = {
'login': {
method: 'POST'
},
'objects': {
method: 'GET',
headers: {
'Authorization': Request.getAuthHeader()
}
}
};
var requests = $resource(domain, {}, actions);
requests.objects();
Request is a service I've written that has a method that builds the auth header based on the api requirements, the has it returns is correct.
When looking at the request to domain, however, I see not 'Authorization' header...
I've also tried passing in a static string, still no header.
So the issue was my versions.
After updating Angular to 1.2.0rc1 I left my ngResource module at 1.0.8.
After updating both to 1.2.0rc1 (I assume 1.1.2 would work as well) I was able to assign headers from the actions object of $resource.
Related
I got a token from backend which I saved it in $sessionStorage and I need to include that along with $http request that I call. I tried include it directly but when I checked it from backend, it's not there.
function _selectGender($sessionStorage, gender) {
return $http({
method: 'POST',
url: config.apiURL + '/auth/gender',
headers: {
'Authorization': $sessionStorage.token
},
data: {
gender: gender
}
}).then(updateCompleted).catch(updateFailed);
}
I also tried with interceptor which it's not working as well.
requestInterceptor.inject = ['$sessionStorage'];
function requestInterceptor($sessionStorage){
return {
'request': function(config){
if ($sessionStorage.token) config.headers['authorization'] = $sessionStorage.token;
return config;
}
}
}
Shoot me some idea how to tackle this. :D
Edit#1: It's likely possible to be preflight error
It's actually because of OPTIONS headers, seem like $http will send a pre-request before browser send an actual request to backend. You need to handle that from the backend. Thanks #Nitish Kumar's comment.
Read more about cors
How to handle OPTIONS
Long story short. I am really not an AngularJS guru. Our site upgraded from 1.3 to 1.5. This one thing is breaking.
We used to inject an HTTP header via transformRequest in a factory named 'api':
.factory('api', function($resource) {
function add_auth_header(data, headersGetter) {
var headers = headersGetter();
headers['Authorization'] = ('Basic ' + btoa(data.username +
':' + data.password));
}
// defining the endpoints.
return {
auth: $resource('/api/v1/auth/', {}, {
login: {method: 'POST', transformRequest: add_auth_header},
logout: {method: 'DELETE'},
}),
Later on in the same file, this is called like so:
.service('auth', function($cookies, $rootScope, api) {
this.user = null;
this.login = function(credentials) {
var log = api.auth.login(credentials);
log.$promise.then(function(data){
// on good username and password
this.user = data;
});
As you can see, it calls api.auth.login with the credentials. I have verified that the transform request is being called, the headers are being fetched properly by headersGetter(), and that hanging the headers[] object no longer changes it like it used to in 1.3. Fiddler verifies that the request no longer has an Authorization header in it like it did in 1.3, and the Django server that gets the request also agrees.
I've read in a few places that the transformRequest functionality 'broke' in 1.4, but those posts have always been in the context of making an $http request, not providing an api service through a factory, and haven't made much sense to an AngularJS newb like me. I have no idea where I would start changing how Authorization is injected.
Can anyone point me the right way?
If anyone else is still facing this, the change was under breaking changes in the changelog for 1.4.
I feel the fix speaks for itself. Note that the function add_auth_header is not invoked but rather is passed.
.factory('api', function($resource) {
function add_auth_header(data) {
// as per HTTP authentication spec [1], credentials must be
// encoded in base64. Lets use window.btoa [2]
return 'Basic ' + btoa(data.data.username + ':' + data.data.password);
}
// defining the endpoints.
return {
auth: $resource('/api/v1/auth/', {}, {
login: {method: 'POST', headers: { 'Authorization': add_auth_header }},
logout: {method: 'DELETE'},
}),
I am using http-auth-interceptor for authentication. In http-auth-interceptor, I use the following way to login:
var data = 'username=' + encodeURIComponent(user.userId) + '&password=' + encodeURIComponent(user.password);
$http.post('api/authenticate', data, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
ignoreAuthModule: 'ignoreAuthModule'
})
ignoreAuthModule is used to tell ignoreAuthModule that this login method will be ignored by the auth interceptor.
Now, I have some request with $resource, like:
.factory('SomeDataService', function ($resource) {
return $resource('api/some/data', {}, {
'get': { method: 'GET'}
});
})
I want SomeDataService.get() is also ignored by the auth interceptors, because I need to control the 401 error by myself.
So, my question is, is there any way for ngResource that I can set config like that in $http.
[update based on comment]
I have listened the login-required event:
$rootScope.$on('event:auth-loginRequired', function (rejection) {
$log.log(rejection);
// I need to get the request url and for some specific url, need to do something.
$rootScope.loginPopup();
});
But the 'rejection' parameter has no context data of request I need. I need to get the request url and check, for some specified url, I need to do something.
After checking the document of ngResource, I got the solution as below:
.factory('SomeDataService', function ($resource) {
return $resource('api/some/data', {}, {
'get': { method: 'GET', ignoreAuthModule: 'ignoreAuthModule'}
});
})
Just add the config item as above. It will be equivalent ad:
$http.post('api/some/data', data, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
ignoreAuthModule: 'ignoreAuthModule'
})
ngResource module is build on top of $http.Hence it is not possible to configure all the stuffs you can do with $http in $resource.I think the below link will be guide you to have a clear understanding on $http and $resource
I have this use case where I pass authToken to every request and this token changes everytime the person logins.
app.factory('Comment', function ($resource, localStorageService, $cacheFactory) {
return $resource('http://localhost:port/comments/:id', {"id":"#id", port:':9000'}, {
query: { method:'GET', isArray: true , headers: {'X-AUTH-TOKEN':'authToken='+localStorageService.get("authToken")}},
save: { method:'POST',headers: {'X-AUTH-TOKEN':'authToken='+localStorageService.get("authToken")}},
update: {method:'PUT' ,headers: {'X-AUTH-TOKEN':'authToken='+localStorageService.get("authToken")}},
delete : {method: 'DELETE',headers: {'X-AUTH-TOKEN':'authToken='+localStorageService.get("authToken")}},
get : { method: 'GET', headers: {'X-AUTH-TOKEN':'authToken='+localStorageService.get("authToken")}}
});
The behaviour I am seeing is that if the authToken changes for some reason the $resource keeps adding the previous authToken while sending the request. I am using the $http directly for login and for any commenting related stuff I am using $resource. Am I missing something?
After login I make sure that my localStorage has the newly created token but the request are using the previous authToken till I refresh the page after which it adds the correct header I know that the $resource uses some kind of caching and tried to remove the $http cache like this after loggin in.
$cacheFactory.get('$http').removeAll();
but didnt't help
It's because token is assigned once when factory code executes. Try this instead:
get : { method: 'GET', headers: {
'X-AUTH-TOKEN': function(){
return 'authToken=' + localStorageService.get("authToken");
}
}}
I'm using angular and angular-resource version 1.1.5 and I'm using a $resource to make a request to a REST service. But it seems like the custom headers is not appended to the request. My definition is as below. Is there anything I did wrong?
myApp.factory('User', function($resource) {
var User = $resource('http://localhost\\:7017/mydomain/users/jack', { }, {
get: {
method: 'GET',
isArray: false,
headers: {'X-Requested-By':'abc'}
}
});
return User;
});
Read this to see how to configure default headers in one place: http://docs.angularjs.org/api/ng.$http
EDIT:
Your header must be included in Access-Control-Allow-Headers header in response to the OPTIONS request, which is sent automatically prior to your GET request.
You can modify the default headers inside the $httpProvider.
the headers are an object and separated intocommon, patch, post and put
so if you want to change the default for all your requests, just do a
$httpProvider.defaults.headers.put['Content-Type'] = 'application/json';
You have to call get method by using its name, i.e User.get(callback)
It seems that custom headers do not get sent when get method is called with User.query(callback)