Firstly, apology if this question does not make sense. I am developing code for session management for my mean stack app. From last few days, i found lots of way to implement it which are using either cookies, sessions or http - headers. I tried to implement, but did not get success.
I successfully link the interceptor with my code. Code is listening to each req/res.
Here is some code:
app.js
angular.module('MyApp', [
'ngMaterial',
'ngMdIcons',
'ui.router',
'e3-core-ui.services',
'e3-core-ui.utils'
])
.config(['$stateProvider', '$routeProvider','$httpProvider','$mdThemingProvider', '$mdIconProvider', function($stateProvider, $routeProvider, $httpProvider, $mdThemingProvider, $mdIconProvider) {
$httpProvider.interceptors.push('YourHttpInterceptor');
...
Interceptor-code
angular.module('MyApp')
.factory('YourHttpInterceptor', ['$q',
function($q, ) {
return {
'request': function(config) {
console.log("req");
return config;
},
// Optional method
'response': function(response) {
// do something on response success
console.log("inside the response ");
return response;
},
// optional method
'responseError': function(rejection) {
// Here you can do something in response error, like handle errors, present error messages etc.
console.log("inside the response error ");
return $q.reject(rejection);
}
};
}]);
I will be very thankful for your time and help.
In Meanjs you have the authentication controller
mean/modules/users/client/controllers/authentication.client.controller.js
but if you want to use the authentication service in your interceptor, just be aware that injecting a dependency isn't that easy as doing it in a controller.
you'll need to use $injector
var AuthService = $injector.get('Auth');
then you'll have to be sure your user is authenticated and check that in your request function, something like
if (!Authentication.user) {
$location.path('/'); // or a login page
}
Related
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);
}
}
});
I want to make it so that users are automatically logged out by having the client terminate the session (as opposed to letting the session die on its own). I pushed an interceptor onto the $httpProvider which allows me to set and reset the timeout timer, but the problem is that I can't figure out how to call the logout function which requires $http. This always produces a circular dependency. Is there any way to do this?
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(
function() {
return {
response: function(response) { $http({ ... }); }
})}
If I make $http a dependency, I get a circular dependency, but without the $http dependency, the call to $http obviously doesn't work.
You should be careful using $http inside an interceptor as it has the potential to cause an infinite loop. Consider refactoring so $http isn't required
That said you can try injecting the $injector instead. Then where you want to make the $http request just use $injector.get('$http')
app.config(['$httpProvider, $injector', function($httpProvider, $injector) {
$httpProvider.interceptors.push(
function() {
return {
response: function(response) { $injector.get('$http') }
})}
You need to inject $http dependancy inside theinceptor.push function, you could also inject other dependencies from there.
Code
app.config(['$httpProvider',
function($httpProvider) {
$httpProvider.interceptors.push(
function($http) { //<--here you could make dependency available.
return {
response: function(response) {
$http({...});
}
})
}])
I used a crossover of the previous answers (use $injector, but in the push() ) to get it working as expected:
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(function($q, $injector) {
...
//now get $http like this and use it as needed:
$injector.get('$http')
I am trying to hanlde my 404 errors properly in my Angular app.
The redirection works fine here but somehow I cannot manage to get the $state url here. The window.location.href gets printed jsut fine bu I get nothing for $injector.get('$state').current.url.
.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push([
'$q',
'$rootScope',
'$injector',
function($q, $rootScope, $injector) {
return {
'request': function(config) {
return config;
},
'responseError': function(response) {
console.log(window.location.href);
console.log($injector.get('$state').current.url);
//404 error handling
if (response.status === 404)
$injector.get('$state').go('404')
//500 error handling
if (response.status === 500)
$injector.get('$state').go('500')
return response;
}
};
}]);
}])
I cannot figure out where the problem comes from. Does anyone has an idea?
Many thanks
What are you really trying to catch as an error : ?
a route change which failed (due to a failed ui-router resolve) ?
any http request ? (which is not linked to ui-router)
If it's a routeChange error, you should take a look at the ui-router $stateChangeError event which will get fired when any resolve fails
Example :
$rootScope.$on("$stateChangeError", function (event, to, toParams, from, fromParams, reason) {
// error handling code
// you can use params to retrieve from/to route
});
If you want to catch any http request like your code snippet, you're code can work only if ui-router had the time to iniatialized itself .. and you can't be sure of that if you don't use ui-router events.
I have simple api and a authorization point
when i request to api i get a 401 if the token is invalid (token loses validity past five minutes).
i know i can intercept 401 for example with
app.factory("HttpErrorInterceptorModule", ["$q", "$rootScope", "$location",
function($q, $rootScope, $location) {
var success = function(response) {
// pass through
return response;
},
error = function(response) {
if(response.status === 401) {
// dostuff
}
return $q.reject(response);
};
return function(httpPromise) {
return httpPromise.then(success, error);
};
}
]).config(["$httpProvider",
function($httpProvider) {
$httpProvider.responseInterceptors.push("HttpErrorInterceptorModule");
}
]);
but i want capture and queue the request and show a login form if is success then change the token (it's a header) and execute request again
You can use $httpInterceptor in slightly another way. If you want to redirect user after login to page where user actually failed you need to cache failed request in some service and then redirect user somewhere after login (I beleive in logic connected to your login).
But you may need to have some test endpoint to protect your controllers from unrestricted access, you might want to use resolve https://thinkster.io/egghead/resolve/
So in this case you will receive error connected with restricted access to proctedted endpoint but not to your page.
To solve this problem I used marker param (or header) to find out where I should redirect user after login.
Here is example of your httpInterceptor.
angular.factory('httpInterceptor', function ($q, $rootScope, $log, someService) {
return {
request: function (config) {
return config || $q.when(config)
},
response: function (response) {
return response || $q.when(response);
},
responseError: function (response) {
if (response.status === 401) {
//here I preserve login page
someService
.setRestrictedPageBeforeLogin(
extractPreservedInfoAboutPage(response)
)
$rootScope.$broadcast('error')
}
return $q.reject(response);
}
};
})
.config(function ($httpProvider) {
$httpProvider.interceptors.push('httpInterceptor');
});
angular-http-auth module provides a service that intercepts requests and queques them to re-send them later once a user logs in.
This service fires also these events below, so you could listen to them and decide what to show on screen
event:auth-loginRequired
event:auth-loginCancelled
event:aut-loginConfirmed
Look at the code. It has just a few lines of code
https://github.com/witoldsz/angular-http-auth
This is a question about template loading customization in $templateCache.
Goal is handling transport layer, exactly:
Ability to modify template url.
Ability to handle transport errors and timeouts.
How can be $templateCache loader modified with custom transport wrapper?
Prefferably at global application level, i.e. directives should't know about this modification.
You could use a $http interceptor for this. You could use the request interceptor to change the URL, and the responseError interceptor to deal with errors. A simple implementation is below, that you would have to change to exactly how you want the URL to be modified and how errors are handled.
app.factory('TemplateInterceptor', function($injector, $window, $q, $timeout) {
return {
'request': function(config) {
// Test if is a template
var isTemplate = config.url.match(new $window.RegExp("^/?templates/"));
// Save in config, so responseError interceptor knows
config.TemplateInterceptor = config.TemplateInterceptor || {};
config.TemplateInterceptor.isTemplate = isTemplate;
if (isTemplate) {
config.url = '/modified-url' + config.url;
}
return config;
},
'responseError': function(rejection) {
// Avoid circular dependency issues
var $http = $injector.get('$http');
// If a template, then auto-retry after 1 second
return !rejection.config.TemplateInterceptor.isTemplate
? $q.reject(rejection)
: $timeout(angular.noop, 1000).then(function() {
return $http(rejection.config);
});
}
}
});
Registered as:
app.config(function($httpProvider) {
$httpProvider.interceptors.push('TemplateInterceptor');
});