Send token in header GET-method - angularjs

There is a site and a web api. All the files I receive from the web api server.
I have an ADFS OAUTH2 authorization on the site.
And I need get the images from the web api with the auth token.
So now I do something like this:
<img src='webApiUrl/Photo/Id?token=token_value' alt />
But I have got a bug with token length. It is very long for some clients and I cannot control it.
I can send the authorization header with the xhr request but I do not understand how to set the authorization header for the site which requests the resources from the html via src.
Can you help me to fix it?

Whenever you have an HTTP request to the Web API you can use Angular Interceptors to put your token on the request header. Here I chose to demonstrate the Bearer authentication. Like this:
appName.config(["$httpProvider", ($httpProvider: ng.IHttpProvider) => {
$httpProvider.interceptors.push(<any>["$q", "$location",
($q: ng.IQService, $location: ng.ILocationService) => {
return {
// config is the request data, including all its properties
'request': (config) => {
// Intercepting only the API requests
if (config.url.indexOf(apiServerUrl) >= 0) {
// Getting the token from local storage for example
var token = localStorage.getItem("token");
// Placing the token in the right header
if (token)
config.headers["Authorization"] = "Bearer " + token;
}
return config;
}
}
}
]);
}]);

Maybe this would solve your problem: http://blog.jsgoupil.com/request-image-files-with-angular-2-and-an-bearer-access-token/
It involves registering a pipe so that you can use secure src attributes with your img tags.

Related

How to refresh JWT token using interceptors in angularjs?

I am having my application back-end implementation in Lumen which gives a JWT token every time a user logs in. The front end I am using Angular to save the token in the local storage and also I am adding it to all the headers in the subsequent requests.
To check the expiry of the token and refresh by creating a request I am using https://github.com/auth0/angular-jwt
I am adding the token refresh code in the config of the app but this method is never called when I make any other requests here is the code which I tried.
app.config(function Config($httpProvider, jwtInterceptorProvider) {
jwtInterceptorProvider.tokenGetter = function(jwtHelper, $http,$localStorage) {
if ($localStorage.currentUser) {
var token = $localStorage.currentUser.token;
if (jwtHelper.isTokenExpired(token)) {
return $http({
url: 'http://backend.mywebsite.com/token',
method: 'GET'
}).then(function(response) {
var token = response.token;
$localStorage.currentUser.token = token;
$http.defaults.headers.common.Authorization = 'Bearer ' + $localStorage.currentUser.token;
return token;
});
} else {
return token;
}
}
}
$httpProvider.interceptors.push('jwtInterceptor');
});
I would like to know how to configure this functionality so that whenever the token expires it is automatically refeshed and set in the http headers?
Points you should consider
You shouldn't change the default headers inside the tokenGetter function.
If your token is expired, you can't call the token endpoint.
You have two options, you can use Refresh tokens and make a post request to a delegation endpoint that makes use of the refresh tokens to obtain a new(not-expired) token.
OR
You can update the JWT with a delegation endpoint and request for a new access token just before the token expires. If the token has expired and there is no refresh_token, you can't really do anything.
A refresh token is a special kind of JWT that is used to authenticate a user without them needing to re-authenticate. It carries the information necessary to obtain a new access token.
In other words, whenever an access token is required to access a specific resource, a client may use a refresh token to get a new access token issued by the authentication server. Common use cases like yours include getting new access tokens after old ones have expired, or getting access to a new resource for the first time. Refresh tokens can also expire but are rather long-lived.
A sample code example for using a refresh token to obtain a new token after a token has expired can be found below:
angular.module('app', ['angular-jwt'])
.config(function Config($httpProvider, jwtInterceptorProvider) {
jwtInterceptorProvider.tokenGetter = function(jwtHelper, $http) {
var jwt = localStorage.getItem('JWT');
var refreshToken = localStorage.getItem('refresh_token');
if (jwtHelper.isTokenExpired(jwt)) {
// This is a promise of a JWT id_token
return $http({
url: '/delegation',
// This will not send the JWT for this call
skipAuthorization: true,
method: 'POST',
refresh_token : refreshToken
}).then(function(response) {
localStorage.setItem('JWT', response.data.jwt);
return jwt;
});
} else {
return jwt;
}
}
$httpProvider.interceptors.push('jwtInterceptor');
})
If you want more information about refresh tokens and how they work, you can check out this article.

