AuthorizeAttribute: How to try with all available Authentication Schemas? - asp.net-core

I have a ASP.NET Core 3.1 Web Application which have ASP.NET Identity authentication and Role based authorization for interactive users (Pages)
Now I implemented some API Controller too within the same ASP.NET Core 3.1 application
[ApiController]
public class ConnectController : ControllerBase {...
I realized, that bearer token endpoint is not out of the box, so I successfully implemented it using OpenIddict, and it is working perfectly.
I would like to use Authorize attribute with Roles.
This is working:
[HttpGet]
[Authorize(Roles = "test01",
AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme)]
//[Authorize(Roles = "test01")] // This is not working, why?
public ActionResult<string> Ping01(string message)
{ ...
The pure [Authorize(Roles = "test01")] is not working, and I do not understand why?
For diagnostic purpose I examined all available Authentication Schemas, there are six, and the explicitly named "OpenIdDict.Validation.AspNetCore" is in the six (the last one, see debugger screenshot below). With other words I would like remain free change API Authentication methods and implementation in the future without touching the Controllers.
Question
How can I achieve that not specifying explicitly the Authentication Schemas in the AuthorizeAttribute constructor the authorization will try to Authorize with all available Authentication schemas?
Why I would like to do that?
...because I would not like to be specific to any Authentication Schema in my controllers. I would like to have a simple Role based authorization, and would not like the controller authorization code depend on anything else than the Role names.

How can I achieve that not specifying explicitly the Authentication
Schemas in the AuthorizeAttribute constructor the authorization will
try to Authorize with all available Authentication schemas?
If you don't want to specify the schemas explicitly, you have to create a Default Policy in the ConfigureServices method, like this:
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme)
.Build();
});
So now when you use [Authorize] the default policy will be included automatically.
By using this attribute now, you will have the user authorized by the role:
[Authorize, Authorize(Roles="admin")]
You may ask, why should Authorize attribute be used twice?
The answer to this can be found here: https://github.com/dotnet/aspnetcore/issues/18954

Related

Handle Authorization and Authentication in DDD

