Repository files navigation

Simple Authentication for ASP.NET Core

Lint Code BaseCodeQLNugetNugetLicense: MIT

A library to easily integrate Authentication in ASP.NET Core projects. Currently it supports JWT Bearer, API Key and Basic Authentication in both Controller-based and Minimal API projects.

Important

Update from Version 2.x to 3.x Swashbuckle (Swagger) support has been moved out from SimpleAuthentication. If you're using the AddSimpleAuthentication extension method with AddSwaggerGen, now you need to install the SimpleAuthentication.Swashbuckle package.

Installation

The library is available on NuGet. Just search for SimpleAuthenticationTools in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools

Usage video

Take a look to a quick demo showing how to integrate the library:

Simple Authentication for ASP.NET Core

Configuration

Authentication can be totally configured adding an Authentication section in the appsettings.json file:

"Authentication": {
"DefaultScheme": "Bearer", // Optional
"JwtBearer": {
"SchemeName": "Bearer" // Default: Bearer
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
"SecurityKey": "supersecretsecuritykey42!", // Required
"Algorithm": "HS256", // Default: HS256
"Issuers": [ "issuer" ], // Optional
"Audiences": [ "audience" ], // Optional
"ExpirationTime": "01:00:00", // Default: No expiration
"ClockSkew": "00:02:00", // Default: 5 minutes
"EnableJwtBearerService": true // Default: true
},
"ApiKey": {
"SchemeName": "ApiKey", // Default: ApiKey
// You can specify either HeaderName, QueryStringKey or both
"HeaderName": "x-api-key",
"QueryStringKey": "code",
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment this line if you want to validate the API Key against a fixed value.
// Otherwise, you need to register an IApiKeyValidator implementation that will be used
// to validate the API Key.
//"ApiKeyValue": "f1I7S5GXa4wQDgLQWgz0",
"UserName": "ApiUser" // Required if ApiKeyValue is used
},
"Basic": {
"SchemeName": "Basic", // Default: Basic
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment the following lines if you want to validate user name and password
// against fixed values.
// Otherwise, you need to register an IBasicAuthenticationValidator implementation
// that will be used to validate the credentials.
//"UserName": "marco",
//"Password": "P@$$w0rd"
}
}

You can configure only the kind of authentication you want to use, or you can include all of them.

The DefaultScheme attribute is used to specify what kind of authentication must be configured as default. Allowed values are the values of the SchemeName attributes.

Registering authentication at Startup

usingSimpleAuthentication;varbuilder=WebApplication.CreateBuilder(args);// ...// Registers authentication schemes and services using IConfiguration information (see above).builder.Services.AddSimpleAuthentication(builder.Configuration);// ...varapp=builder.Build();//...// The following middlewares aren't strictly necessary in .NET 7.0 or higher, because they are automatically// added when detecting that the corresponding services have been registered. However, you may// need to call them explicitly if the default middlewares configuration is not correct for your// app, for example when you need to use CORS.// Check https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/middleware// for more information.//app.UseAuthentication();//app.UseAuthorization();//...app.Run();

Integrating with Swashbuckle

If you're using Swashbuckle (Swagger) to document your API, you can integrate the authentication configuration with the Swagger documentation. Just search for SimpleAuthenticationTools.Swashbuckle in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools.Swashbuckle

Then, you can use the AddSimpleAuthentication extension method:

