ASP.NET Core: JWT token with Scopes - c#

Background
I have a ASP.NET core (v2.1) project that contains an API. This API is access restricted by JWT bearer.
My server expose an endpoint for login:
POST http://example.com/api/login
After attaching the token to the request, I can call one of the server methods (GET or DELETE:
GET http://example.com/api/1234
or
DELETE http://example.com/api/1234
Target
I want to implement "another type" of token that will allow access only to specific scope. Let's say that we want to give access just for GET method. So, if you have this token - you can GET the resource but not to DELETE it.
Wondering if this is possible with JWT bearer token? If yes, how?
Thanks!

You shouldn't do this with the token itself. The token is used to authenticate that a user is who they claim to be. You should instead look at using the roles to authorise an action and assign different users roles to restrict access to delete verbs.
This article should be able to explain further
https://learn.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-2.1

JWT Bearer token should be used for authentication mechanism but what you are talking about is Authorization and thus your approach is wrong seems. You should rather use the Authorization pipeline and implement proper Roles/Policy based authorization which will restrict access to those Api endpoints.

Related

Client Claims not being checked by Policy

We have a system that uses C# Core 2.1, IdentityServer4, and Identity to authenticate users. Various other projects use the system for authorization. I can create policies in my API's that check user claims; and use those policies to secure resources. I add code similar to this in the API Sartup.cs:
services.AddAuthorization(options =>
{
options.AddPolicy("example",
policy => policy.RequireClaim("claim", "data"));
});
And add the following code before my API controller or specific task:
[Authorize(policy: "example")]
We have used this system for a long time. Now we want to lock down an action so that only a specific client can do it (not their users). But claims obtained through the grant type client_credentials are either not being added to the access token, or not being seen by the Authorization service.
Is there a way I can see what claims are in a token when it does not have openid as a scope?
Assuming the claim is there, why isn't the Authorization service able to see it?
Is there another alternative? We want to lock down an action so that only the client apps themselves can do it.
First you can always capture the raw tokens using Fiddler to see what claims that are actually passed to the receiver of the tokens. Then check in the User (ClaimsPrincipal) created by the authentication handler what claims it contains.
Then you need to explicitly map/add the missing claims so that the expected claims get into the claimsPrincipal User object. Some claims are removed in that process by default.

How to obtain "B2C JWT Access Token" from the signed in User?

I'm working with a .Net Core Web API and a .Net Core Web MVC Application. They both use Azure AD B2C to authenticate users. But in order to get a response from a HttpRequest from the Web API I need to provide the JWT Access Token from B2C for the signed in user on my web MVC application. Is there a way to obtain this access token inside a controller using the authenticated "User".
I have tried accessing the claims of the signed in user but no luck there, I have also used jwt.ms to review that the B2C workflow works well and that the JWT token is being generated and it works as well. The MVC application is authenticating the user and the web API is working fine with a hardcoded token. I just need to obtain the access token from a signed in user rather than doing it hardcoded.
I expect to be able to get the B2C JWT access token so that I can later on pass it to the Web Api and be able to secure my requests.
After getting some help from the MS AzureADB2C.UI GitHub crew we were able to solve the issue. The issue was that the tokens aren't saved by default on the library, so we needed to configure OIDC to specify that the tokens have to be saved for future use within the application. And so here is the example code of the "Startup" configuration and the example of how to query the "JWT access token" from the controller.
Startup.cs:
services.Configure(AzureADB2CDefaults.OpenIdScheme, options => {
options.SaveTokens = true;
});
Controller:
string idToken = await HttpContext.GetTokenAsync("id_token");
More information on how was the issue solved can be found on the following link:
https://github.com/aspnet/AspNetCore/issues/11424
You can refer to this sample application.
It uses the ASP.NET Core Azure AD B2C middleware to authenticate the end user and MSAL.NET to acquire, cache, and refresh the access token.
The access token is acquired in the AzureADB2COpenIdConnectOptionsConfigurator class.
A code example for a controller method referencing the access token is here.
Is it the actual token string you need? If so, you can access the headers using the HttpContext within the controller? The HttpContext will have a collection of headers that were passed in

How to get application profile data into access token?

I'm using IdentityServer4 with a mix of v4/v3 clients.
I have custom profile data that is store on the application side that I'd like to include in the access_token so that my downstream APIs can use this with bearer/jwt authenication.
I understand I can manipulate claims via IProfileService, but that is registered on the identity side, not the application.
How can I get my custom profile claims into the requested access token?
Additional Details
I've done a proof of concept using Extension Grants to specifically pass my application claims through the IdS so that it includes those in the token. It works...but feels pretty hacky.
Please do not do that. The JWT token is sent with every request.
if the downstream API needs something from the user, then either submit it with the call, or have an endpoing the downstream api can call. Embedding rarely used large inforamtion in someting transmitted every call (except in http 2.0) is a nonononono.
You can not change jwt token content after being created and signed by authorization server. But you can use ClaimsTransformation to manipulate claims on the api project.
Edit: Another option to use JwtBearer OnTokenValidated event.
Any claims issued from your implementation of IProfileService should end up in the token.
Note that your implementation of IProfileService should check if it is issuing claims related to IdentityResources or ApiResources. It would be a bit pointless adding api claims to an id_token.
When the client receives the token from you IDS, it will pass it in calls to your API.
If your client is using cookie authentication, the tokens themselves as well as some user profile claims will be stored in the authentication cookie. This obviously depends on the flow your are using Implicit, Hybrid etc.
If you want to inspect what you get back from the IDS at the client you could add a Cookie Authentication Event handler (eg OnValidatePrincipal) to see whats stored in the cookie, or add an OnUserInformationReceived event handler to your OIDC handler and inspect what you get back in there.

Asp.Net Core - Custom Authorization and Identity from another server?

I'm trying to figure out how to configure/use the Asp.Net Core Authorization with the credentials and user data in another server, accessed through an API.
For example, in the "Auth" server, we have the Auth database, that stores users, roles and claims. Some examples:
GET https://auth.myserver.com/v1/users/4/IsInRole/Admin
The response is a simple bool.
Or:
GET https://auth.myserver.com/v1/users/4/GetRolesForUser/
The response is a list of roles.
The another server is the resource server (also entirely API based, no front-end). It stores a lot of data that demands authorization by roles and claims.
Also, we have a third player: the client.
The client will:
Ask the auth server to get a bearer and a refresh token, using an username and a password
The client stores those tokens and send the bearer to the resource server to get some data
The resource server will ask the auth server if the bearer token is valid
If it is, then the resource server needs to ask the auth server again about the user that has that bearer token, and if that user has the necessary holes/claims that are necessary to access the requested resource.
The 4 step is my doubt. I imagine that should happen on the resource server controllers:
[HttpGet]
[Authorize(Roles = "Admin")] //API CALL HERE TO THE AUTH SERVER (?)
public async Task<IActionResult> GetData()
{
...
Basically, I don't know how to Authenticate an user on the context (just until the request is returned), putting it in the HttpContext.User, using my own custom validation process.
I've tried to simplify this architecture as much as possible to make my question more clear. Please forget about the security on the "Auth" server.
If you are using jwts this flow can be simplified roles can be stored in claims which means that no api call is needed in the authorise attribute.
Also the resource server doesn't need to verify that the token is valid that can be done using a secret.
Look into thinktecture the following are good resources https://leastprivilege.com/ and https://brockallen.com/

How to save OAuth Access Token in ASP.NET Web API

I have implemented simple OAuth server with Katana using following steps:
http://www.tugberkugurlu.com/archive/simple-oauth-server-implementing-a-simple-oauth-server-with-katana-oauth-authorization-server-components-part-1
I need to log each and every API Usage so when user access any API, I have to save the generated access token and other information in database.
In GrantResourceOwnerCredentials method, Is there any way to get generated access token or is there any event in OAuthAuthorizationServerProvider where I could get it?
I have not been able to find a way to get the token in the GrantResourceOwnerCredentials method. However, if you override the TokenEndpointResponse method, you can grab the access token there. It may be a little late in the pipeline for your purposes, but it's there.

Categories

Resources