Custom AngularJS $http interceptor case

recently i am working hard on my website with angularjs on the Front End and Symfony 3 on the backend. I put a security layer on my backend so every request from my FE must need a valid token (using grant_type=client_credentials). I have read a looooot about the best practices about call my API Backend with angular... I normally send the token on every request that i make to the Backend, but i read that i can use the $http interceptor to send always on the header my bearer token.
So, i am a little confused that how start... because for one part:
i want to do calls to my backend to load certain data to be used on my pages to show info (using the grant_type=client_credentials) and,
i will have an user management system too. So this users must to login with user and password (again another call to my backend) but with grant_type=password...
The really big question is:
can i do the same things with one interceptor? (one for show page elements data with grant_type=client_credentials and other for the normal users?)
Tha another question is... can i make a token with this interceptor if the token has not been created yet (only for the pages info, for the users i want to refresh the token if is going to expire)?
Sorry if is a little confused... i am confused, i really read many posts, documentation and help... but i don't know where to start... I hope that you can help me...
Thanks for all.
The beauty of JWT is that they are essentially just javascript objects. You could for instance provide the user a token containing their role in the system (user, admin, support etc...) and show/hide elements accordingly.
So basically not only you grant the user access to the API, you also provide them with their type of access. Of course you should NEVER rely on client side authentication to allow restricted API's directly (verify the token on each request, check for the provided role on the server).
Here's an example in NodeJS and Angular:
//In NodeJS...
app.get('/path/to/secured/api', verifyTokenOr401, function(req, res) {
//Do stuff...
res.json({msg: 'Success');
});
function verifyTokenOr401(req, res, next) {
var authHeader = req.headers.authorization;
try {
var token = authHeader.split(' ')[1];
if(jwt.verify(token, 'myAppSecret'))
next();
} catch(e) {
res.status(401).send('Not authorized');
}
}
//Assuming you use node-jsonwebtoken package
app.post('/path/to/authentication', function (req, res) {
//Verify authentication...
User.findOne({username: req.body.username}).then(function(user) {
//VerifyPassword
if(!user)
return res.status(401).send('No such user ' + req.body.username);
if(!user.verifyPassword(req.body.password))
return res.status(401).send('Wrong password for user ' + user.username);
//Provide the user with the access token
var token = jwt.sign({ subject: user.id, role: user.role }, 'myAppSecret');
res.setHeader('Authorization', 'Bearer ' + token.toString());
res.json(user);
})
.catch(function (e) { res.status(500).json(e); });
});
//In angular...
.factory('jwtInterceptor', function() {
return {
request: function(config){
var authHeader = config.headers('authorization');
//Attach header if not present
if(!authHeader)
config.headers.authorization = 'Bearer ' + localStorage.get('myAppToken');
return config;
},
response: function(response){
//Look for token in the header if you get a response and save it
var authHeader = response.headers('authorization');
if(authHeader){
try { localStorage.myAppToken = authHeader.split(' ')[1]; } catch(e) {}
}
return response;
}
}
});
Notable mention: check out auth0's repos for NodeJS and Angular. Both are awesome.
You can create a service which when loaded by angular make a get call for authorization token and set in header. Through this you do not need to set token at every Ajax call. You can do it like this:
app.service("MyService", ["$http", function($http) {
initialize();
function initialize() {
getAuthorizationToken().then(function(response) {
$http.defaults.headers.common.Authorization = 'Bearer some_auth_code_here';
});
}
function getAuthorizationToken() {
// Get call for token
}
}]);

AngularJS, $http and interceptor - every request received twice in nodejs

I'm trying to use AngularJS' $http interceptor for adding a token on every API call.
This is my code (http://pastebin.com/x1EMGcVE):
.factory('authInterceptor', function(authorization, API) {
return {
request: function(config) {
var token = authorization.getToken();
if (config.url.indexOf(API) === 0 && token) {
config.headers.Authorization = token;
}
return config;
}
}
})
On my nodes backend I'm receiving the call with express:
app.route('/API-CALL')
.get(function(req, res) {
...
My problem is that every API request is received twice in nodejs, one request without the token added in Authorization and one with the token added.
Is this an issue with the interceptor? Outputting the config from the interceptor seems to show no issues and only the correct number of requests with the token added.
If I remove the:
$httpProvider.interceptors.push('authInterceptor');
calls are only made once, but of course without the token added.

Session and Login User data with Node and AngularJS

I need to know that if my authentication and session management method is right.
I am using session management as when I receive successful auth. from node server. I store user data(without any trace of pass.) in $window.sessionStorage and if user marked rememberMe(checkbox), store data in $window.localStorage too.
Through this I am able to get data in different controllers. Though I read somewhere about session implementation at server(nodeJs) side is also possible. But I am not sure about how to use session along with JSONToken Authentication.
I was using
https://jasonwatmore.com/post/2015/12/09/MEAN-Stack-User-Registration-and-Login-Example.aspx
as a learning example but I could not understand it.
/app/app.js
Why is it in the run() method ?
// add JWT token as default auth header
$http.defaults.headers.common['Authorization'] = 'Bearer ' + $window.jwtToken;
and what is this:
// manually bootstrap angular after the JWT token is retrieved from the server
$(function () {
// get JWT token from server
$.get('/app/token', function (token) {
window.jwtToken = token;
angular.bootstrap(document, ['app']);
});
});
/controllers/app.controller.js
// use session auth to secure the angular app files
router.use('/', function (req, res, next) {
if (req.path !== '/login' && !req.session.token) {
return res.redirect('/login?returnUrl=' + encodeURIComponent('/app' + req.path));
}
next();
});
// make JWT token available to angular app
router.get('/token', function (req, res) {
res.send(req.session.token);
});
// serve angular app files from the '/app' route
router.use('/', express.static('app'));
So using a session server-side with JWT kind of defeats the purpose of using JWT. JWT's are awesome in a number of ways, but one of the ways they are great, is regardless which server intercepts a request, they can verify the user.
If you put it in a session, you have to make sure the client keeps going to the same server as the session is saved in memory on that machine. There are plenty of ways around that, but again it kind of defeats the purpose of a JSON web token.
What I did for my authentication with angular/node/JWT was just passed the JWT back in the header every time, and with my middleware intercepted it with:
req.header.whatever_my_tokens_name_is
The code below set the $http to send on every request the JWT Token to the server.
// add JWT token as default auth header
$http.defaults.headers.common['Authorization'] = 'Bearer ' + $window.jwtToken;
The code below get the token from '/app/token' and store it in LocalStorage. After that, it starts the angular.
// manually bootstrap angular after the JWT token is retrieved from the server
$(function () {
// get JWT token from server
$.get('/app/token', function (token) {
window.jwtToken = token;
angular.bootstrap(document, ['app']);
});
});
Here this is a middleware that check if there are no token stored in req.session.token and requested url is not '/login'. If so, send a redirect to '/login'.
// use session auth to secure the angular app files
router.use('/', function (req, res, next) {
if (req.path !== '/login' && !req.session.token) {
return res.redirect('/login?returnUrl=' + encodeURIComponent('/app' + req.path));
}
next();
});
Finally here, this is a endpoint to the client request the '/token' again from the server.
// make JWT token available to angular app
router.get('/token', function (req, res) {
res.send(req.session.token);
});
Anyway, check the #morgan-g response regarless session-side and JWT.
I hope this helps.

Correct way to set and override a request header in Angular

I need to set a global http header to all my requests because of the authentication method that we are using. We have an Identity Server to authenticate the user using a SSO approach. So far so good, we were using interceptors to set headers globally. But sometimes we need to make a request to a 3rd party API that doesn't use any authentication method.
How can I override the authentication header that was configured by the interceptor?
Is it a recommended approach for this problem?
In your interceptor, you can write some logic to decide if you need to add the header or not:
.factory('AuthHeaderInterceptor', function () {
function request(config) {
//if 3rd party url, don't add auth header
if(config.url.indexOf('third_party_url') !== -1) {
return config;
}
config.headers.Authorization = 'auth header';
return config;
}
return {
request: request
};
});

Resources