Adding security
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
# Introduction
|
||||
This repo is used to store the collection of standardized security packages for LCU
|
||||
___
|
||||
|
||||
# LCU.Library.Internal.ApiSecurity
|
||||
Currently you can add API Key security to you API using this nuget package
|
||||
The following sample code will run the configuration code and add the required
|
||||
services to the applications service collection on startup
|
||||
```C#
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("v1", new OpenApiInfo
|
||||
{
|
||||
Title = "IntegrationTestApiTwo",
|
||||
Version = "v1"
|
||||
});
|
||||
|
||||
//Add Security Entry Fields In Swagger
|
||||
c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||
{
|
||||
{
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Id = HeaderKeys.ApiKey, // Must match the "AddSecurityDefinition"
|
||||
Type = ReferenceType.SecurityScheme
|
||||
}
|
||||
},
|
||||
new List<string>()
|
||||
}
|
||||
});
|
||||
|
||||
c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||
{
|
||||
{
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Id = HeaderKeys.Client, // Must match the "AddSecurityDefinition"
|
||||
Type = ReferenceType.SecurityScheme
|
||||
}
|
||||
},
|
||||
new List<string>()
|
||||
}
|
||||
});
|
||||
|
||||
c.AddSecurityDefinition(HeaderKeys.ApiKey,
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Description = HeaderKeys.ApiKey,
|
||||
In = ParameterLocation.Header,
|
||||
Name = HeaderKeys.ApiKey,
|
||||
Type = SecuritySchemeType.ApiKey,
|
||||
Scheme = "apikey"
|
||||
});
|
||||
|
||||
c.AddSecurityDefinition(HeaderKeys.Client,
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Description = HeaderKeys.Client,
|
||||
In = ParameterLocation.Header,
|
||||
Name = HeaderKeys.Client,
|
||||
Type = SecuritySchemeType.ApiKey,
|
||||
Scheme = "apikey"
|
||||
});
|
||||
});
|
||||
|
||||
builder.Services.AddApiKeySecurity(builder.Configuration);
|
||||
```
|
||||
|
||||
There are two ways to implement API Key auth in a Web API
|
||||
|
||||
- Attribute: A more precise implementation that will only run the
|
||||
authentication against requests that hit endpoints tagged with the
|
||||
'ApiKey' attribute within your controllers
|
||||
```C#
|
||||
[ApiKey]
|
||||
public async Task<IActionResult> Get()
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
```
|
||||
|
||||
- Middleware: A blanket authentication solution that will authenticate
|
||||
all incoming requests
|
||||
```C#
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseMiddleware<ApiKeyMiddleware>();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
```
|
||||
Extracting the auth logic from the Attribute & Middleware to a service class
|
||||
was explored and is possible but was rolled back to allow for custom logic updates
|
||||
to each respective authentication strategy
|
||||
|
||||
## ApiSecurityConfiguration
|
||||
|
||||
### ApiKeyAuthenticationFailureBehavior [ Default = Error ]
|
||||
Authentication failure behavior enum
|
||||
- Error: Log error on failure, return error to requesting client
|
||||
- Warn: Log warning on failure, process request normally afterwards
|
||||
|
||||
### ExternalApiKeySet [ Default = Null ]
|
||||
Collection of authorized client-key combinations to authenticate
|
||||
incoming requests against
|
||||
|
||||
### InternalApiKeySet [ Default = Null ]
|
||||
Collection of authorized client-key combinations to be added to outbound
|
||||
requests requiring authentication
|
||||
|
||||
### Sample Configuration
|
||||
|
||||
```C#
|
||||
"ApiSecurityConfiguration": {
|
||||
"ApiKeyAuthenticationFailureBehavior": "Warn",
|
||||
"ExternalApiKeySet": {
|
||||
"TestTenantTwo": "TestKeyTwo"
|
||||
},
|
||||
"InternalApiKeySet": {
|
||||
"TestTenantOne": "TestKeyOne"
|
||||
}
|
||||
}
|
||||
```
|
||||
### Azure AD Authentication
|
||||
Open TopDesk ticket in Other Request category. Within ticket, request service account and group creation for each environment such as:
|
||||
Group: temenos_action_handler_qa
|
||||
User: svc_temenosaction_q
|
||||
Also ask that each group be placed into the Groups Organization unit (if this is not requested, the user name and password may inadvertently change).
|
||||
|
||||
In appsettings, add the following AzureAd node
|
||||
```C#
|
||||
"AzureAd": {
|
||||
"Instance": "https://login.microsoftonline.com/",
|
||||
"Domain": "landmarkcu.onmicrosoft.com",
|
||||
"TenantId": "acquireFromDevOps",
|
||||
"CallbackPath": "/signin-oidc",
|
||||
"ClientId": "acquireFromDevOps",
|
||||
"ClientSecret": "acquireFromDevOps",
|
||||
"AzureKeyVaultUrl": "qa-ApiName-kv",
|
||||
"Role": "Api_Name_QA",
|
||||
"AuthenticationUrl": "https://login.microsoftonline.com/landmarkcu.onmicrosoft.com/oauth2/v2.0/token",
|
||||
"Scope": "acquireFromDevOps"
|
||||
}
|
||||
```
|
||||
In Program class, add configurations and services
|
||||
```C#
|
||||
using Azure.Identity;
|
||||
using LCU.Library.Internal.Security.Service;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.Identity.Web;
|
||||
|
||||
var settings = builder.Configuration.GetSection("AzureAd");
|
||||
var clientSecretCredentials = new ClientSecretCredential(
|
||||
settings["TenantId"],
|
||||
settings["ClientId"],
|
||||
settings["ClientSecret"]);
|
||||
builder.Configuration.AddAzureKeyVault(
|
||||
new Uri($"https://{settings["AzureKeyVaultUrl"]}.vault.azure.net/"), clientSecretCredentials);
|
||||
|
||||
configuration.Bind<AzureAdJwtRetrievalConfiguration>(services, "AzureAd");
|
||||
|
||||
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddMicrosoftIdentityWebApi(configuration.GetSection("AzureAd"))
|
||||
.EnableTokenAcquisitionToCallDownstreamApi()
|
||||
.AddInMemoryTokenCaches();
|
||||
|
||||
services.AddScoped<IAzureAdVerificationService, AzureAdVerificationService>();
|
||||
```
|
||||
|
||||
### Adding Policy Authentication from Azure AD Groups
|
||||
|
||||
Here is an example of using the Authentication portion of the library to add Azure AD Group-based authentication to your blazor application, by converting them
|
||||
to policies.
|
||||
|
||||
Program.cs
|
||||
|
||||
```C#
|
||||
services.AddAzureAdGroupPolicyServices(configuration.GetSection("AzureAd"),
|
||||
configuration.GetSection("Security"));
|
||||
```
|
||||
appsettings.json
|
||||
|
||||
```json
|
||||
"AzureAd": {
|
||||
"TenantId": "GET FROM AZURE AD",
|
||||
"ClientId": "GET FROM AZURE AD",
|
||||
"ClientSecret": "GET FROM AZURE AD",
|
||||
"Instance": "https://login.microsoftonline.com/",
|
||||
"Domain": "landmarkcu.onmicrosoft.com",
|
||||
"CallbackPath": "/signin-oidc",
|
||||
"AuthenticationUrl": "https://login.microsoftonline.com/landmarkcu.onmicrosoft.com/oauth2/v2.0/token"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
"Security": {
|
||||
"AccessPolicies": {
|
||||
"Admin": {
|
||||
"Groups": "IT Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user