I implemented jwt stateless in backend , so except login and signup all other method has to intercept in angularjs and sending auth token to server in request header .But token is not sending mean not seeing in reqest header in console(developer tools).
This is my interceptor.js :
/**
*
*/
/* Interceptor declaration */
rootApp.factory('authInterceptor', function ($rootScope, $q, $sessionStorage, $location,$window) {
return {
request: function (config) {
//config.headers['Content-Type'] = 'application/json';
config.headers = config.headers || {};
if ($window.sessionStorage.token) {
config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
//config.headers['x-auth-token'] ='Bearer ' + $window.sessionStorage.token;
}
return config;
},
response: function (response) {
if(response.status === 200){
if(response.data && response.data.success === false){
if($rootScope.authFailureReasons.indexOf(response.data.reason) !== -1){
$location.path('/login');
}
}
}
if (response.status === 401) {
$location.path('/');
}
return response || $q.when(response);
},
'responseError': function (rejection) {
return $q.reject(rejection);
}
};
});
rootApp.config(['$httpProvider', function ($httpProvider) {
// $httpProvider.interceptors.push('headerInterceptor');
$httpProvider.interceptors.push('authInterceptor');
}]);
And service.js file is:
rootApp.service('adminService', function ($rootScope, $http, $q,$window) {
return {
inviteUser: function (user) {
var deferred = $q.defer();
$http({
method: 'POST',
url:$rootScope.baseUrl+'api/v1/admin/user/add',
data:user
}).success(function (response, status, headers, config) {
deferred.resolve(response);
}).error(function () {
// Something went wrong.
deferred.reject({'success': false, 'msg': 'Oops! Something went wrong. Please try again later.'});
});
return deferred.promise;
}
};
});
In server side X-AUTH-TOKEN is allowed in headers too.Where i am going wrong
Please help.
hey I have recently made my first token authentication in my Ionic app .. yeah it is an easy step but implementation may take some time if you are not a language PRO..
you can try this.
https://devdactic.com/user-auth-angularjs-ionic/
this is one of the finest and tested tutorial on the web for token based AUTH..
Maybe that may help you to find the error !
Related
I have a login function that works. But, when the user enters an invalid credential, i of course want to display this. But I cant seem to catch the error.
This is my code that works;
function userAccount($resource) {
return {
login: $resource("/Token", null,
{
'loginUser': {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
transformRequest: function (data, headersGetter) {
var str = [];
for (var d in data)
str.push(encodeURIComponent(d) + "=" +
encodeURIComponent(data[d]));
return str.join("&");
}
}
})
}
}
vm.login = function () {
vm.userData.grant_type = "password";
vm.userData.userName = vm.userData.email;
userAccount.login.loginUser(vm.userData,
function (data) {
//login
},
function (response) {
//run this if error (code 400 or similar error)
});
}
});
What do I need to change, to make sure the last bit is run, when to request fails?
EDIT
I found this in the code, and it looks like that is intercepting the error - but how do i get it to, work with my login function, so i can get an error displayed to the user?
.factory('authInterceptor', [
"$q", "$window", "$location", "currentUser", function ($q, $window, $location, currentUser) {
return {
request: function (config) {
if (currentUser.getProfile().token) {
config.headers = config.headers || {};
config.headers.Authorization = 'Bearer ' + currentUser.getProfile().token;
}
return config;
},
response: function(response) {
return response || $q.when(response);
},
responseError: function(rejection) {
// error handler
}
};
}
])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
}])
When i remove the last 3 lines, and thereby disabling the interceptor, it works, and the error is caught and showed to the user.
So how to make these work together? :)
You need to return the rejection or error object back to the login user requset object like this
.factory('authInterceptor', [
"$q", "$window", "$location", "currentUser", function ($q, $window, $location, currentUser) {
return {
request: function (config) {
if (currentUser.getProfile().token) {
config.headers = config.headers || {};
config.headers.Authorization = 'Bearer ' + currentUser.getProfile().token;
}
return config;
},
response: function(response) {
return response || $q.when(response);
},
responseError: function(rejection) {
if(ableToREsolve()){
return customRejection
}
return $q.reject(rejection);
}
};
}
])
This in turn will be caught in :
responseError: function(rejection) {
// Show in modal or alert
}
For better understanding I suggest to read on interceptors. Interceptors are of four types:
Request
2.Request Error
3.Response
4.Response Error
In simple words, Interceptors get called before actual
request is passed on to server
response is delivered to client
So in your case error needs to be returned from interceptor in able to be caught by your request object error function.
request
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 an $http service that make an API call and I have a transformResponse and error interceptor both attached to every call. In case of errors I can see that transform response gets called first, then followed by an interceptor. I do not want the transformation method to be called for error responses, I want it to skip right to the interceptor. How can I achieve that?
I know that I can put if (response.status != 200) into every transformation method, but I have a lot of these methods and I do not want to do that in each of them.
You probably need to go for Interceptors to play with request response in general.
myApp.factory('authInterceptor', function ($rootScope, $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) {
if (response.status === 401) {
// handle the case where the user is not authenticated
}
return response || $q.when(response);
}
};
});
myApp.config(function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
});
Perhaps it will also be useful
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.transformResponse.unshift(
function (data, headers) {
/* some code*/
return data;
});
}])
I have this route in my API app:
router.get('/users', auth, function(req, res) {
User.find({}, function(err, users) {
res.json(users);
});
});
In postman I do the api call like this:
URL + users?token=token
But this returns:
Format is Authorization: Bearer [token]
How can I properly do the api call with a token in postman?
The error you got indicates the right format you need to use for the header:
Format is Authorization: Bearer [token]
You can try this in Postman
You need to add the header to the http
module.run(function($http) {
$http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'
});
after doing this your requests will be sent with this header
take a look at https://docs.angularjs.org/api/ng/service/$http
You can create a http interceptor service like this
app.factory('authInterceptor', function($rootScope, $q, $cookieStore, $location) {
return {
// Add authorization token to headers
request: function(config) {
config.headers = config.headers || {};
if ($cookieStore.get('token')) {
config.headers.Authorization = 'Bearer ' + $cookieStore.get('token');
}
return config;
},
// Intercept 401s and redirect you to login
responseError: function(response) {
if (response.status === 401) {
$location.path('/login');
// remove any stale tokens
$cookieStore.remove('token');
return $q.reject(response);
} else {
return $q.reject(response);
}
}
};
})
And then add the service into the interceptors like this
app.config(function($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
})
Why is the success callback fired here when the response is 500?
$scope.submit = function() {
var user = $scope.user;
// provide username and password to obtain a token which will be used for api calls
$http.post('/authenticate', user).
success(function(data, status, headers, config) {
$window.sessionStorage.token = data.token;
$location.path('/');
}).
error(function(data, status, headers, config) {
$scope.errors = data.errors;
$scope.message = 'Invalid JSON format, see guidelines for correct format';
$scope.uploadError = true;
console.log('ERROR TRUE');
});
};
And the interceptor:
angular.module('uploadApp')
.factory('authInterceptor',
function ($rootScope, $q, $window, $location) {
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) {
$location.path('/login');
}
return response || $q.when(response);
}
};
});
The way angular $q promises work is that errors need to be unhandled to continue down the error path - otherwise it assumes that you have corrected the issue or handled the error. So the easiest way is to throw the response from your error path, until you get to the point you actually want to handle it.
angular.module('uploadApp')
.factory('authInterceptor',
function ($rootScope, $q, $window, $location) {
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) {
$location.path('/login');
}
// instead of returning, you should throw,
// and when you throw you don't need to wrap, as it will
// handle it for you.
//return response || $q.when(response);
throw response;
}
};
});
$q will ensure that the thrown object is wrapped in the promise call-chain. Note that whenever you return in a $q promise it will assume you have handled any issues, unless you throw instead of return. This allows you to have errors in resolvers further down the call-chain that can then be treated as an error.
If throwing isn't your style, you can defer a new promise and return that, then reject it - but that is way less efficient than using the current call-chain.