builder.Services.AddSwaggerGen(options =>{// ...// Add this line to integrate authentication with Swagger.options.AddSimpleAuthentication(builder.Configuration);});

Integrating with Microsoft.AspNetCore.OpenApi (.NET 9 or later)

Starting from version 9, .NET offer a built-in support for OpenAPI. If you're using the AddOpenApi extension method to provide OpenAPI support, you just need to add the corresponding extension method in its declaration (no extra package required):

builder.Services.AddOpenApi(options =>{// ...// Add this line to integrate authentication with OpenAPI.options.AddSimpleAuthentication(builder.Configuration);});

Important

Known issue Currently, to make the AddSimpleAuthentication extension method work with AddOpenApi, you need to have at least one endpoint that produces a Problem response, for example:

app.MapPost("api/auth/login",()=>{// ...}).ProducesProblem(StatusCodes.Status400BadRequest);

This is a workaround that will be fixed in the next release.

Creating a JWT Bearer

When using JWT Bearer authentication, you can set the EnableJwtBearerService setting to true to automatically register an implementation of the IJwtBearerService interface to create a valid JWT Bearer, according to the setting you have specified in the appsettings.json file:

app.MapPost("api/auth/login",(LoginRequestloginRequest,IJwtBearerServicejwtBearerService)=>{// Check for login rights...// Add custom claims (optional).varclaims=newList<Claim>{new(ClaimTypes.GivenName,"Marco"),new(ClaimTypes.Surname,"Minerva")};vartoken=jwtBearerService.CreateToken(loginRequest.UserName,claims);returnTypedResults.Ok(newLoginResponse(token));});publicrecordclassLoginRequest(stringUserName,stringPassword);publicrecordclassLoginResponse(stringToken);

The IJwtBearerService.CreateToken method allows to specify the issuer and the audience of the token. If you don't specify any value, the first ones defined in appsettings.json will be used.

Supporting multiple API Keys/Basic Authentication credentials

When using API Key or Basic Authentication, you can specify multiple fixed values for authentication:

"Authentication": {
"ApiKey": {
"ApiKeys": [
{
"Value": "key-1",
"UserName": "UserName1"
},
{
"Value": "key-2",
"UserName": "UserName2"
}
]
},
"Basic": {
"Credentials": [
{
"UserName": "UserName1",
"Password": "Password1"
},
{
"UserName": "UserName2",
"Password": "Password2"
}
]
}
}

With this configuration, authentication will succedd if any of these credentials are provided.

Custom Authentication logic for API Keys and Basic Authentication

If you need to implement custom authentication login, for example validating credentials with dynamic values and adding claims to identity, you can omit all the credentials in the appsettings.json file and then provide an implementation of IApiKeyValidator.cs or IBasicAuthenticationValidator.cs:

builder.Services.AddTransient<IApiKeyValidator,CustomApiKeyValidator>();builder.Services.AddTransient<IBasicAuthenticationValidator,CustomBasicAuthenticationValidator>();//...publicclassCustomApiKeyValidator:IApiKeyValidator{publicTask<ApiKeyValidationResult>ValidateAsync(stringapiKey){varresult=apiKeyswitch{"ArAilHVOoL3upX78Cohq"=>ApiKeyValidationResult.Success("User 1"),"DiUU5EqImTYkxPDAxBVS"=>ApiKeyValidationResult.Success("User 2"),
_ =>ApiKeyValidationResult.Fail("Invalid User")};returnTask.FromResult(result);}}publicclassCustomBasicAuthenticationValidator:IBasicAuthenticationValidator{publicTask<BasicAuthenticationValidationResult>ValidateAsync(stringuserName,stringpassword){if(userName==password){varclaims=newList<Claim>(){new(ClaimTypes.Role,"User")};returnTask.FromResult(BasicAuthenticationValidationResult.Success(userName,claims));}returnTask.FromResult(BasicAuthenticationValidationResult.Fail("Invalid user"));}}

Permission-based authorization

The library provides services for adding permission-based authorization to an ASP.NET Core project. Just use the following registration at startup:

// Enable permission-based authorization.builder.Services.AddPermissions<T>();

The AddPermissions extension method requires an implementation of the IPermissionHandler interface, that is responsible to check if the user owns the required permissions:

publicinterfaceIPermissionHandler{Task<bool>IsGrantedAsync(ClaimsPrincipaluser,IEnumerable<string>permissions);}

The library provides the built-in ScopeClaimPermissionHandler class, that checks for permissions reading the default scope claims of the current user (scp or http://schemas.microsoft.com/identity/claims/scope). To use this default handler, we can just write this:

builder.Services.AddScopePermissions();// The line above is equivalent to builder.Services.AddPermissions<ScopeClaimPermissionHandler>();

Based on the scenario, we can provide our own implementation, for example reading different claims or using external services (database, HTTP calls, etc.) to get user permissions.

Then, just use the PermissionAttribute or the RequirePermission extension method:

// In a Controller[Permission("profile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequirePermission("profile")

With the ScopeClaimPermissionHandler mentioned above, the invocation succeeds if the user has a scp or http://schemas.microsoft.com/identity/claims/scope claim that contains the profile value, for example:

"scp": "profile email calendar:read"

It is also possible to explicitly create a policy that requires the one or more permissions:

builder.Services.AddAuthorization(options =>{// Define permissions using a policy.options.AddPolicy("UserProfile", builder =>builder.RequirePermission("profile"));});// ...// In a Controller[Authorize(Policy="UserProfile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequireAuthorization(policyNames:"UserProfile")

Samples

Contribute

The project is constantly evolving. Contributions are welcome. Feel free to file issues and pull requests on the repo and we'll address them as we can.

About

A library to easily integrate Authentication in ASP.NET Core projects.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Simple Authentication for ASP.NET Core

Lint Code BaseCodeQLNugetNugetLicense: MIT

A library to easily integrate Authentication in ASP.NET Core projects. Currently it supports JWT Bearer, API Key and Basic Authentication in both Controller-based and Minimal API projects.

Important

Update from Version 2.x to 3.x Swashbuckle (Swagger) support has been moved out from SimpleAuthentication. If you're using the AddSimpleAuthentication extension method with AddSwaggerGen, now you need to install the SimpleAuthentication.Swashbuckle package.

Installation

The library is available on NuGet. Just search for SimpleAuthenticationTools in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools

Usage video

Take a look to a quick demo showing how to integrate the library:

Simple Authentication for ASP.NET Core

Configuration

Authentication can be totally configured adding an Authentication section in the appsettings.json file:

"Authentication": {
"DefaultScheme": "Bearer", // Optional
"JwtBearer": {
"SchemeName": "Bearer" // Default: Bearer
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
"SecurityKey": "supersecretsecuritykey42!", // Required
"Algorithm": "HS256", // Default: HS256
"Issuers": [ "issuer" ], // Optional
"Audiences": [ "audience" ], // Optional
"ExpirationTime": "01:00:00", // Default: No expiration
"ClockSkew": "00:02:00", // Default: 5 minutes
"EnableJwtBearerService": true // Default: true
},
"ApiKey": {
"SchemeName": "ApiKey", // Default: ApiKey
// You can specify either HeaderName, QueryStringKey or both
"HeaderName": "x-api-key",
"QueryStringKey": "code",
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment this line if you want to validate the API Key against a fixed value.
// Otherwise, you need to register an IApiKeyValidator implementation that will be used
// to validate the API Key.
//"ApiKeyValue": "f1I7S5GXa4wQDgLQWgz0",
"UserName": "ApiUser" // Required if ApiKeyValue is used
},
"Basic": {
"SchemeName": "Basic", // Default: Basic
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment the following lines if you want to validate user name and password
// against fixed values.
// Otherwise, you need to register an IBasicAuthenticationValidator implementation
// that will be used to validate the credentials.
//"UserName": "marco",
//"Password": "P@$$w0rd"
}
}

You can configure only the kind of authentication you want to use, or you can include all of them.

The DefaultScheme attribute is used to specify what kind of authentication must be configured as default. Allowed values are the values of the SchemeName attributes.

Registering authentication at Startup

usingSimpleAuthentication;varbuilder=WebApplication.CreateBuilder(args);// ...// Registers authentication schemes and services using IConfiguration information (see above).builder.Services.AddSimpleAuthentication(builder.Configuration);// ...varapp=builder.Build();//...// The following middlewares aren't strictly necessary in .NET 7.0 or higher, because they are automatically// added when detecting that the corresponding services have been registered. However, you may// need to call them explicitly if the default middlewares configuration is not correct for your// app, for example when you need to use CORS.// Check https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/middleware// for more information.//app.UseAuthentication();//app.UseAuthorization();//...app.Run();

Integrating with Swashbuckle

If you're using Swashbuckle (Swagger) to document your API, you can integrate the authentication configuration with the Swagger documentation. Just search for SimpleAuthenticationTools.Swashbuckle in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools.Swashbuckle

Then, you can use the AddSimpleAuthentication extension method:

builder.Services.AddSwaggerGen(options =>{// ...// Add this line to integrate authentication with Swagger.options.AddSimpleAuthentication(builder.Configuration);});

Integrating with Microsoft.AspNetCore.OpenApi (.NET 9 or later)

Starting from version 9, .NET offer a built-in support for OpenAPI. If you're using the AddOpenApi extension method to provide OpenAPI support, you just need to add the corresponding extension method in its declaration (no extra package required):

builder.Services.AddOpenApi(options =>{// ...// Add this line to integrate authentication with OpenAPI.options.AddSimpleAuthentication(builder.Configuration);});

Important

Known issue Currently, to make the AddSimpleAuthentication extension method work with AddOpenApi, you need to have at least one endpoint that produces a Problem response, for example:

app.MapPost("api/auth/login",()=>{// ...}).ProducesProblem(StatusCodes.Status400BadRequest);

This is a workaround that will be fixed in the next release.

Creating a JWT Bearer

When using JWT Bearer authentication, you can set the EnableJwtBearerService setting to true to automatically register an implementation of the IJwtBearerService interface to create a valid JWT Bearer, according to the setting you have specified in the appsettings.json file:

app.MapPost("api/auth/login",(LoginRequestloginRequest,IJwtBearerServicejwtBearerService)=>{// Check for login rights...// Add custom claims (optional).varclaims=newList<Claim>{new(ClaimTypes.GivenName,"Marco"),new(ClaimTypes.Surname,"Minerva")};vartoken=jwtBearerService.CreateToken(loginRequest.UserName,claims);returnTypedResults.Ok(newLoginResponse(token));});publicrecordclassLoginRequest(stringUserName,stringPassword);publicrecordclassLoginResponse(stringToken);

The IJwtBearerService.CreateToken method allows to specify the issuer and the audience of the token. If you don't specify any value, the first ones defined in appsettings.json will be used.

Supporting multiple API Keys/Basic Authentication credentials

When using API Key or Basic Authentication, you can specify multiple fixed values for authentication:

"Authentication": {
"ApiKey": {
"ApiKeys": [
{
"Value": "key-1",
"UserName": "UserName1"
},
{
"Value": "key-2",
"UserName": "UserName2"
}
]
},
"Basic": {
"Credentials": [
{
"UserName": "UserName1",
"Password": "Password1"
},
{
"UserName": "UserName2",
"Password": "Password2"
}
]
}
}

With this configuration, authentication will succedd if any of these credentials are provided.

Custom Authentication logic for API Keys and Basic Authentication

If you need to implement custom authentication login, for example validating credentials with dynamic values and adding claims to identity, you can omit all the credentials in the appsettings.json file and then provide an implementation of IApiKeyValidator.cs or IBasicAuthenticationValidator.cs:

builder.Services.AddTransient<IApiKeyValidator,CustomApiKeyValidator>();builder.Services.AddTransient<IBasicAuthenticationValidator,CustomBasicAuthenticationValidator>();//...publicclassCustomApiKeyValidator:IApiKeyValidator{publicTask<ApiKeyValidationResult>ValidateAsync(stringapiKey){varresult=apiKeyswitch{"ArAilHVOoL3upX78Cohq"=>ApiKeyValidationResult.Success("User 1"),"DiUU5EqImTYkxPDAxBVS"=>ApiKeyValidationResult.Success("User 2"),
_ =>ApiKeyValidationResult.Fail("Invalid User")};returnTask.FromResult(result);}}publicclassCustomBasicAuthenticationValidator:IBasicAuthenticationValidator{publicTask<BasicAuthenticationValidationResult>ValidateAsync(stringuserName,stringpassword){if(userName==password){varclaims=newList<Claim>(){new(ClaimTypes.Role,"User")};returnTask.FromResult(BasicAuthenticationValidationResult.Success(userName,claims));}returnTask.FromResult(BasicAuthenticationValidationResult.Fail("Invalid user"));}}

Permission-based authorization

The library provides services for adding permission-based authorization to an ASP.NET Core project. Just use the following registration at startup:

// Enable permission-based authorization.builder.Services.AddPermissions<T>();

The AddPermissions extension method requires an implementation of the IPermissionHandler interface, that is responsible to check if the user owns the required permissions:

publicinterfaceIPermissionHandler{Task<bool>IsGrantedAsync(ClaimsPrincipaluser,IEnumerable<string>permissions);}

The library provides the built-in ScopeClaimPermissionHandler class, that checks for permissions reading the default scope claims of the current user (scp or http://schemas.microsoft.com/identity/claims/scope). To use this default handler, we can just write this:

builder.Services.AddScopePermissions();// The line above is equivalent to builder.Services.AddPermissions<ScopeClaimPermissionHandler>();

Based on the scenario, we can provide our own implementation, for example reading different claims or using external services (database, HTTP calls, etc.) to get user permissions.

Then, just use the PermissionAttribute or the RequirePermission extension method:

// In a Controller[Permission("profile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequirePermission("profile")

With the ScopeClaimPermissionHandler mentioned above, the invocation succeeds if the user has a scp or http://schemas.microsoft.com/identity/claims/scope claim that contains the profile value, for example:

"scp": "profile email calendar:read"

It is also possible to explicitly create a policy that requires the one or more permissions:

builder.Services.AddAuthorization(options =>{// Define permissions using a policy.options.AddPolicy("UserProfile", builder =>builder.RequirePermission("profile"));});// ...// In a Controller[Authorize(Policy="UserProfile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequireAuthorization(policyNames:"UserProfile")

Samples

Contribute

The project is constantly evolving. Contributions are welcome. Feel free to file issues and pull requests on the repo and we'll address them as we can.

About

A library to easily integrate Authentication in ASP.NET Core projects.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Simple Authentication for ASP.NET Core

Lint Code BaseCodeQLNugetNugetLicense: MIT

A library to easily integrate Authentication in ASP.NET Core projects. Currently it supports JWT Bearer, API Key and Basic Authentication in both Controller-based and Minimal API projects.

Important

Update from Version 2.x to 3.x Swashbuckle (Swagger) support has been moved out from SimpleAuthentication. If you're using the AddSimpleAuthentication extension method with AddSwaggerGen, now you need to install the SimpleAuthentication.Swashbuckle package.

Installation

The library is available on NuGet. Just search for SimpleAuthenticationTools in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools

Usage video

Take a look to a quick demo showing how to integrate the library:

Simple Authentication for ASP.NET Core

Configuration

Authentication can be totally configured adding an Authentication section in the appsettings.json file:

"Authentication": {
"DefaultScheme": "Bearer", // Optional
"JwtBearer": {
"SchemeName": "Bearer" // Default: Bearer
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
"SecurityKey": "supersecretsecuritykey42!", // Required
"Algorithm": "HS256", // Default: HS256
"Issuers": [ "issuer" ], // Optional
"Audiences": [ "audience" ], // Optional
"ExpirationTime": "01:00:00", // Default: No expiration
"ClockSkew": "00:02:00", // Default: 5 minutes
"EnableJwtBearerService": true // Default: true
},
"ApiKey": {
"SchemeName": "ApiKey", // Default: ApiKey
// You can specify either HeaderName, QueryStringKey or both
"HeaderName": "x-api-key",
"QueryStringKey": "code",
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment this line if you want to validate the API Key against a fixed value.
// Otherwise, you need to register an IApiKeyValidator implementation that will be used
// to validate the API Key.
//"ApiKeyValue": "f1I7S5GXa4wQDgLQWgz0",
"UserName": "ApiUser" // Required if ApiKeyValue is used
},
"Basic": {
"SchemeName": "Basic", // Default: Basic
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment the following lines if you want to validate user name and password
// against fixed values.
// Otherwise, you need to register an IBasicAuthenticationValidator implementation
// that will be used to validate the credentials.
//"UserName": "marco",
//"Password": "P@$$w0rd"
}
}

You can configure only the kind of authentication you want to use, or you can include all of them.

The DefaultScheme attribute is used to specify what kind of authentication must be configured as default. Allowed values are the values of the SchemeName attributes.

Registering authentication at Startup

usingSimpleAuthentication;varbuilder=WebApplication.CreateBuilder(args);// ...// Registers authentication schemes and services using IConfiguration information (see above).builder.Services.AddSimpleAuthentication(builder.Configuration);// ...varapp=builder.Build();//...// The following middlewares aren't strictly necessary in .NET 7.0 or higher, because they are automatically// added when detecting that the corresponding services have been registered. However, you may// need to call them explicitly if the default middlewares configuration is not correct for your// app, for example when you need to use CORS.// Check https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/middleware// for more information.//app.UseAuthentication();//app.UseAuthorization();//...app.Run();

Integrating with Swashbuckle

If you're using Swashbuckle (Swagger) to document your API, you can integrate the authentication configuration with the Swagger documentation. Just search for SimpleAuthenticationTools.Swashbuckle in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools.Swashbuckle

Then, you can use the AddSimpleAuthentication extension method:

builder.Services.AddSwaggerGen(options =>{// ...// Add this line to integrate authentication with Swagger.options.AddSimpleAuthentication(builder.Configuration);});

Integrating with Microsoft.AspNetCore.OpenApi (.NET 9 or later)

Starting from version 9, .NET offer a built-in support for OpenAPI. If you're using the AddOpenApi extension method to provide OpenAPI support, you just need to add the corresponding extension method in its declaration (no extra package required):

builder.Services.AddOpenApi(options =>{// ...// Add this line to integrate authentication with OpenAPI.options.AddSimpleAuthentication(builder.Configuration);});

Important

Known issue Currently, to make the AddSimpleAuthentication extension method work with AddOpenApi, you need to have at least one endpoint that produces a Problem response, for example:

app.MapPost("api/auth/login",()=>{// ...}).ProducesProblem(StatusCodes.Status400BadRequest);

This is a workaround that will be fixed in the next release.

Creating a JWT Bearer

When using JWT Bearer authentication, you can set the EnableJwtBearerService setting to true to automatically register an implementation of the IJwtBearerService interface to create a valid JWT Bearer, according to the setting you have specified in the appsettings.json file:

app.MapPost("api/auth/login",(LoginRequestloginRequest,IJwtBearerServicejwtBearerService)=>{// Check for login rights...// Add custom claims (optional).varclaims=newList<Claim>{new(ClaimTypes.GivenName,"Marco"),new(ClaimTypes.Surname,"Minerva")};vartoken=jwtBearerService.CreateToken(loginRequest.UserName,claims);returnTypedResults.Ok(newLoginResponse(token));});publicrecordclassLoginRequest(stringUserName,stringPassword);publicrecordclassLoginResponse(stringToken);

The IJwtBearerService.CreateToken method allows to specify the issuer and the audience of the token. If you don't specify any value, the first ones defined in appsettings.json will be used.

Supporting multiple API Keys/Basic Authentication credentials

When using API Key or Basic Authentication, you can specify multiple fixed values for authentication:

"Authentication": {
"ApiKey": {
"ApiKeys": [
{
"Value": "key-1",
"UserName": "UserName1"
},
{
"Value": "key-2",
"UserName": "UserName2"
}
]
},
"Basic": {
"Credentials": [
{
"UserName": "UserName1",
"Password": "Password1"
},
{
"UserName": "UserName2",
"Password": "Password2"
}
]
}
}

With this configuration, authentication will succedd if any of these credentials are provided.

Custom Authentication logic for API Keys and Basic Authentication

If you need to implement custom authentication login, for example validating credentials with dynamic values and adding claims to identity, you can omit all the credentials in the appsettings.json file and then provide an implementation of IApiKeyValidator.cs or IBasicAuthenticationValidator.cs:

builder.Services.AddTransient<IApiKeyValidator,CustomApiKeyValidator>();builder.Services.AddTransient<IBasicAuthenticationValidator,CustomBasicAuthenticationValidator>();//...publicclassCustomApiKeyValidator:IApiKeyValidator{publicTask<ApiKeyValidationResult>ValidateAsync(stringapiKey){varresult=apiKeyswitch{"ArAilHVOoL3upX78Cohq"=>ApiKeyValidationResult.Success("User 1"),"DiUU5EqImTYkxPDAxBVS"=>ApiKeyValidationResult.Success("User 2"),
_ =>ApiKeyValidationResult.Fail("Invalid User")};returnTask.FromResult(result);}}publicclassCustomBasicAuthenticationValidator:IBasicAuthenticationValidator{publicTask<BasicAuthenticationValidationResult>ValidateAsync(stringuserName,stringpassword){if(userName==password){varclaims=newList<Claim>(){new(ClaimTypes.Role,"User")};returnTask.FromResult(BasicAuthenticationValidationResult.Success(userName,claims));}returnTask.FromResult(BasicAuthenticationValidationResult.Fail("Invalid user"));}}

Permission-based authorization

The library provides services for adding permission-based authorization to an ASP.NET Core project. Just use the following registration at startup:

// Enable permission-based authorization.builder.Services.AddPermissions<T>();

The AddPermissions extension method requires an implementation of the IPermissionHandler interface, that is responsible to check if the user owns the required permissions:

publicinterfaceIPermissionHandler{Task<bool>IsGrantedAsync(ClaimsPrincipaluser,IEnumerable<string>permissions);}

The library provides the built-in ScopeClaimPermissionHandler class, that checks for permissions reading the default scope claims of the current user (scp or http://schemas.microsoft.com/identity/claims/scope). To use this default handler, we can just write this:

builder.Services.AddScopePermissions();// The line above is equivalent to builder.Services.AddPermissions<ScopeClaimPermissionHandler>();

Based on the scenario, we can provide our own implementation, for example reading different claims or using external services (database, HTTP calls, etc.) to get user permissions.

Then, just use the PermissionAttribute or the RequirePermission extension method:

// In a Controller[Permission("profile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequirePermission("profile")

With the ScopeClaimPermissionHandler mentioned above, the invocation succeeds if the user has a scp or http://schemas.microsoft.com/identity/claims/scope claim that contains the profile value, for example:

"scp": "profile email calendar:read"

It is also possible to explicitly create a policy that requires the one or more permissions:

builder.Services.AddAuthorization(options =>{// Define permissions using a policy.options.AddPolicy("UserProfile", builder =>builder.RequirePermission("profile"));});// ...// In a Controller[Authorize(Policy="UserProfile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequireAuthorization(policyNames:"UserProfile")

Samples

Contribute

The project is constantly evolving. Contributions are welcome. Feel free to file issues and pull requests on the repo and we'll address them as we can.

About

A library to easily integrate Authentication in ASP.NET Core projects.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Simple Authentication for ASP.NET Core

Lint Code BaseCodeQLNugetNugetLicense: MIT

A library to easily integrate Authentication in ASP.NET Core projects. Currently it supports JWT Bearer, API Key and Basic Authentication in both Controller-based and Minimal API projects.

Important

Update from Version 2.x to 3.x Swashbuckle (Swagger) support has been moved out from SimpleAuthentication. If you're using the AddSimpleAuthentication extension method with AddSwaggerGen, now you need to install the SimpleAuthentication.Swashbuckle package.

Installation

The library is available on NuGet. Just search for SimpleAuthenticationTools in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools

Usage video

Take a look to a quick demo showing how to integrate the library:

Simple Authentication for ASP.NET Core

Configuration

Authentication can be totally configured adding an Authentication section in the appsettings.json file:

"Authentication": {
"DefaultScheme": "Bearer", // Optional
"JwtBearer": {
"SchemeName": "Bearer" // Default: Bearer
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
"SecurityKey": "supersecretsecuritykey42!", // Required
"Algorithm": "HS256", // Default: HS256
"Issuers": [ "issuer" ], // Optional
"Audiences": [ "audience" ], // Optional
"ExpirationTime": "01:00:00", // Default: No expiration
"ClockSkew": "00:02:00", // Default: 5 minutes
"EnableJwtBearerService": true // Default: true
},
"ApiKey": {
"SchemeName": "ApiKey", // Default: ApiKey
// You can specify either HeaderName, QueryStringKey or both
"HeaderName": "x-api-key",
"QueryStringKey": "code",
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment this line if you want to validate the API Key against a fixed value.
// Otherwise, you need to register an IApiKeyValidator implementation that will be used
// to validate the API Key.
//"ApiKeyValue": "f1I7S5GXa4wQDgLQWgz0",
"UserName": "ApiUser" // Required if ApiKeyValue is used
},
"Basic": {
"SchemeName": "Basic", // Default: Basic
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment the following lines if you want to validate user name and password
// against fixed values.
// Otherwise, you need to register an IBasicAuthenticationValidator implementation
// that will be used to validate the credentials.
//"UserName": "marco",
//"Password": "P@$$w0rd"
}
}

You can configure only the kind of authentication you want to use, or you can include all of them.

The DefaultScheme attribute is used to specify what kind of authentication must be configured as default. Allowed values are the values of the SchemeName attributes.

Registering authentication at Startup

usingSimpleAuthentication;varbuilder=WebApplication.CreateBuilder(args);// ...// Registers authentication schemes and services using IConfiguration information (see above).builder.Services.AddSimpleAuthentication(builder.Configuration);// ...varapp=builder.Build();//...// The following middlewares aren't strictly necessary in .NET 7.0 or higher, because they are automatically// added when detecting that the corresponding services have been registered. However, you may// need to call them explicitly if the default middlewares configuration is not correct for your// app, for example when you need to use CORS.// Check https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/middleware// for more information.//app.UseAuthentication();//app.UseAuthorization();//...app.Run();

Integrating with Swashbuckle

If you're using Swashbuckle (Swagger) to document your API, you can integrate the authentication configuration with the Swagger documentation. Just search for SimpleAuthenticationTools.Swashbuckle in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools.Swashbuckle

Then, you can use the AddSimpleAuthentication extension method:

builder.Services.AddSwaggerGen(options =>{// ...// Add this line to integrate authentication with Swagger.options.AddSimpleAuthentication(builder.Configuration);});

Integrating with Microsoft.AspNetCore.OpenApi (.NET 9 or later)

Starting from version 9, .NET offer a built-in support for OpenAPI. If you're using the AddOpenApi extension method to provide OpenAPI support, you just need to add the corresponding extension method in its declaration (no extra package required):

builder.Services.AddOpenApi(options =>{// ...// Add this line to integrate authentication with OpenAPI.options.AddSimpleAuthentication(builder.Configuration);});

Important

Known issue Currently, to make the AddSimpleAuthentication extension method work with AddOpenApi, you need to have at least one endpoint that produces a Problem response, for example:

app.MapPost("api/auth/login",()=>{// ...}).ProducesProblem(StatusCodes.Status400BadRequest);

This is a workaround that will be fixed in the next release.

Creating a JWT Bearer

When using JWT Bearer authentication, you can set the EnableJwtBearerService setting to true to automatically register an implementation of the IJwtBearerService interface to create a valid JWT Bearer, according to the setting you have specified in the appsettings.json file:

app.MapPost("api/auth/login",(LoginRequestloginRequest,IJwtBearerServicejwtBearerService)=>{// Check for login rights...// Add custom claims (optional).varclaims=newList<Claim>{new(ClaimTypes.GivenName,"Marco"),new(ClaimTypes.Surname,"Minerva")};vartoken=jwtBearerService.CreateToken(loginRequest.UserName,claims);returnTypedResults.Ok(newLoginResponse(token));});publicrecordclassLoginRequest(stringUserName,stringPassword);publicrecordclassLoginResponse(stringToken);

The IJwtBearerService.CreateToken method allows to specify the issuer and the audience of the token. If you don't specify any value, the first ones defined in appsettings.json will be used.

Supporting multiple API Keys/Basic Authentication credentials

When using API Key or Basic Authentication, you can specify multiple fixed values for authentication:

"Authentication": {
"ApiKey": {
"ApiKeys": [
{
"Value": "key-1",
"UserName": "UserName1"
},
{
"Value": "key-2",
"UserName": "UserName2"
}
]
},
"Basic": {
"Credentials": [
{
"UserName": "UserName1",
"Password": "Password1"
},
{
"UserName": "UserName2",
"Password": "Password2"
}
]
}
}

With this configuration, authentication will succedd if any of these credentials are provided.

Custom Authentication logic for API Keys and Basic Authentication

If you need to implement custom authentication login, for example validating credentials with dynamic values and adding claims to identity, you can omit all the credentials in the appsettings.json file and then provide an implementation of IApiKeyValidator.cs or IBasicAuthenticationValidator.cs:

builder.Services.AddTransient<IApiKeyValidator,CustomApiKeyValidator>();builder.Services.AddTransient<IBasicAuthenticationValidator,CustomBasicAuthenticationValidator>();//...publicclassCustomApiKeyValidator:IApiKeyValidator{publicTask<ApiKeyValidationResult>ValidateAsync(stringapiKey){varresult=apiKeyswitch{"ArAilHVOoL3upX78Cohq"=>ApiKeyValidationResult.Success("User 1"),"DiUU5EqImTYkxPDAxBVS"=>ApiKeyValidationResult.Success("User 2"),
_ =>ApiKeyValidationResult.Fail("Invalid User")};returnTask.FromResult(result);}}publicclassCustomBasicAuthenticationValidator:IBasicAuthenticationValidator{publicTask<BasicAuthenticationValidationResult>ValidateAsync(stringuserName,stringpassword){if(userName==password){varclaims=newList<Claim>(){new(ClaimTypes.Role,"User")};returnTask.FromResult(BasicAuthenticationValidationResult.Success(userName,claims));}returnTask.FromResult(BasicAuthenticationValidationResult.Fail("Invalid user"));}}

Permission-based authorization

The library provides services for adding permission-based authorization to an ASP.NET Core project. Just use the following registration at startup:

// Enable permission-based authorization.builder.Services.AddPermissions<T>();

The AddPermissions extension method requires an implementation of the IPermissionHandler interface, that is responsible to check if the user owns the required permissions:

publicinterfaceIPermissionHandler{Task<bool>IsGrantedAsync(ClaimsPrincipaluser,IEnumerable<string>permissions);}

The library provides the built-in ScopeClaimPermissionHandler class, that checks for permissions reading the default scope claims of the current user (scp or http://schemas.microsoft.com/identity/claims/scope). To use this default handler, we can just write this:

builder.Services.AddScopePermissions();// The line above is equivalent to builder.Services.AddPermissions<ScopeClaimPermissionHandler>();

Based on the scenario, we can provide our own implementation, for example reading different claims or using external services (database, HTTP calls, etc.) to get user permissions.

Then, just use the PermissionAttribute or the RequirePermission extension method:

// In a Controller[Permission("profile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequirePermission("profile")

With the ScopeClaimPermissionHandler mentioned above, the invocation succeeds if the user has a scp or http://schemas.microsoft.com/identity/claims/scope claim that contains the profile value, for example:

"scp": "profile email calendar:read"

It is also possible to explicitly create a policy that requires the one or more permissions:

builder.Services.AddAuthorization(options =>{// Define permissions using a policy.options.AddPolicy("UserProfile", builder =>builder.RequirePermission("profile"));});// ...// In a Controller[Authorize(Policy="UserProfile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequireAuthorization(policyNames:"UserProfile")

Samples

Contribute

The project is constantly evolving. Contributions are welcome. Feel free to file issues and pull requests on the repo and we'll address them as we can.

About

A library to easily integrate Authentication in ASP.NET Core projects.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Simple Authentication for ASP.NET Core

Lint Code BaseCodeQLNugetNugetLicense: MIT

A library to easily integrate Authentication in ASP.NET Core projects. Currently it supports JWT Bearer, API Key and Basic Authentication in both Controller-based and Minimal API projects.

Important

Update from Version 2.x to 3.x Swashbuckle (Swagger) support has been moved out from SimpleAuthentication. If you're using the AddSimpleAuthentication extension method with AddSwaggerGen, now you need to install the SimpleAuthentication.Swashbuckle package.

Installation

The library is available on NuGet. Just search for SimpleAuthenticationTools in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools

Usage video

Take a look to a quick demo showing how to integrate the library:

Simple Authentication for ASP.NET Core

Configuration

Authentication can be totally configured adding an Authentication section in the appsettings.json file:

"Authentication": {
"DefaultScheme": "Bearer", // Optional
"JwtBearer": {
"SchemeName": "Bearer" // Default: Bearer
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
"SecurityKey": "supersecretsecuritykey42!", // Required
"Algorithm": "HS256", // Default: HS256
"Issuers": [ "issuer" ], // Optional
"Audiences": [ "audience" ], // Optional
"ExpirationTime": "01:00:00", // Default: No expiration
"ClockSkew": "00:02:00", // Default: 5 minutes
"EnableJwtBearerService": true // Default: true
},
"ApiKey": {
"SchemeName": "ApiKey", // Default: ApiKey
// You can specify either HeaderName, QueryStringKey or both
"HeaderName": "x-api-key",
"QueryStringKey": "code",
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment this line if you want to validate the API Key against a fixed value.
// Otherwise, you need to register an IApiKeyValidator implementation that will be used
// to validate the API Key.
//"ApiKeyValue": "f1I7S5GXa4wQDgLQWgz0",
"UserName": "ApiUser" // Required if ApiKeyValue is used
},
"Basic": {
"SchemeName": "Basic", // Default: Basic
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment the following lines if you want to validate user name and password
// against fixed values.
// Otherwise, you need to register an IBasicAuthenticationValidator implementation
// that will be used to validate the credentials.
//"UserName": "marco",
//"Password": "P@$$w0rd"
}
}

You can configure only the kind of authentication you want to use, or you can include all of them.

The DefaultScheme attribute is used to specify what kind of authentication must be configured as default. Allowed values are the values of the SchemeName attributes.

Registering authentication at Startup

usingSimpleAuthentication;varbuilder=WebApplication.CreateBuilder(args);// ...// Registers authentication schemes and services using IConfiguration information (see above).builder.Services.AddSimpleAuthentication(builder.Configuration);// ...varapp=builder.Build();//...// The following middlewares aren't strictly necessary in .NET 7.0 or higher, because they are automatically// added when detecting that the corresponding services have been registered. However, you may// need to call them explicitly if the default middlewares configuration is not correct for your// app, for example when you need to use CORS.// Check https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/middleware// for more information.//app.UseAuthentication();//app.UseAuthorization();//...app.Run();

Integrating with Swashbuckle

If you're using Swashbuckle (Swagger) to document your API, you can integrate the authentication configuration with the Swagger documentation. Just search for SimpleAuthenticationTools.Swashbuckle in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools.Swashbuckle

Then, you can use the AddSimpleAuthentication extension method:

builder.Services.AddSwaggerGen(options =>{// ...// Add this line to integrate authentication with Swagger.options.AddSimpleAuthentication(builder.Configuration);});

Integrating with Microsoft.AspNetCore.OpenApi (.NET 9 or later)

Starting from version 9, .NET offer a built-in support for OpenAPI. If you're using the AddOpenApi extension method to provide OpenAPI support, you just need to add the corresponding extension method in its declaration (no extra package required):

builder.Services.AddOpenApi(options =>{// ...// Add this line to integrate authentication with OpenAPI.options.AddSimpleAuthentication(builder.Configuration);});

Important

Known issue Currently, to make the AddSimpleAuthentication extension method work with AddOpenApi, you need to have at least one endpoint that produces a Problem response, for example:

app.MapPost("api/auth/login",()=>{// ...}).ProducesProblem(StatusCodes.Status400BadRequest);

This is a workaround that will be fixed in the next release.

Creating a JWT Bearer

When using JWT Bearer authentication, you can set the EnableJwtBearerService setting to true to automatically register an implementation of the IJwtBearerService interface to create a valid JWT Bearer, according to the setting you have specified in the appsettings.json file:

app.MapPost("api/auth/login",(LoginRequestloginRequest,IJwtBearerServicejwtBearerService)=>{// Check for login rights...// Add custom claims (optional).varclaims=newList<Claim>{new(ClaimTypes.GivenName,"Marco"),new(ClaimTypes.Surname,"Minerva")};vartoken=jwtBearerService.CreateToken(loginRequest.UserName,claims);returnTypedResults.Ok(newLoginResponse(token));});publicrecordclassLoginRequest(stringUserName,stringPassword);publicrecordclassLoginResponse(stringToken);

The IJwtBearerService.CreateToken method allows to specify the issuer and the audience of the token. If you don't specify any value, the first ones defined in appsettings.json will be used.

Supporting multiple API Keys/Basic Authentication credentials

When using API Key or Basic Authentication, you can specify multiple fixed values for authentication:

"Authentication": {
"ApiKey": {
"ApiKeys": [
{
"Value": "key-1",
"UserName": "UserName1"
},
{
"Value": "key-2",
"UserName": "UserName2"
}
]
},
"Basic": {
"Credentials": [
{
"UserName": "UserName1",
"Password": "Password1"
},
{
"UserName": "UserName2",
"Password": "Password2"
}
]
}
}

With this configuration, authentication will succedd if any of these credentials are provided.

Custom Authentication logic for API Keys and Basic Authentication

If you need to implement custom authentication login, for example validating credentials with dynamic values and adding claims to identity, you can omit all the credentials in the appsettings.json file and then provide an implementation of IApiKeyValidator.cs or IBasicAuthenticationValidator.cs:

builder.Services.AddTransient<IApiKeyValidator,CustomApiKeyValidator>();builder.Services.AddTransient<IBasicAuthenticationValidator,CustomBasicAuthenticationValidator>();//...publicclassCustomApiKeyValidator:IApiKeyValidator{publicTask<ApiKeyValidationResult>ValidateAsync(stringapiKey){varresult=apiKeyswitch{"ArAilHVOoL3upX78Cohq"=>ApiKeyValidationResult.Success("User 1"),"DiUU5EqImTYkxPDAxBVS"=>ApiKeyValidationResult.Success("User 2"),
_ =>ApiKeyValidationResult.Fail("Invalid User")};returnTask.FromResult(result);}}publicclassCustomBasicAuthenticationValidator:IBasicAuthenticationValidator{publicTask<BasicAuthenticationValidationResult>ValidateAsync(stringuserName,stringpassword){if(userName==password){varclaims=newList<Claim>(){new(ClaimTypes.Role,"User")};returnTask.FromResult(BasicAuthenticationValidationResult.Success(userName,claims));}returnTask.FromResult(BasicAuthenticationValidationResult.Fail("Invalid user"));}}

Permission-based authorization

The library provides services for adding permission-based authorization to an ASP.NET Core project. Just use the following registration at startup:

// Enable permission-based authorization.builder.Services.AddPermissions<T>();

The AddPermissions extension method requires an implementation of the IPermissionHandler interface, that is responsible to check if the user owns the required permissions:

publicinterfaceIPermissionHandler{Task<bool>IsGrantedAsync(ClaimsPrincipaluser,IEnumerable<string>permissions);}

The library provides the built-in ScopeClaimPermissionHandler class, that checks for permissions reading the default scope claims of the current user (scp or http://schemas.microsoft.com/identity/claims/scope). To use this default handler, we can just write this:

builder.Services.AddScopePermissions();// The line above is equivalent to builder.Services.AddPermissions<ScopeClaimPermissionHandler>();

Based on the scenario, we can provide our own implementation, for example reading different claims or using external services (database, HTTP calls, etc.) to get user permissions.

Then, just use the PermissionAttribute or the RequirePermission extension method:

// In a Controller[Permission("profile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequirePermission("profile")

With the ScopeClaimPermissionHandler mentioned above, the invocation succeeds if the user has a scp or http://schemas.microsoft.com/identity/claims/scope claim that contains the profile value, for example:

"scp": "profile email calendar:read"

It is also possible to explicitly create a policy that requires the one or more permissions:

builder.Services.AddAuthorization(options =>{// Define permissions using a policy.options.AddPolicy("UserProfile", builder =>builder.RequirePermission("profile"));});// ...// In a Controller[Authorize(Policy="UserProfile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequireAuthorization(policyNames:"UserProfile")

Samples

Contribute

The project is constantly evolving. Contributions are welcome. Feel free to file issues and pull requests on the repo and we'll address them as we can.

About

A library to easily integrate Authentication in ASP.NET Core projects.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Simple Authentication for ASP.NET Core

Lint Code BaseCodeQLNugetNugetLicense: MIT

A library to easily integrate Authentication in ASP.NET Core projects. Currently it supports JWT Bearer, API Key and Basic Authentication in both Controller-based and Minimal API projects.

Important

Update from Version 2.x to 3.x Swashbuckle (Swagger) support has been moved out from SimpleAuthentication. If you're using the AddSimpleAuthentication extension method with AddSwaggerGen, now you need to install the SimpleAuthentication.Swashbuckle package.

Installation

The library is available on NuGet. Just search for SimpleAuthenticationTools in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools

Usage video

Take a look to a quick demo showing how to integrate the library:

Simple Authentication for ASP.NET Core

Configuration

Authentication can be totally configured adding an Authentication section in the appsettings.json file:

"Authentication": {
"DefaultScheme": "Bearer", // Optional
"JwtBearer": {
"SchemeName": "Bearer" // Default: Bearer
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
"SecurityKey": "supersecretsecuritykey42!", // Required
"Algorithm": "HS256", // Default: HS256
"Issuers": [ "issuer" ], // Optional
"Audiences": [ "audience" ], // Optional
"ExpirationTime": "01:00:00", // Default: No expiration
"ClockSkew": "00:02:00", // Default: 5 minutes
"EnableJwtBearerService": true // Default: true
},
"ApiKey": {
"SchemeName": "ApiKey", // Default: ApiKey
// You can specify either HeaderName, QueryStringKey or both
"HeaderName": "x-api-key",
"QueryStringKey": "code",
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment this line if you want to validate the API Key against a fixed value.
// Otherwise, you need to register an IApiKeyValidator implementation that will be used
// to validate the API Key.
//"ApiKeyValue": "f1I7S5GXa4wQDgLQWgz0",
"UserName": "ApiUser" // Required if ApiKeyValue is used
},
"Basic": {
"SchemeName": "Basic", // Default: Basic
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment the following lines if you want to validate user name and password
// against fixed values.
// Otherwise, you need to register an IBasicAuthenticationValidator implementation
// that will be used to validate the credentials.
//"UserName": "marco",
//"Password": "P@$$w0rd"
}
}

You can configure only the kind of authentication you want to use, or you can include all of them.

The DefaultScheme attribute is used to specify what kind of authentication must be configured as default. Allowed values are the values of the SchemeName attributes.

Registering authentication at Startup

usingSimpleAuthentication;varbuilder=WebApplication.CreateBuilder(args);// ...// Registers authentication schemes and services using IConfiguration information (see above).builder.Services.AddSimpleAuthentication(builder.Configuration);// ...varapp=builder.Build();//...// The following middlewares aren't strictly necessary in .NET 7.0 or higher, because they are automatically// added when detecting that the corresponding services have been registered. However, you may// need to call them explicitly if the default middlewares configuration is not correct for your// app, for example when you need to use CORS.// Check https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/middleware// for more information.//app.UseAuthentication();//app.UseAuthorization();//...app.Run();

Integrating with Swashbuckle

If you're using Swashbuckle (Swagger) to document your API, you can integrate the authentication configuration with the Swagger documentation. Just search for SimpleAuthenticationTools.Swashbuckle in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools.Swashbuckle

Then, you can use the AddSimpleAuthentication extension method:

builder.Services.AddSwaggerGen(options =>{// ...// Add this line to integrate authentication with Swagger.options.AddSimpleAuthentication(builder.Configuration);});

Integrating with Microsoft.AspNetCore.OpenApi (.NET 9 or later)

Starting from version 9, .NET offer a built-in support for OpenAPI. If you're using the AddOpenApi extension method to provide OpenAPI support, you just need to add the corresponding extension method in its declaration (no extra package required):

builder.Services.AddOpenApi(options =>{// ...// Add this line to integrate authentication with OpenAPI.options.AddSimpleAuthentication(builder.Configuration);});

Important

Known issue Currently, to make the AddSimpleAuthentication extension method work with AddOpenApi, you need to have at least one endpoint that produces a Problem response, for example:

app.MapPost("api/auth/login",()=>{// ...}).ProducesProblem(StatusCodes.Status400BadRequest);

This is a workaround that will be fixed in the next release.

Creating a JWT Bearer

When using JWT Bearer authentication, you can set the EnableJwtBearerService setting to true to automatically register an implementation of the IJwtBearerService interface to create a valid JWT Bearer, according to the setting you have specified in the appsettings.json file:

app.MapPost("api/auth/login",(LoginRequestloginRequest,IJwtBearerServicejwtBearerService)=>{// Check for login rights...// Add custom claims (optional).varclaims=newList<Claim>{new(ClaimTypes.GivenName,"Marco"),new(ClaimTypes.Surname,"Minerva")};vartoken=jwtBearerService.CreateToken(loginRequest.UserName,claims);returnTypedResults.Ok(newLoginResponse(token));});publicrecordclassLoginRequest(stringUserName,stringPassword);publicrecordclassLoginResponse(stringToken);

The IJwtBearerService.CreateToken method allows to specify the issuer and the audience of the token. If you don't specify any value, the first ones defined in appsettings.json will be used.

Supporting multiple API Keys/Basic Authentication credentials

When using API Key or Basic Authentication, you can specify multiple fixed values for authentication:

"Authentication": {
"ApiKey": {
"ApiKeys": [
{
"Value": "key-1",
"UserName": "UserName1"
},
{
"Value": "key-2",
"UserName": "UserName2"
}
]
},
"Basic": {
"Credentials": [
{
"UserName": "UserName1",
"Password": "Password1"
},
{
"UserName": "UserName2",
"Password": "Password2"
}
]
}
}

With this configuration, authentication will succedd if any of these credentials are provided.

Custom Authentication logic for API Keys and Basic Authentication

If you need to implement custom authentication login, for example validating credentials with dynamic values and adding claims to identity, you can omit all the credentials in the appsettings.json file and then provide an implementation of IApiKeyValidator.cs or IBasicAuthenticationValidator.cs:

builder.Services.AddTransient<IApiKeyValidator,CustomApiKeyValidator>();builder.Services.AddTransient<IBasicAuthenticationValidator,CustomBasicAuthenticationValidator>();//...publicclassCustomApiKeyValidator:IApiKeyValidator{publicTask<ApiKeyValidationResult>ValidateAsync(stringapiKey){varresult=apiKeyswitch{"ArAilHVOoL3upX78Cohq"=>ApiKeyValidationResult.Success("User 1"),"DiUU5EqImTYkxPDAxBVS"=>ApiKeyValidationResult.Success("User 2"),
_ =>ApiKeyValidationResult.Fail("Invalid User")};returnTask.FromResult(result);}}publicclassCustomBasicAuthenticationValidator:IBasicAuthenticationValidator{publicTask<BasicAuthenticationValidationResult>ValidateAsync(stringuserName,stringpassword){if(userName==password){varclaims=newList<Claim>(){new(ClaimTypes.Role,"User")};returnTask.FromResult(BasicAuthenticationValidationResult.Success(userName,claims));}returnTask.FromResult(BasicAuthenticationValidationResult.Fail("Invalid user"));}}

Permission-based authorization

The library provides services for adding permission-based authorization to an ASP.NET Core project. Just use the following registration at startup:

// Enable permission-based authorization.builder.Services.AddPermissions<T>();

The AddPermissions extension method requires an implementation of the IPermissionHandler interface, that is responsible to check if the user owns the required permissions:

publicinterfaceIPermissionHandler{Task<bool>IsGrantedAsync(ClaimsPrincipaluser,IEnumerable<string>permissions);}

The library provides the built-in ScopeClaimPermissionHandler class, that checks for permissions reading the default scope claims of the current user (scp or http://schemas.microsoft.com/identity/claims/scope). To use this default handler, we can just write this:

builder.Services.AddScopePermissions();// The line above is equivalent to builder.Services.AddPermissions<ScopeClaimPermissionHandler>();

Based on the scenario, we can provide our own implementation, for example reading different claims or using external services (database, HTTP calls, etc.) to get user permissions.

Then, just use the PermissionAttribute or the RequirePermission extension method:

// In a Controller[Permission("profile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequirePermission("profile")

With the ScopeClaimPermissionHandler mentioned above, the invocation succeeds if the user has a scp or http://schemas.microsoft.com/identity/claims/scope claim that contains the profile value, for example:

"scp": "profile email calendar:read"

It is also possible to explicitly create a policy that requires the one or more permissions:

builder.Services.AddAuthorization(options =>{// Define permissions using a policy.options.AddPolicy("UserProfile", builder =>builder.RequirePermission("profile"));});// ...// In a Controller[Authorize(Policy="UserProfile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequireAuthorization(policyNames:"UserProfile")

Samples

Contribute

The project is constantly evolving. Contributions are welcome. Feel free to file issues and pull requests on the repo and we'll address them as we can.

About

A library to easily integrate Authentication in ASP.NET Core projects.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Simple Authentication for ASP.NET Core

Lint Code BaseCodeQLNugetNugetLicense: MIT

A library to easily integrate Authentication in ASP.NET Core projects. Currently it supports JWT Bearer, API Key and Basic Authentication in both Controller-based and Minimal API projects.

Important

Update from Version 2.x to 3.x Swashbuckle (Swagger) support has been moved out from SimpleAuthentication. If you're using the AddSimpleAuthentication extension method with AddSwaggerGen, now you need to install the SimpleAuthentication.Swashbuckle package.

Installation

The library is available on NuGet. Just search for SimpleAuthenticationTools in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools

Usage video

Take a look to a quick demo showing how to integrate the library:

Simple Authentication for ASP.NET Core

Configuration

Authentication can be totally configured adding an Authentication section in the appsettings.json file:

"Authentication": {
"DefaultScheme": "Bearer", // Optional
"JwtBearer": {
"SchemeName": "Bearer" // Default: Bearer
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
"SecurityKey": "supersecretsecuritykey42!", // Required
"Algorithm": "HS256", // Default: HS256
"Issuers": [ "issuer" ], // Optional
"Audiences": [ "audience" ], // Optional
"ExpirationTime": "01:00:00", // Default: No expiration
"ClockSkew": "00:02:00", // Default: 5 minutes
"EnableJwtBearerService": true // Default: true
},
"ApiKey": {
"SchemeName": "ApiKey", // Default: ApiKey
// You can specify either HeaderName, QueryStringKey or both
"HeaderName": "x-api-key",
"QueryStringKey": "code",
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment this line if you want to validate the API Key against a fixed value.
// Otherwise, you need to register an IApiKeyValidator implementation that will be used
// to validate the API Key.
//"ApiKeyValue": "f1I7S5GXa4wQDgLQWgz0",
"UserName": "ApiUser" // Required if ApiKeyValue is used
},
"Basic": {
"SchemeName": "Basic", // Default: Basic
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment the following lines if you want to validate user name and password
// against fixed values.
// Otherwise, you need to register an IBasicAuthenticationValidator implementation
// that will be used to validate the credentials.
//"UserName": "marco",
//"Password": "P@$$w0rd"
}
}

You can configure only the kind of authentication you want to use, or you can include all of them.

The DefaultScheme attribute is used to specify what kind of authentication must be configured as default. Allowed values are the values of the SchemeName attributes.

Registering authentication at Startup

usingSimpleAuthentication;varbuilder=WebApplication.CreateBuilder(args);// ...// Registers authentication schemes and services using IConfiguration information (see above).builder.Services.AddSimpleAuthentication(builder.Configuration);// ...varapp=builder.Build();//...// The following middlewares aren't strictly necessary in .NET 7.0 or higher, because they are automatically// added when detecting that the corresponding services have been registered. However, you may// need to call them explicitly if the default middlewares configuration is not correct for your// app, for example when you need to use CORS.// Check https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/middleware// for more information.//app.UseAuthentication();//app.UseAuthorization();//...app.Run();

Integrating with Swashbuckle

If you're using Swashbuckle (Swagger) to document your API, you can integrate the authentication configuration with the Swagger documentation. Just search for SimpleAuthenticationTools.Swashbuckle in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools.Swashbuckle

Then, you can use the AddSimpleAuthentication extension method:

builder.Services.AddSwaggerGen(options =>{// ...// Add this line to integrate authentication with Swagger.options.AddSimpleAuthentication(builder.Configuration);});

Integrating with Microsoft.AspNetCore.OpenApi (.NET 9 or later)

Starting from version 9, .NET offer a built-in support for OpenAPI. If you're using the AddOpenApi extension method to provide OpenAPI support, you just need to add the corresponding extension method in its declaration (no extra package required):

builder.Services.AddOpenApi(options =>{// ...// Add this line to integrate authentication with OpenAPI.options.AddSimpleAuthentication(builder.Configuration);});

Important

Known issue Currently, to make the AddSimpleAuthentication extension method work with AddOpenApi, you need to have at least one endpoint that produces a Problem response, for example:

app.MapPost("api/auth/login",()=>{// ...}).ProducesProblem(StatusCodes.Status400BadRequest);

This is a workaround that will be fixed in the next release.

Creating a JWT Bearer

When using JWT Bearer authentication, you can set the EnableJwtBearerService setting to true to automatically register an implementation of the IJwtBearerService interface to create a valid JWT Bearer, according to the setting you have specified in the appsettings.json file:

app.MapPost("api/auth/login",(LoginRequestloginRequest,IJwtBearerServicejwtBearerService)=>{// Check for login rights...// Add custom claims (optional).varclaims=newList<Claim>{new(ClaimTypes.GivenName,"Marco"),new(ClaimTypes.Surname,"Minerva")};vartoken=jwtBearerService.CreateToken(loginRequest.UserName,claims);returnTypedResults.Ok(newLoginResponse(token));});publicrecordclassLoginRequest(stringUserName,stringPassword);publicrecordclassLoginResponse(stringToken);

The IJwtBearerService.CreateToken method allows to specify the issuer and the audience of the token. If you don't specify any value, the first ones defined in appsettings.json will be used.

Supporting multiple API Keys/Basic Authentication credentials

When using API Key or Basic Authentication, you can specify multiple fixed values for authentication:

"Authentication": {
"ApiKey": {
"ApiKeys": [
{
"Value": "key-1",
"UserName": "UserName1"
},
{
"Value": "key-2",
"UserName": "UserName2"
}
]
},
"Basic": {
"Credentials": [
{
"UserName": "UserName1",
"Password": "Password1"
},
{
"UserName": "UserName2",
"Password": "Password2"
}
]
}
}

With this configuration, authentication will succedd if any of these credentials are provided.

Custom Authentication logic for API Keys and Basic Authentication

If you need to implement custom authentication login, for example validating credentials with dynamic values and adding claims to identity, you can omit all the credentials in the appsettings.json file and then provide an implementation of IApiKeyValidator.cs or IBasicAuthenticationValidator.cs:

builder.Services.AddTransient<IApiKeyValidator,CustomApiKeyValidator>();builder.Services.AddTransient<IBasicAuthenticationValidator,CustomBasicAuthenticationValidator>();//...publicclassCustomApiKeyValidator:IApiKeyValidator{publicTask<ApiKeyValidationResult>ValidateAsync(stringapiKey){varresult=apiKeyswitch{"ArAilHVOoL3upX78Cohq"=>ApiKeyValidationResult.Success("User 1"),"DiUU5EqImTYkxPDAxBVS"=>ApiKeyValidationResult.Success("User 2"),
_ =>ApiKeyValidationResult.Fail("Invalid User")};returnTask.FromResult(result);}}publicclassCustomBasicAuthenticationValidator:IBasicAuthenticationValidator{publicTask<BasicAuthenticationValidationResult>ValidateAsync(stringuserName,stringpassword){if(userName==password){varclaims=newList<Claim>(){new(ClaimTypes.Role,"User")};returnTask.FromResult(BasicAuthenticationValidationResult.Success(userName,claims));}returnTask.FromResult(BasicAuthenticationValidationResult.Fail("Invalid user"));}}

Permission-based authorization

The library provides services for adding permission-based authorization to an ASP.NET Core project. Just use the following registration at startup:

// Enable permission-based authorization.builder.Services.AddPermissions<T>();

The AddPermissions extension method requires an implementation of the IPermissionHandler interface, that is responsible to check if the user owns the required permissions:

publicinterfaceIPermissionHandler{Task<bool>IsGrantedAsync(ClaimsPrincipaluser,IEnumerable<string>permissions);}

The library provides the built-in ScopeClaimPermissionHandler class, that checks for permissions reading the default scope claims of the current user (scp or http://schemas.microsoft.com/identity/claims/scope). To use this default handler, we can just write this:

builder.Services.AddScopePermissions();// The line above is equivalent to builder.Services.AddPermissions<ScopeClaimPermissionHandler>();

Based on the scenario, we can provide our own implementation, for example reading different claims or using external services (database, HTTP calls, etc.) to get user permissions.

Then, just use the PermissionAttribute or the RequirePermission extension method:

// In a Controller[Permission("profile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequirePermission("profile")

With the ScopeClaimPermissionHandler mentioned above, the invocation succeeds if the user has a scp or http://schemas.microsoft.com/identity/claims/scope claim that contains the profile value, for example:

"scp": "profile email calendar:read"

It is also possible to explicitly create a policy that requires the one or more permissions:

builder.Services.AddAuthorization(options =>{// Define permissions using a policy.options.AddPolicy("UserProfile", builder =>builder.RequirePermission("profile"));});// ...// In a Controller[Authorize(Policy="UserProfile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequireAuthorization(policyNames:"UserProfile")

Samples

Contribute

The project is constantly evolving. Contributions are welcome. Feel free to file issues and pull requests on the repo and we'll address them as we can.

About

A library to easily integrate Authentication in ASP.NET Core projects.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Simple Authentication for ASP.NET Core

Lint Code BaseCodeQLNugetNugetLicense: MIT

A library to easily integrate Authentication in ASP.NET Core projects. Currently it supports JWT Bearer, API Key and Basic Authentication in both Controller-based and Minimal API projects.

Important

Update from Version 2.x to 3.x Swashbuckle (Swagger) support has been moved out from SimpleAuthentication. If you're using the AddSimpleAuthentication extension method with AddSwaggerGen, now you need to install the SimpleAuthentication.Swashbuckle package.

Installation

The library is available on NuGet. Just search for SimpleAuthenticationTools in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools

Usage video

Take a look to a quick demo showing how to integrate the library:

Simple Authentication for ASP.NET Core

Configuration

Authentication can be totally configured adding an Authentication section in the appsettings.json file:

"Authentication": {
"DefaultScheme": "Bearer", // Optional
"JwtBearer": {
"SchemeName": "Bearer" // Default: Bearer
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
"SecurityKey": "supersecretsecuritykey42!", // Required
"Algorithm": "HS256", // Default: HS256
"Issuers": [ "issuer" ], // Optional
"Audiences": [ "audience" ], // Optional
"ExpirationTime": "01:00:00", // Default: No expiration
"ClockSkew": "00:02:00", // Default: 5 minutes
"EnableJwtBearerService": true // Default: true
},
"ApiKey": {
"SchemeName": "ApiKey", // Default: ApiKey
// You can specify either HeaderName, QueryStringKey or both
"HeaderName": "x-api-key",
"QueryStringKey": "code",
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment this line if you want to validate the API Key against a fixed value.
// Otherwise, you need to register an IApiKeyValidator implementation that will be used
// to validate the API Key.
//"ApiKeyValue": "f1I7S5GXa4wQDgLQWgz0",
"UserName": "ApiUser" // Required if ApiKeyValue is used
},
"Basic": {
"SchemeName": "Basic", // Default: Basic
//"NameClaimType": "user_name", // Default: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
//"RoleClaimType": "user_role", // Default: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// Uncomment the following lines if you want to validate user name and password
// against fixed values.
// Otherwise, you need to register an IBasicAuthenticationValidator implementation
// that will be used to validate the credentials.
//"UserName": "marco",
//"Password": "P@$$w0rd"
}
}

You can configure only the kind of authentication you want to use, or you can include all of them.

The DefaultScheme attribute is used to specify what kind of authentication must be configured as default. Allowed values are the values of the SchemeName attributes.

Registering authentication at Startup

usingSimpleAuthentication;varbuilder=WebApplication.CreateBuilder(args);// ...// Registers authentication schemes and services using IConfiguration information (see above).builder.Services.AddSimpleAuthentication(builder.Configuration);// ...varapp=builder.Build();//...// The following middlewares aren't strictly necessary in .NET 7.0 or higher, because they are automatically// added when detecting that the corresponding services have been registered. However, you may// need to call them explicitly if the default middlewares configuration is not correct for your// app, for example when you need to use CORS.// Check https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/middleware// for more information.//app.UseAuthentication();//app.UseAuthorization();//...app.Run();

Integrating with Swashbuckle

If you're using Swashbuckle (Swagger) to document your API, you can integrate the authentication configuration with the Swagger documentation. Just search for SimpleAuthenticationTools.Swashbuckle in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package SimpleAuthenticationTools.Swashbuckle

Then, you can use the AddSimpleAuthentication extension method:

builder.Services.AddSwaggerGen(options =>{// ...// Add this line to integrate authentication with Swagger.options.AddSimpleAuthentication(builder.Configuration);});

Integrating with Microsoft.AspNetCore.OpenApi (.NET 9 or later)

Starting from version 9, .NET offer a built-in support for OpenAPI. If you're using the AddOpenApi extension method to provide OpenAPI support, you just need to add the corresponding extension method in its declaration (no extra package required):

builder.Services.AddOpenApi(options =>{// ...// Add this line to integrate authentication with OpenAPI.options.AddSimpleAuthentication(builder.Configuration);});

Important

Known issue Currently, to make the AddSimpleAuthentication extension method work with AddOpenApi, you need to have at least one endpoint that produces a Problem response, for example:

app.MapPost("api/auth/login",()=>{// ...}).ProducesProblem(StatusCodes.Status400BadRequest);

This is a workaround that will be fixed in the next release.

Creating a JWT Bearer

When using JWT Bearer authentication, you can set the EnableJwtBearerService setting to true to automatically register an implementation of the IJwtBearerService interface to create a valid JWT Bearer, according to the setting you have specified in the appsettings.json file:

app.MapPost("api/auth/login",(LoginRequestloginRequest,IJwtBearerServicejwtBearerService)=>{// Check for login rights...// Add custom claims (optional).varclaims=newList<Claim>{new(ClaimTypes.GivenName,"Marco"),new(ClaimTypes.Surname,"Minerva")};vartoken=jwtBearerService.CreateToken(loginRequest.UserName,claims);returnTypedResults.Ok(newLoginResponse(token));});publicrecordclassLoginRequest(stringUserName,stringPassword);publicrecordclassLoginResponse(stringToken);

The IJwtBearerService.CreateToken method allows to specify the issuer and the audience of the token. If you don't specify any value, the first ones defined in appsettings.json will be used.

Supporting multiple API Keys/Basic Authentication credentials

When using API Key or Basic Authentication, you can specify multiple fixed values for authentication:

"Authentication": {
"ApiKey": {
"ApiKeys": [
{
"Value": "key-1",
"UserName": "UserName1"
},
{
"Value": "key-2",
"UserName": "UserName2"
}
]
},
"Basic": {
"Credentials": [
{
"UserName": "UserName1",
"Password": "Password1"
},
{
"UserName": "UserName2",
"Password": "Password2"
}
]
}
}

With this configuration, authentication will succedd if any of these credentials are provided.

Custom Authentication logic for API Keys and Basic Authentication

If you need to implement custom authentication login, for example validating credentials with dynamic values and adding claims to identity, you can omit all the credentials in the appsettings.json file and then provide an implementation of IApiKeyValidator.cs or IBasicAuthenticationValidator.cs:

builder.Services.AddTransient<IApiKeyValidator,CustomApiKeyValidator>();builder.Services.AddTransient<IBasicAuthenticationValidator,CustomBasicAuthenticationValidator>();//...publicclassCustomApiKeyValidator:IApiKeyValidator{publicTask<ApiKeyValidationResult>ValidateAsync(stringapiKey){varresult=apiKeyswitch{"ArAilHVOoL3upX78Cohq"=>ApiKeyValidationResult.Success("User 1"),"DiUU5EqImTYkxPDAxBVS"=>ApiKeyValidationResult.Success("User 2"),
_ =>ApiKeyValidationResult.Fail("Invalid User")};returnTask.FromResult(result);}}publicclassCustomBasicAuthenticationValidator:IBasicAuthenticationValidator{publicTask<BasicAuthenticationValidationResult>ValidateAsync(stringuserName,stringpassword){if(userName==password){varclaims=newList<Claim>(){new(ClaimTypes.Role,"User")};returnTask.FromResult(BasicAuthenticationValidationResult.Success(userName,claims));}returnTask.FromResult(BasicAuthenticationValidationResult.Fail("Invalid user"));}}

Permission-based authorization

The library provides services for adding permission-based authorization to an ASP.NET Core project. Just use the following registration at startup:

// Enable permission-based authorization.builder.Services.AddPermissions<T>();

The AddPermissions extension method requires an implementation of the IPermissionHandler interface, that is responsible to check if the user owns the required permissions:

publicinterfaceIPermissionHandler{Task<bool>IsGrantedAsync(ClaimsPrincipaluser,IEnumerable<string>permissions);}

The library provides the built-in ScopeClaimPermissionHandler class, that checks for permissions reading the default scope claims of the current user (scp or http://schemas.microsoft.com/identity/claims/scope). To use this default handler, we can just write this:

builder.Services.AddScopePermissions();// The line above is equivalent to builder.Services.AddPermissions<ScopeClaimPermissionHandler>();

Based on the scenario, we can provide our own implementation, for example reading different claims or using external services (database, HTTP calls, etc.) to get user permissions.

Then, just use the PermissionAttribute or the RequirePermission extension method:

// In a Controller[Permission("profile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequirePermission("profile")

With the ScopeClaimPermissionHandler mentioned above, the invocation succeeds if the user has a scp or http://schemas.microsoft.com/identity/claims/scope claim that contains the profile value, for example:

"scp": "profile email calendar:read"

It is also possible to explicitly create a policy that requires the one or more permissions:

builder.Services.AddAuthorization(options =>{// Define permissions using a policy.options.AddPolicy("UserProfile", builder =>builder.RequirePermission("profile"));});// ...// In a Controller[Authorize(Policy="UserProfile")]publicActionResult<User>Get()=>newUser(User.Identity!.Name);// In a Minimal APIapp.MapGet("api/me",(ClaimsPrincipaluser)=>{returnTypedResults.Ok(newUser(user.Identity!.Name));}).RequireAuthorization(policyNames:"UserProfile")

Samples

Contribute

The project is constantly evolving. Contributions are welcome. Feel free to file issues and pull requests on the repo and we'll address them as we can.

About

A library to easily integrate Authentication in ASP.NET Core projects.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages