In my angular app the global $http headers are defined for every request, like this:
function useBasicAuth(username, hash) {
var encoded = btoa(username + ':' + hash);
$http.defaults.headers.common.Authorization = 'Basic ' + encoded;
}
How to disable sending this information, when for example the user logs out, and the authentication is no longer required?
What I found as a working solution was to redeclare the $http.defaults.headers.common Object so it won't contain the headers.
Example:
function useBasicAuth(username, hash) {
var encoded = btoa(username + ':' + hash);
$http.defaults.headers.common.Authorization = 'Basic ' + encoded;
}
This, however won't delete the cached credentials from the browser. To overcome this, I've made a simple - and not asynch call to generate a bad request on purpose.
This is the function for this in my accountServices factory:
function checkAuth(username, hash) {
var encoded = btoa(username + ':' + hash);
var result = false;
$.ajax({
type: "POST",
beforeSend: function (request) {
request.setRequestHeader("Authorization", 'Basic ' + encoded);
},
url: "user/current",
statusCode: {
401: function () {
result = false;
},
200: function (response) {
result = response;
}
},
async: false
});
return result;
}
To log the user out, I call this function:
function useBasicWithoutAuth() {
accountServices.checkAuth('logout','logout');
$http.defaults.headers.common = {Accept: "application/json, text/plain, */*"};
}
So what this does, is it first sends a request to a protected URL, with a fake and non-existant user, so it's basically the same, as if the prompt would appear to you, and you'd click cancel.
After this has been done, there's no cached data in the browser, we can simply remove the headers from Angular, so it won't send any Authorization information, where it's not needed.
Related
I am not able to add bearer token in $resource service header for token based authentication. I used following code
Factory
return $resource(appSettings.serverPath + "/api/product/:id", null, {
'get': {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + currentUser.getProfile().token
}
}
Also i tried below code as per some research in app.run
$http.defaults.headers.common.Authorization = 'Bearer ' + currentUser.getProfile().token;
But both options do not add this header in my request and i can see request in chrome without this headers and hence got unauthorized response. I am using angular 1.5.9. Any clue on this.
Assuming currentUser is a service and currentUser.getProfile() is a synchronous API:
app.factory("myRestAPI", function(currentUser) {
return $resource(appSettings.serverPath + "/api/product/:id", null, {
'get': {
method: 'GET',
headers: {
//REPLACE expression
//'Authorization': 'Bearer ' + currentUser.getProfile().token
//WITH a function
'Authorization':
function() {
return 'Bearer ' + currentUser.getProfile().token;
}
}
}
);
});
By using a function instead of an expression, the Authorization header will be computed on every call.
From the Docs:1
headers – {Object} – Map of strings or functions which return strings representing HTTP headers to send to the server. If the return value of a function is null, the header will not be sent. Functions accept a config object as an argument.
I'm using basic HTTP auth (without SSL for testing).
The login works fine, we send an $http request with the authorization header and if the login is correct, it works.
For logout, I'm setting the Authorization header to a bad value and sending an $http request to "trick" the server. The server seems to ignore the new changed auth header. I verified with developer tools in FF that the header value is all ones, but the request is still successful.
How do I "logout"? The logout function sends a bad Authorization header, and the browser sends it according to firebug. What's going on? This is a Java EE 7 app with Wildfly 9 and Shiro, if that makes a difference.
Here is the code:
var DataFactory = function($http, $rootScope, $base64, $cookieStore) {
var _debug = false;
function _d(message) {
if (!_debug) {
return;
}
console.log(message);
}
function setDebug(flag) {
_debug = flag;
}
function doLogout() {
_d("Logging out");
$rootScope.globals = {};
$cookieStore.remove('globals');
$http.defaults.headers.common['Authorization'] = 'Basic 111111111111111111';
$http.get(
'http://localhost:8080/myapp/rest/v1/svc')
.then(function(data) {
alert("Logout: " + JSON.stringify(data.data));
}, function(data) {
alert("Logout Error: " + JSON.stringify(data))
});
}
function doLogin(username, password) {
var token = $base64.encode(username + ":" + password);
_d("Logging " + username + " in with token " + token);
$http.defaults.headers.common['Authorization'] = 'Basic ' + token; // jshint
// ignore:line
$rootScope.globals = {
token : token,
username : username
};
$cookieStore.put("globals", $rootScope.globals);
_d("Login finished, globals are: " + JSON.stringify($rootScope.globals));
$http.get(
'http://localhost:8080/myapp/rest/v1/svc')
.then(function(data) {
alert(JSON.stringify(data.data));
}, function(data) {
alert("Error: " + JSON.stringify(data))
});
}
;
return {
setDebug : setDebug,
doLogin : doLogin,
doLogout : doLogout
};
}
Sending your own authorization string within a XHR request will not magically delete the information cached in the browser. Basic authentication has no concept of logging out. The only way to "logout" with basic authentication is to make the credentials invalid at the server, i.e. change username and/or password so that the stored credentials do not work any longer.
I'm trying to wrangle the auth-0 angular plugin for JWTs and I'm stuck in a spot where I've setup the jwtInterceptor to push a JWT token into the headers of every single request made.
Here is my code:
// Send JWT with every request
jwtInterceptorProvider.tokenGetter = ['config', function(config) {
var user = JSON.parse(localStorage.getItem('ngStorage-user'));
var token = user.token;
return token;
}];
$httpProvider.interceptors.push('jwtInterceptor');
The problem is that there are a few instances where I need to make a call where I DON'T send the token in the headers of the request, such as getting the initial JWT token on registration. As of right now, with my code, if there is no JWT set, it results in an error.
One of other thought I had was to just edit each call to send the token in the headers manually, however I can't seem to get the request to work with ngResource:
function getCourseCatalog(token) {
return Registrar.checkToken($localStorage.user.token).then(function(data) {
return $resource($rootScope.APIBaseURL + 'catalog',{
query: {
method: 'GET',
isArray: true,
headers: {
Authorization: 'Bearer ' + $localStorage.user.token
}
}
});
});
}
^ With this function, the call never gets made and I'm pretty sure this is exactly how you're supposed to setup the $resource call. Is there something I'm missing? This particular call is hitting an endpoint that gets an array of objects.
It turns out that the function was missing a parameter, but additionally, I needed to still run the query() function on $resource in order to actually make the call. The new function looks like this:
function getCourseCatalog(token) {
return Registrar.checkToken($localStorage.user.token).then(function(data) {
return $resource($rootScope.APIBaseURL + 'catalog',{},{
query: {
method: 'GET',
isArray: true,
headers: {
Authorization: 'Bearer ' + $localStorage.user.token
}
}
}).query();
});
}
Hi am using basic authentication for webservie integration.
$http.defaults.headers.common['Authorization'] = 'Basic ' + Base64.encode(Username + ':' + password);
$http({method: 'GET', url: 'http:url.com'}).
success(function(data) {
if(data=='' || data==null || data=='undefined'){
var alertPopup = $ionicPopup.alert({
title: 'Info!',
template: 'Invalid Password, or no user found with this Email Address'
});
alertPopup.then(function(res) {
console.log('Invalid Password, or no user found with this Email Address ');
});
}
This code is working fine for me .but my problem is if one user is logedin using username and password.then logged out after that another user try to logged in with different username and password will get the previous user loged in. how to clear the header authentication data?
You could probably redefine the header with
$http.defaults.headers.common['Authorization'] = 'Basic ' + Base64.encode(newUsername + ':' + newPassword)
It seems that,
You have not replaced the Authorization header when
the user logged out
logged in as a different user
Login - call this every time a user logs in
function setCredentials(username, password) {
$http.defaults.headers.common['Authorization'] = 'Basic ' + Base64.encode(username + ':' + password);
};
Logout - call this when a user logs out
function clearCredentials() {
$http.defaults.headers.common.Authorization = 'Basic ';
};
The above snippets simplified from this tutorial - AngularJS Basic HTTP Authentication Example. i recommend reading it
In addition,
Please note that using basic http authentication is insecure because the password passed on each request with no encryption!
As an alternative, you can change basic http authentication to a server side authentication using sessions (comment the server your'e using and i'll link you to example)
If you still decides to keep the basic http authentication, at least use HTTPS !
I've found this solution working:
When initiating a logout, first try making a bad request with a fake user to throw away the currently cached credentials.
I have this function doing the requests (it's using jquery's $.ajax with disabled asynch calls):
function authenticateUser(username, hash) {
var result = false;
var encoded = btoa(username + ':' + hash);
$.ajax({
type: "POST",
beforeSend: function (request) {
request.setRequestHeader("Authorization", 'Basic ' + encoded);
},
url: "user/current",
statusCode: {
401: function () {
result = false;
},
200: function (response) {
result = response;
}
},
async: false
});
return result;
}
So when I try to log a user out, this happens:
//This will send a request with a non-existant user.
//The purpose is to overwrite the cached data with something else
accountServices.authenticateUser('logout','logout');
//Since setting headers.common.Authorization = '' will still send some
//kind of auth data, I've redefined the headers.common object to get
//rid of the Authorization property
$http.defaults.headers.common = {Accept: "application/json, text/plain, */*"};
I'm making a GET request to retrieve posts, but when I load the page, it makes the first request with the correct page query in the request URL but then immediately makes another request with page set to 1. Here's the console output when I make a request for page=3:
"page: 3"
bolt.js:54 Object {method: "GET", url: "http://localhost/api/v1/content/news?order=datepublish%20DESC&limit=10&page=3", headers: Object}
bolt.js:54 Object {method: "GET", url: "http://localhost/api/v1/content/news?order=datepublish%20DESC&limit=10&page=1", headers: Object}
bolt.js:58 "success function called."
posts.controller.js:35 Object {data: Object, status: 200, headers: function, config: Object, statusText: "OK"}
bolt.js:58 "success function called."
So you can see it's clearly making two GET requests, but only returning one set of data (the latter, with page=1.
In my posts.controller.js, I have:
activate();
function activate() {
$scope.isLoading = 1;
$scope.previousLink = 0;
return getPosts($stateParams.page).then(function(data) {
$scope.isLoading = 0;
$rootScope.pageLoading = 0;
});
}
function getPosts(page) {
console.log("page: " + page);
var contenttype = 'news';
var order = 'datepublish%20DESC';
var limit = 10;
return Bolt.getRecords(contenttype, order, limit, page)
.then(function(data){
// Below is line 35
console.log(data);
$scope.posts = data.data.data;
});
}
And the Bolt service (bolt.js):
function getRecords(contenttype, order, limit, page) {
var request = {
method: 'GET',
url: API_BASE_URL + 'content/' + contenttype +
'?order=' + order +
'&limit=' + limit +
'&page=' + page,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
};
// Below is line 54
console.log(request);
return $http(request)
.success(function(data){
// Below is line 58
console.log("success function called.");
return data;
})
.error(function(error){
return error;
});
}
What am I doing wrong here?
Sometimes there are asynchronous function calls made within a watch that are executed via the digest cycle.
Check if you have used your getRecords or getPosts function anywhere else in your code. Perhaps is related to watching some variable related to your pages parameter.
Good luck.