Authenticate and Authorise in Both MVC and Http AuthorizeAttribute - angularjs

I get follow scenario which is working now:
MVC controller using System.Web.Mvc.AuthorizeAttribute to authenticate user is authenticated or not, it will be using cookie.
API controller using System.Web.Http.AuthorizeAttribute to authorise with bearer token.
I do also have angular http interceptor that verify and get bearer token for API purpose that can use among all angular $http request. But I am confusing how to achieve both after user has login?
This is current workflow
User click login, angular verify and store bears token in local storage.
After complete, manually trigger MVC controller so that it will get cookie for MVC authenticate.
This seem to me really double job, or I should focusing on using one AuthorizeAttribute?

You need you use Authorize key to give permission to those functions where authorization is needed. And those functions can only be accessed when authorization token is generated and passed with http request.
module.service('tokenservice', function ($http) {
this.get = function () {
var accesstoken = sessionStorage.getItem('accessToken');
var logged_in = localStorage.getItem('logged_in').toString().trim() === 'false' ? false : true;
var authHeaders = {};
if (accesstoken && logged_in) {
authHeaders.Authorization = 'Bearer ' + accesstoken;
}
return authHeaders;
};
});
module.controller('yourControllerName', function ( $http, tokenservice) {
$http({
method: "POST",
url: '/Controller/MyFucntion',
headers: tokenservice.get(),
});
});
This will help you to get generated token in user login. After that You need to work with your controller
[Authorize]
public JsonResult MyFucntion()
{
//Your logic and calculation
//return
}
Hope that will help

Related

Angularjs $http service passing facebook access token

I'm implementing fb authentication in my SPA built using MEAN stack. While I've successfully implemented the fb authentication using facebook token passport strategy, I'm facing issues in securing API endpoints. Because for that I need to pass both the authenticated user object and access token in the $http service and I've tried passing access_token as a property of the user object and also as a header property, but I still 401 (Unauthorized error). Below is my code snippet.
Passport documentation says "Authorization: Bearer base64_access_token_string". Should the token be encoded in a base64 format? Pls help.
server code
app.get('/api/getbikes*',
passport.authenticate('facebook-token',{session: false}),
function(req,res){
if(req.user){
console.log('In getbikes api');
// console.log('req.query :',req.query);
var msg="";
ubBike
.find({cust:req.query._id})
.populate('cust','email')
.exec(function(err,bikes){
res.send(bikes);
if(err) throw err;
});
}
else
{
res.send(401);
}
});
angular code
service
this.getbikes = function(user){
var deferred = $q.defer();
$http({
method:"GET",
url:"http://localhost:3000/api/getbikes",
params: user,
headers:{
Authorization:auth.getAccesstoken()
}
}).then(function successCallback(srresponse){
deferred.resolve(srresponse.data);
},
function failureCallback(srresponse){
$log.error("get bikes http call failed ",srresponse.data);
deferred.reject(srresponse.data);
});//$http
return deferred.promise;
};//getbikes
controller
$scope.fblogin= function(){
auth.fblogin().then(
function(response){
$scope.isAuth = auth.isAuth;
$scope.usr =auth.getResponseobj();
$scope.usr.access_token=auth.getAccesstoken();
$scope.profpic=auth.profpic;
bike.getbikes($scope.usr).then(function(response){
if (response.length ==0)
{
$location.path('/addbike');//redirect to addbike screen
}
else{
$location.path('/appoint');//else redirect to view appointment screen
}
},function(reason){
$scope.msg1 = reason;
});//getbikes
},function(reason){
$log.log("fblogin() - failure :Need to login to the application :"+reason);
})
};//fblogin
Surprisingly, when I send the header as "Authorization: Bearer access_token_string" ie the fb token as is without base64 encoding the API authentication works perfectly fine. This is contrary to the passport facebook token documentation https://github.com/drudge/passport-facebook-token

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
}
}]);

Angular.js SPA security with ASP.NET MVC and WebApi

