Token Based Authorization Web API - c#

I'm building an application using backbone.js and web api. JS client will send ajax requests to access api. Building an API is pretty easy but i want to implement authentication and authorization for API.
I'm planning to return a token after a successful authentication and use this token for further requests. This token will be passed in HTTP Authorization headers.
My requirements are as below
1) Verify token on each request and get user id.
2) Use fetched user id for further actions.
First bit can be handled using Custom action filter where the permanent token can be verified against the database.
But i'm not able to find any sample or example for doing a second bit. I want to get a userid from a passed token and carry it further for later processing.
Is there any way of doing it?
Waiting for suggestions or ideas. Any code sample will really help. Thanks in advance.

You can set Thread.CurrentPrincipal upon successful token verification like this:
IPrincipal principal = new GenericPrincipal(new GenericIdentity(username), null);
Thread.CurrentPrincipal = principal;
// if we're running in IIS...
if ( HttpContext.Current != null )
HttpContext.Current.User = principal;
The principal might also be an instance of a custom class implementing the System.Security.Principal.IPrincipal interface (in order to be able to have its user ID associated).
I further suggest you use a DelegatingHandler instead of an action filter for the token verification in order to set the current principal as early as possible during the message lifecycle. Additionally, this way you don't have to decorate every action method/controller with the action filter attribute.

I highly recommend to use OAuth. Anyway, you can set the token and user info in session and use them in subsequent calls. i.e. if the session is active and user info exists then use them otherwise authorize and authenticate user (probably through OAuth) and if it is valid then store them in session to be used in subsequent calls.

Related

How to use JWT token and Action filters to retrieve user specific content?

I'm developing an .NET Web API and using JWT tokens to secure it. In my research of the best way to implement it, i decided to use the jwt claims to also limit the access to content, depending on specific claims present on the token. I can now manually verify if for example, a userId matches with the userId of a record's userId and return it if it's a match, but this is very tedious and not quickly adds up the amount of code just to do the same task...
Is there a way to implement something like an action filter to apply the claims to every request and return only the records that match the information in the token?
Thanks everyone in advance
See this implementation on this project.
https://github.com/cuongle/WebApi.Jwt/blob/master/WebApi.Jwt/Filters/JwtAuthenticationAttribute.cs
It's a simple scenario.
JWT contains a user's id or some claims.
You have a WEB API endpoint like ("GetCurrentUserData()") decorated with your custom ActionFilterAttribute.
Within that method you will call a helper function that will read the current request user claims and return them in a simple form (like user id).
See: Get claims from a WebAPI Controller - JWT Token,
Then within the method you can query/filter your returned data based on the Id/Claims of the current user of the request.

Fetch permissions from identity server during authorization

I am using identity server 4 for authentication and authorization, and user permissions are saved in JWT and then used on API-s to check if users has required permission.
But the problem is that JWT got too big and I would like to remove permissions from it, and make custom authorization on API-s so that its fetches permissions from identity server instead of getting it from JWT.
API would get only userId from JWT and then based on that fetch additional information from identity server. Is it possible to do something like that?
We basically have a similar problem in our application.
The way to solve this problem is using an event which is raised at the level of the API resource (the API which you are protecting by using JWT bearer tokens authentication) once the JWT token has been read from the incoming request and validated.
This event is called OnTokenValidated, see here for more details.
This is the top level plan:
keep your JWT bearer token minimal. At the very minimum it contains the subject id, which is the unique identifier of the user at the identity provider level. You can put other claims there, but the idea is that the JWT bearer token must be small
implement a way to get the user permissions given the user unique identifier (you can use the subject id as an identifier or any other id which makes sense in your system)
make the user permissions fetch mechanism of the previous point accessible via api call. Caching this API is a good idea, because usually permissions are stable. Defining a smart way to evict this cache is beyond the scope of this answer, but it's something you should definitely think about.
once you have fetched the user permissions (via an API call) you need to make them available to the ASP.NET core authorization framework. The simplest way to do so is create a custom claim type (for instance: "app_permission") and create one user claim per each user permission. Each of these permission claims has the custom claim type ("app_permission") and the permission name as the claim value. For instance a user having the two permissions "read-content" and "write-content" will have two claims both having "app_permission" as the claim type, the first one having "read-content" as the claim value and the second one having "write-content" as the claim value.
the permissions claims defined at the previous point can be injected in the user identity (at the API resource level) by defining an additional ClaimsIdentity for the user and by adding it to the current user identity. The process depicted here is quite similar to a claims transformation done by an MVC application using cookie authentication.
In the Startup class of your API resource, in the point where you register the authentication services, you can do something like this:
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://localhost:8080";
options.Audience = "sample-api";
options.RequireHttpsMetadata = false;
// register callbacks for events
options.Events = new JwtBearerEvents
{
OnTokenValidated = context =>
{
if (!context.Principal.Identity.IsAuthenticated)
{
return;
}
var subjectId = context.Principal.FindFirst(JwtClaimTypes.Subject)?.Value;
if (string.IsNullOrWhiteSpace(subjectId))
{
return;
}
// do whatever you want with the user subjectId in order to get user permissions.
//You can resolve services by using context.HttpContext.RequestServices which is an instance of IServiceProvider
//Usually you will perform an API call to fetch user permissions by using the subject id as the user unique identifier
// User permissions are usually transformed in additional user claims, so that they are accessible from ASP.NET core authorization handlers
var identity = new ClaimsIdentity(userPermissionsClaims);
context.Principal.AddIdentity(identity);
}
};
});
+1 for the accepted answer but I would just like to offer an alternative solution to this problem. If your permissions are pretty simple like readResource or writeResource then you could define all your permissions as enum and use integers instead of strings in JWT, that would reduce JWT size.
If permission list is still huge then you could also group permissions together so that the permission list is smaller for some customers e.g. merge readResource, writeResource, updateResource, deleteResource into one permission called crudResource.