currently i am trying to deal with authorization and authentication on .net core API
There is a company, and that company can create custom roles.
Those roles, will have permissions inside it, such as:
Read
Write
Delete
The company, can apply a role to the users that he creates
With that said, how would i handle the authorization part?
Because, i believe this is considered business logic.
How should i approach this?
Thanks in advance
You can create the role and add claims to that specific role and policy for authorization
AddAuthorization((options) =>{
options.AddPolicy("UserCreation", policy =>
policy.RequireRole("Admin").RequireClaim("Admin", "Edit"));
by using the role manager in.net core identity you can add the claim to the role
RoleManager<Role> _roleManager;
_roleManager.AddClaimAsync(role, claim);
last you can check whether the user have the role and claim to access the resource using authorize attribute
[Authorize(Roles = "Admin", AuthenticationSchemes = "Bearer", Policy = "UserCreation")]
You can probably handle this in multiple different ways. I'd suggest, since you are referring to an API, to decorate the Controllers, Routes or both with the [Authorize] attribute, where you want the rules to apply.
And you would use this attribute as such (where foo, bar, baz - are the roles on the authenticated user).
[Authorize(Roles = "foo,bar,baz")]
You can also define the challange scheme like
[Authorize(Roles = "foo,bar,baz", AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
Docs: https://learn.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-6.0

Get current authentication scheme in ASP.NET core 2

I am currently struggling with an Asp.net core 2 application which uses two openid providers for authentication, mapped to two different Authentication Schemes (with different names).
The problem I am facing is trying to logout of the specific scheme that is currently being used. For example, if I support both Google and Facebook authentication, I need to understand which scheme is currently being used, and call the SignOut method indicating the correct scheme. This allows me to clear the local cookies and also redirect the user to the external identity provider and logout.
The thing is that I am not able to find a GetCurrentScheme() sort of function so that I can use to then specify the scheme in the SignOut method. I am sure I am missing something basic...
There does not seem be any direct way to find current scheme. Here is a crude way:
private readonly IAuthenticationSchemeProvider authenticationSchemeProvider;
...
foreach(var scheme in authenticationSchemeProvider.GetRequestHandlerSchemesAsync()){
var authResult = await context.AuthenticateAsync(scheme.Name);
if(authResult.Succeeded)
// this is the scheme that was used for authentication
}
I had the same question, but I finally put the authentication scheme in the claims collection in my SignIn method :
claims.Add(new Claim(ClaimTypes.AuthenticationMethod, authenticationScheme));
So, in the SignOut method, I can retrieve the authentication scheme :
var authenticationScheme = HttpContext.User.FindFirstValue(ClaimTypes.AuthenticationMethod);
IAuthenticationHandler has also Task InitializeAsync(AuthenticationScheme scheme, HttpContext context). It is called before AuthenticateAsync scheme name is here in first parameter.

How to restrict controller/view access based on domain ad group

I want to restrict certain parts of my web app to certain user groups located in AD groups inside our domain.
I am using .Net Core 1.1. I have also tried decorating my controller with the [Authorize] attribute but with little success.
Does .Net Core currently have a way to do this?
Make sure you pass windows authentication token with in your Services:
services.Configure<IISOptions>(options =>
{
options.ForwardWindowsAuthentication = true;
});
And then use the [Authorize] attribute as follows
[Authorize(Roles = "AD Role")]

Get JSON Web Token payload data within controller action

I'm implementing JWT based authorization for my ASP.NET Web API application with Angular2 SPA. All is well and clear regarding authorization flow except for one detail. I am wondering how to get JWT payload information within the Web API controller action?
Looking through the web I can't find any solution that I would go for, for example, setting Thread.Principal or something like that.
What are the recommended ways to accomplish that?
The normal process to handle a JWT token as authentication in ASP.NET is:
Get the token from the request and ensure is valid.
Create a principal based on the information contained within the token and associate it with the request.
This implies that the payload information within the token is available through the request principal usually in the form of claims. For example, if your JWT contains information about the user roles it would get mapped to a role claim available in the principal.
You don't mention if you're using OWIN or not so I'll assume OWIN for the example, but it shouldn't really matter or be much different at the controller level.
Despite the fact you're concerned only with the data consumption part, if curious, you can read through this set of tutorials about ASP.NET Web API (OWIN) for a more in-depth look on the whole process:
Introduction
Authentication (HS256)
Authorization
The last one would be the one with most interest , you'll note the following code snippet on that one:
[HttpGet]
[Authorize]
[Route("claims")]
public object Claims()
{
var claimsIdentity = User.Identity as ClaimsIdentity;
return claimsIdentity.Claims.Select(c =>
new
{
Type = c.Type,
Value = c.Value
});
}
This relies on the User.Identity available within the controller to list all the claims of the currently authenticated identity. Unless you have an authentication pipeline configured rather different then what it's the norm, these claims are mapped from the JWT payload your API receives.

Authorize Claim in every Web Api Request using ASP.NET Identity Token Based Authenticaton

How can I authorize claims for each web api request using Token Based Authentication. I have a controller on which I applied Authorize attribute that will look for token on each request and return response if it's a valid token. But I have a controller called AdminController which I would like to be accessible for user having admin claim. How can I implement this? Any suggestion please?
Quick way to do this is to add claim of type "Role" and assign it value of "Admin", this should be done before generating the token for this user in method GrantResourceOwnerCredentials, it will be as the code below:
identity.AddClaim(new Claim(ClaimTypes.Role, "Admin"));
Now in your AdminController you attribute it with
[Authorize(Roles="Admin")]
This is called Roles based authentication but at the end the Roles are considered as claims.
You can check this complete code sample too