I'm building a SPA using Angular.js and ASP.NET and I would like to know what is the best way to secure it.
Here is what I need :
I would like to use MVC framework to hide my application only to logged users. So the first thing that users will do before launching the SPA will be to log into the website using a simple login form.
When the Angular app will be launched, it will communicate with my ApiController using REST requests.
I also want my user to be logged out automatically after 20 minutes of inactivity.
I know that REST is supposed to be stateless... but I can't figure how to implement all I need without sessions...
But on the other side, I want to be able to use my WebAPI with a future mobile application. I will have to use Tokens for the authentication on this application.
What is the best way for me to achieve that kind of authentication?
Thanks for your time!
I developed an entire security layer with the same conditions as yours following those very well explained in this post here.
BTW, the token will expire automatically after 20 minutes because when you create it you will set it's expiration date immediately; every time you're going to make a request, the system will check the token exp date with the current date, refusing your token if the time passed. For example this a tipical oauth server configuration with token and refresh token settings:
internal static OAuthAuthorizationServerOptions GetAuthorizationServerOptions(IComponentContext scope)
{
OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
ApplicationCanDisplayErrors = true,
TokenEndpointPath = new PathString(Constants.PublicAuth.OAUTH_TOKEN_PATH),
AuthorizeEndpointPath = new PathString(Constants.ExternalAuth.AUTH_ENDPOINT),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(Constants.PublicAuth.TOKEN_EXPIRATION_IN_MINUTES),
Provider = scope.Resolve<AuthorizationServerProvider>(),
AccessTokenFormat = new CustomJwtFormat(),
RefreshTokenProvider = scope.Resolve<SimpleRefreshTokenProvider>()
};
return oAuthServerOptions;
}
The refresh token is also very useful, but you have to manage the token replacement by yourself; for example in our application we pass every API call through a single service that, if the server responds 401 (unauthorized), it will try to request a new token using the refresh token and then it will try the same call again. Only after the second failure you'll be redirected to the login page.
For example:
function executeCallWithAuth(method, url, payload, params) {
var defer = $q.defer();
debug.logf('{0}: {1}', method.toUpperCase(), url);
$http({ method: method, url: url, data: payload, headers: createHeaders(), params: params }).then(
function(results) { defer.resolve(results); },
function(error) {
if (error.status !== 401) defer.reject(error);
else {
debug.warn(`Call to: ${method}:${url} result in 401, try token refresh...`);
auth.refreshToken().then(
function() {
debug.warn('Token refresh succesfully, retry api call...');
$http({ method: method, url: url, data: payload, headers: createHeaders() }).then(
function(results) { defer.resolve(results); },
function(errors) { defer.reject(errors); });
},
function(tokenError) {
debug.warn('Token refresh rejected, redirect to login.');
$state.go('login');
defer.reject(tokenError);
});
}
});
return defer.promise;
}
and
function createHeaders() {
var headers = {
};
var authData = storage.get('authorizationData');
if (authData) {
headers.Authorization = 'Bearer ' + authData.token;
}
return headers;
}
Using Angular the best way to secure a route is "do not create a route". Basically, you need to load the user profile, and only after that you will create the routes only to the pages he can navigate to. If you don't create the route for a page you don't need to secure that page: Angular will automatically send the user to a 404.
I would secure your WebAPI calls with OAuth2 (you can even use the built in Identity 2.0 provider that comes baked in with it). Keep your WebAPI stateless, use SSL (consider a filter to force it), and use the [Authorize] tags to secure you services. On the MVC side, this will have to maintain state and you will want to have the login form get an OAuth2 token from your WebAPI layer and pass that down into Angular. Set the expiration on this to 20 minutes. You can also use the cookies authentication model here since it will need to be stateful on the MVC side, but all ajax calls made to the WebAPI layer by Angular will need to pass the OAuth2 token as a bearer token in the Authorization request header.

Angular $http post with custom headers

I am new to angular and am from .net framework. I need to post a angular request to .net service, where it expects two custom headers from the client.
angular post command:
var request = $http(
{
url: "http://localhost:53585/api/myService/Validate",
method: "POST",
data: JSON.stringify(payload),
headers: { 'first_token': sessionService.first_token, 'second_token': sessionService.second_token }
});
But in the service side, I can see only first_token in the request header and not the second token. What I am missing here?
Issue is with my service. I figured out and restarted the IIS and then service was able to read both the headers token
I found this method in a forum, it works.
return this.http.post<any>('https://yourendpoint', { username, password }, { headers: new HttpHeaders().set('Authorizaion', 'your token')})
.pipe(map(user => {
// login successful if there's a jwt token in the response
if (user && user.token) {
// sto`enter code here`re user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
console.log(user);
return user;

Resources