ASP.NET Set User Identity and IsAuthenticated = true

I have an ASP.NET MVC application that must only be accessed by users that are logged in.
We are implementing PingAccess and PingFederate that intercepts traffic to our application and forces the user to log in before it even hits our application.
Once authenticated PingAccess sets a cookie containing a JWT token and I can read this inside an MVC controller and abstract the claims (sample below) but I need to be able to set the User.Identity object and ensure that IsAuthenticated is true so that I can use the standard Authorize attribute on all of our controllers.
var cookie = this.Request.Cookies.Get("PA.mycookie");
var jwtTokenString = cookie.Value;
var jwtToken = new JwtSecurityToken(jwtTokenString);
var claims = jwtToken.Claims;
Could anyone point me in the right direction?
Many thanks
If the goal of going after the User.Identity object and the IsAuthenticated attribute is just to ensure that your Authorize attribute works, then the way to do that via jwt tokens requires some setup in Startup.cs via ConfigureOAuthTokenConsumption. The second answer in this post has some example code that may set you on the right track: How to use JWT in MVC application for authentication and authorization?.

Retrieve bearer token in ASP.NET WebAPI

I have a Web API with authentication enabled (bearer token). This is called by a client application and I want to protect it from anonymous usage so I would like to create a single user and create a bearer token for it.
I can create the token by calling the register and token methods, but I would like to do this from code.
As far as I know, the bearer token is not stored in the database. Can it be retrieved somehow using the ASP.NET Identity API?
I would also like to create this user from code and save the token somewhere because I need to deploy the database to multiple servers.
I do not recommend going with this approach if you have only one client who will talk to your API, my understanding that you need to issue a very very long lived access token maybe for a year and keep using this token to access the back-end API, right?
What you will do if this token is stolen? You can't revoke the access token, so it is somehow like your master key (password).
My recommendation is to use OAuth refresh tokens along with access tokens. This depends on the type of your client, you can check how this is done here http://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/
The refresh tokens can be revoked and they can expire after a very long time. Let me know if you need further details to implement this.
Create a Custom Authentication Attribute and store the token hashes for users. A user can have multiple tokens. Then you can let user do what he wants - log out all other sessions when password is changed or remove sessions selectively
public class CustomAuthAttribute : System.Web.Http.AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext context)
{
var accessToken = HttpContext.Current.Request.Headers["Authorization"];
var hash = accessToken.Md5();
//store the hash for that user
//check if the hash is created before the password change or its session was removed by the user
//store IP address and user agent
var isBlackListed = ...
.....
return !isBlackListed && base.IsAuthorized(context);
}
}
If you're needing to decode the token within a WebAPI Controller function, I found this worked:
String token = Request.Headers.Authorization.Parameter;
Microsoft.Owin.Security.AuthenticationTicket t = Startup.OAuthOptions.AccessTokenFormat.Unprotect(token);

How to access the ACS token on mvc application?

I am using Access Control Service (ACS). I configure my MVC-4 application to use ACS. I put the return url to my controller, which is http://127.0.0.1:81/ACS/LogOn and after logon with any identity provider we are successfully return to the controller. But now can anybody please tell me how i can access the issued token in the controller ?
Assuming that you've used the normal WIF-based mechanisms to configure your app to use ACS, everything you need should be accessible via Thread.CurrentPrincipal. In most cases, you don't want the token itself but instead you want the claims within it. See this example.
If you actually need the underlying token in XML/string form rather than the claims (I wouldn't recommend this most of the time) then you can get it by setting SaveBoostrapContext in your service configuration to true and accessing it via the BootstrapContext property on the claims identity.
Thread.CurrentPrincipal.Identity.BootstrapContext;

Categories