Unverified Commit e20619de authored by Valentin LECERF's avatar Valentin LECERF Committed by GitHub
Browse files

CSP Configuration Trusted Domains from appsettings.json (#724)

* Integration of configurable AzureAd External Provider

* Documentation Updated for AzureAD Provider

* Implementation of Csp for Images

* Configuration for CSP based on appsettings configuration

* merge issue fixed in json

* Added documentation for CSP

* CSP Added in Admin project

* gravatar.com trusted added domain

* URI for default CSP fixed

* Missing trusted domains default added

* added unsafe script to csp + stylesource
parent 4304e9e2
......@@ -441,6 +441,17 @@ In STS project - in `appsettings.json`:
}
```
## CSP - Content Security Policy
- If you want to use favicon or logo not included/hosted on the same place, you need to declare trusted domain where ressources are hosted in appsettings.json.
```
"CspTrustedDomains": [
"google.com",
"mydomain.com"
],
```
## Health checks
- AdminUI, AdminUI Api and STS contain endpoint `health`, which check databases and IdentityServer.
......
namespace Skoruba.IdentityServer4.Admin.Configuration.Constants
using System.Collections.Generic;
namespace Skoruba.IdentityServer4.Admin.Configuration.Constants
{
public class ConfigurationConsts
{
......@@ -23,5 +25,8 @@
public const string AdminAuditLogDbConnectionStringKey = "AdminAuditLogDbConnection";
public const string DataProtectionDbConnectionStringKey = "DataProtectionDbConnection";
public const string CspTrustedDomainsKey = "CspTrustedDomains";
}
}
\ No newline at end of file
......@@ -165,7 +165,8 @@ namespace Skoruba.IdentityServer4.Admin.Helpers
/// Using of Forwarded Headers, Hsts, XXssProtection and Csp
/// </summary>
/// <param name="app"></param>
public static void UseSecurityHeaders(this IApplicationBuilder app)
/// <param name="configuration"></param>
public static void UseSecurityHeaders(this IApplicationBuilder app, IConfiguration configuration)
{
var forwardingOptions = new ForwardedHeadersOptions()
{
......@@ -181,35 +182,49 @@ namespace Skoruba.IdentityServer4.Admin.Helpers
app.UseXContentTypeOptions();
app.UseXfo(options => options.SameOrigin());
app.UseReferrerPolicy(options => options.NoReferrer());
var allowCspUrls = new List<string>
{
"https://fonts.googleapis.com/",
"https://fonts.gstatic.com/"
};
app.UseCsp(options =>
// CSP Configuration to be able to use external resources
var cspTrustedDomains = new List<string>();
configuration.GetSection(ConfigurationConsts.CspTrustedDomainsKey).Bind(cspTrustedDomains);
if (cspTrustedDomains.Any())
{
options.FontSources(configuration =>
app.UseCsp(csp =>
{
configuration.SelfSrc = true;
configuration.CustomSources = allowCspUrls;
});
//TODO: consider remove unsafe sources - currently using for toastr inline scripts in Notification.cshtml
options.ScriptSources(configuration =>
{
configuration.SelfSrc = true;
configuration.UnsafeInlineSrc = true;
configuration.UnsafeEvalSrc = true;
});
options.StyleSources(configuration =>
{
configuration.SelfSrc = true;
configuration.CustomSources = allowCspUrls;
configuration.UnsafeInlineSrc = true;
csp.ImageSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
});
csp.FontSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
});
csp.ScriptSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
options.UnsafeInlineSrc = true;
options.UnsafeEvalSrc = true;
});
csp.StyleSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
options.UnsafeInlineSrc = true;
});
csp.DefaultSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
});
});
});
}
}
/// <summary>
......
......@@ -107,7 +107,7 @@ namespace Skoruba.IdentityServer4.Admin
app.UsePathBase(Configuration.GetValue<string>("BasePath"));
// Add custom security headers
app.UseSecurityHeaders();
app.UseSecurityHeaders(Configuration);
app.UseStaticFiles();
......
{
"ConnectionStrings": {
"ConfigurationDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"PersistedGrantDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"IdentityDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"AdminLogDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"AdminAuditLogDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"DataProtectionDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true"
"ConnectionStrings": {
"ConfigurationDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"PersistedGrantDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"IdentityDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"AdminLogDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"AdminAuditLogDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"DataProtectionDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"SeedConfiguration": {
"ApplySeed": true
},
"DatabaseMigrationsConfiguration": {
"ApplyDatabaseMigrations": true
},
"DatabaseProviderConfiguration": {
"ProviderType": "SqlServer"
},
"AdminConfiguration": {
"PageTitle": "Skoruba IdentityServer4 Admin",
"FaviconUri": "~/favicon.ico",
"IdentityAdminRedirectUri": "https://localhost:44303/signin-oidc",
"IdentityServerBaseUrl": "https://localhost:44310",
"IdentityAdminCookieName": "IdentityServerAdmin",
"IdentityAdminCookieExpiresUtcHours": 12,
"RequireHttpsMetadata": false,
"TokenValidationClaimName": "name",
"TokenValidationClaimRole": "role",
"ClientId": "skoruba_identity_admin",
"ClientSecret": "skoruba_admin_client_secret",
"OidcResponseType": "code",
"Scopes": [
"openid",
"profile",
"email",
"roles"
],
"AdministrationRole": "SkorubaIdentityAdminAdministrator",
"HideUIForMSSqlErrorLogging": false
},
"CspTrustedDomains": [
"fonts.googleapis.com",
"fonts.gstatic.com"
],
"SmtpConfiguration": {
"Host": "",
"Login": "",
"Password": ""
},
"SendGridConfiguration": {
"ApiKey": "",
"SourceEmail": "",
"SourceName": ""
},
"AuditLoggingConfiguration": {
"Source": "IdentityServer.Admin.Web",
"SubjectIdentifierClaim": "sub",
"SubjectNameClaim": "name",
"IncludeFormVariables": false
},
"CultureConfiguration": {
"Cultures": [],
"DefaultCulture": null
},
"BasePath": "",
"IdentityOptions": {
"Password": {
"RequiredLength": 8
},
"SeedConfiguration": {
"ApplySeed": true
"User": {
"RequireUniqueEmail": true
},
"DatabaseMigrationsConfiguration": {
"ApplyDatabaseMigrations": true
},
"DatabaseProviderConfiguration": {
"ProviderType": "SqlServer"
},
"AdminConfiguration": {
"PageTitle": "Skoruba IdentityServer4 Admin",
"FaviconUri": "~/favicon.ico",
"IdentityAdminRedirectUri": "https://localhost:44303/signin-oidc",
"IdentityServerBaseUrl": "https://localhost:44310",
"IdentityAdminCookieName": "IdentityServerAdmin",
"IdentityAdminCookieExpiresUtcHours": 12,
"RequireHttpsMetadata": false,
"TokenValidationClaimName": "name",
"TokenValidationClaimRole": "role",
"ClientId": "skoruba_identity_admin",
"ClientSecret": "skoruba_admin_client_secret",
"OidcResponseType": "code",
"Scopes": [
"openid",
"profile",
"email",
"roles"
],
"AdministrationRole": "SkorubaIdentityAdminAdministrator",
"HideUIForMSSqlErrorLogging": false
},
"SmtpConfiguration": {
"Host": "",
"Login": "",
"Password": ""
},
"SendGridConfiguration": {
"ApiKey": "",
"SourceEmail": "",
"SourceName": ""
},
"AuditLoggingConfiguration": {
"Source": "IdentityServer.Admin.Web",
"SubjectIdentifierClaim": "sub",
"SubjectNameClaim": "name",
"IncludeFormVariables": false
},
"CultureConfiguration": {
"Cultures": [],
"DefaultCulture": null
},
"BasePath": "",
"IdentityOptions": {
"Password": {
"RequiredLength": 8
},
"User": {
"RequireUniqueEmail": true
},
"SignIn": {
"RequireConfirmedAccount": false
}
},
"DataProtectionConfiguration": {
"ProtectKeysWithAzureKeyVault": false
},
"AzureKeyVaultConfiguration": {
"AzureKeyVaultEndpoint": "",
"ClientId": "",
"ClientSecret": "",
"UseClientCredentials": true,
"DataProtectionKeyIdentifier": "",
"ReadConfigurationFromKeyVault": false
"SignIn": {
"RequireConfirmedAccount": false
}
},
"DataProtectionConfiguration": {
"ProtectKeysWithAzureKeyVault": false
},
"AzureKeyVaultConfiguration": {
"AzureKeyVaultEndpoint": "",
"ClientId": "",
"ClientSecret": "",
"UseClientCredentials": true,
"DataProtectionKeyIdentifier": "",
"ReadConfigurationFromKeyVault": false
}
}
\ No newline at end of file
......@@ -19,5 +19,7 @@
public const string RegisterConfigurationKey = "RegisterConfiguration";
public const string AdvancedConfigurationKey = "AdvancedConfiguration";
public const string CspTrustedDomainsKey = "CspTrustedDomains";
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Globalization;
using IdentityServer4.EntityFramework.Storage;
using Microsoft.AspNetCore.Authentication;
......@@ -95,7 +96,8 @@ namespace Skoruba.IdentityServer4.STS.Identity.Helpers
/// Using of Forwarded Headers and Referrer Policy
/// </summary>
/// <param name="app"></param>
public static void UseSecurityHeaders(this IApplicationBuilder app)
/// <param name="configuration"></param>
public static void UseSecurityHeaders(this IApplicationBuilder app, IConfiguration configuration)
{
var forwardingOptions = new ForwardedHeadersOptions()
{
......@@ -108,6 +110,48 @@ namespace Skoruba.IdentityServer4.STS.Identity.Helpers
app.UseForwardedHeaders(forwardingOptions);
app.UseReferrerPolicy(options => options.NoReferrer());
// CSP Configuration to be able to use external resources
var cspTrustedDomains = new List<string>();
configuration.GetSection(ConfigurationConsts.CspTrustedDomainsKey).Bind(cspTrustedDomains);
if (cspTrustedDomains.Any())
{
app.UseCsp(csp =>
{
csp.ImageSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
});
csp.FontSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
});
csp.ScriptSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
});
csp.StyleSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
options.UnsafeInlineSrc = true;
});
csp.DefaultSources(options =>
{
options.SelfSrc = true;
options.CustomSources = cspTrustedDomains;
options.Enabled = true;
});
});
}
}
/// <summary>
......
......@@ -74,7 +74,7 @@ namespace Skoruba.IdentityServer4.STS.Identity
app.UsePathBase(Configuration.GetValue<string>("BasePath"));
// Add custom security headers
app.UseSecurityHeaders();
app.UseSecurityHeaders(Configuration);
app.UseStaticFiles();
UseAuthentication(app);
......
......@@ -4,7 +4,7 @@
@inject IViewLocalizer Localizer
@inject IRootConfiguration RootConfiguration
<div class="welcome-block px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
<h1 class="display-4"><img class="icon" alt="Logo" src="@UrlHelper.Content(RootConfiguration.AdminConfiguration.HomePageLogoUri)"><br />@RootConfiguration.AdminConfiguration.PageTitle</h1>
<h1 class="display-4"><img class="img-fluid" alt="Logo" src="@UrlHelper.Content(RootConfiguration.AdminConfiguration.HomePageLogoUri)"><br />@RootConfiguration.AdminConfiguration.PageTitle</h1>
<p class="lead">@Localizer["SubTitle", RootConfiguration.AdminConfiguration.PageTitle]</p>
</div>
......
{
"ConnectionStrings": {
"ConfigurationDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"PersistedGrantDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"IdentityDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"DataProtectionDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"DatabaseProviderConfiguration": {
"ProviderType": "SqlServer"
},
"CertificateConfiguration": {
"ConnectionStrings": {
"ConfigurationDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"PersistedGrantDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"IdentityDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true",
"DataProtectionDbConnection": "Server=(localdb)\\mssqllocaldb;Database=IdentityServer4Admin;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"DatabaseProviderConfiguration": {
"ProviderType": "SqlServer"
},
"CertificateConfiguration": {
"UseTemporarySigningKeyForDevelopment": true,
"UseTemporarySigningKeyForDevelopment": true,
"CertificateStoreLocation": "LocalMachine",
"CertificateValidOnly": true,
"CertificateStoreLocation": "LocalMachine",
"CertificateValidOnly": true,
"UseSigningCertificateThumbprint": false,
"SigningCertificateThumbprint": "",
"UseSigningCertificateThumbprint": false,
"SigningCertificateThumbprint": "",
"UseSigningCertificatePfxFile": false,
"SigningCertificatePfxFilePath": "",
"SigningCertificatePfxFilePassword": "",
"UseSigningCertificatePfxFile": false,
"SigningCertificatePfxFilePath": "",
"SigningCertificatePfxFilePassword": "",
"UseValidationCertificatePfxFile": false,
"ValidationCertificatePfxFilePath": "",
"ValidationCertificatePfxFilePassword": "",
"UseValidationCertificatePfxFile": false,
"ValidationCertificatePfxFilePath": "",
"ValidationCertificatePfxFilePassword": "",
"UseValidationCertificateThumbprint": false,
"ValidationCertificateThumbprint": "",
"UseValidationCertificateThumbprint": false,
"ValidationCertificateThumbprint": "",
"UseSigningCertificateForAzureKeyVault": false,
"UseValidationCertificateForAzureKeyVault": false
},
"RegisterConfiguration": {
"Enabled": true
},
"UseSigningCertificateForAzureKeyVault": false,
"UseValidationCertificateForAzureKeyVault": false
},
"RegisterConfiguration": {
"Enabled": true
},
"ExternalProvidersConfiguration": {
"UseGitHubProvider": false,
"GitHubClientId": "",
......@@ -45,57 +45,68 @@
"AzureInstance": "",
"AzureAdSecret": "",
"AzureAdCallbackPath": "",
"AzureDomain": ""
"AzureDomain": ""
},
"SmtpConfiguration": {
"Host": "",
"Login": "",
"Password": ""
},
"SendGridConfiguration": {
"ApiKey": "",
"SourceEmail": "",
"SourceName": ""
},
"LoginConfiguration": {
"ResolutionPolicy": "Username"
},
"AdminConfiguration": {
"PageTitle": "Skoruba IdentityServer4",
"HomePageLogoUri": "~/images/skoruba-icon.png",
"FaviconUri": "~/favicon.ico",
"IdentityAdminBaseUrl": "https://localhost:44303",
"AdministrationRole": "SkorubaIdentityAdminAdministrator"
},
"CultureConfiguration": {
"Cultures": [],
"DefaultCulture": null
},
"AdvancedConfiguration": {
"PublicOrigin": ""
},
"BasePath": "",
"IdentityOptions": {
"Password": {
"RequiredLength": 8
},
"User": {
"RequireUniqueEmail": true
},
"SignIn": {
"RequireConfirmedAccount": false
}
"SmtpConfiguration": {
"Host": "",
"Login": "",
"Password": ""
},
"SendGridConfiguration": {
"ApiKey": "",
"SourceEmail": "",
"SourceName": ""
},
"LoginConfiguration": {
"ResolutionPolicy": "Username"
},
"AdminConfiguration": {
"PageTitle": "Skoruba IdentityServer4",
"HomePageLogoUri": "~/images/skoruba-icon.png",
"FaviconUri": "~/favicon.ico",
"IdentityAdminBaseUrl": "https://localhost:44303",
"AdministrationRole": "SkorubaIdentityAdminAdministrator"
},
"CspTrustedDomains": [
"www.gravatar.com",
"fonts.googleapis.com",
"fonts.gstatic.com"
],
"CultureConfiguration": {
"Cultures": [],
"DefaultCulture": null
},
"AdvancedConfiguration": {
"PublicOrigin": ""
},
"BasePath": "",
"IdentityOptions": {
"Password": {
"RequiredLength": 8
},
"DataProtectionConfiguration": {
"ProtectKeysWithAzureKeyVault": false
"User": {
"RequireUniqueEmail": true
},
"AzureKeyVaultConfiguration": {
"AzureKeyVaultEndpoint": "",
"ClientId": "",
"ClientSecret": "",
"UseClientCredentials": true,
"IdentityServerCertificateName": "",
"DataProtectionKeyIdentifier": "",
"ReadConfigurationFromKeyVault": false
"SignIn": {
"RequireConfirmedAccount": false
}
},
"User": {
"RequireUniqueEmail": true
},
"SignIn": {
"RequireConfirmedAccount": false
},
"DataProtectionConfiguration": {
"ProtectKeysWithAzureKeyVault": false
},
"AzureKeyVaultConfiguration": {
"AzureKeyVaultEndpoint": "",
"ClientId": "",
"ClientSecret": "",
"UseClientCredentials": true,
"IdentityServerCertificateName": "",
"DataProtectionKeyIdentifier": "",
"ReadConfigurationFromKeyVault": false
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment