I want to host identity server 4 on azurewebsites.net https but I am not sure how to find ssl certificate of my someapp.azurewebsites.net sub domain so I can use it as thumbprint? Is that even possible to obtain ssl certificate that is running on your webapp on azurewebsites.net subdomain?
-
Are you wanting to use a certificate to be used for the signing? – aaronR Mar 02 '18 at 21:02
-
Yes for identity server but I didn’t find the way how to get it – sensei Mar 02 '18 at 21:03
2 Answers
Use self-signed certificates. Since Identity Server only uses the certs internally, it doesn't matter that they aren't signed by a trusted CA, you aren't presenting them to others. I store my signing certificates in Azure Key Vault as serialized Secrets. Key Vault is very inexpensive but you have to cache the results, it isn't meant for high traffic.
Remember to enable Managed Service Identity on the website, Function App, or whatever else is retrieving the values, and add those to the Key Vault SAS list with read-access to Secrets.
Powershell: Create Signing Certificate
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)][string]$password = "",
[Parameter(Mandatory=$true)][string]$rootDomain = ""
)
$cwd = Convert-Path .
$sCerFile = "$cwd\token_signing.cer"
$sPfxFile = "$cwd\token_signing.pfx"
$vCerFile = "$cwd\token_validation.cer"
$vPfxFile = "$cwd\token_validation.pfx"
# abort if files exist
if((Test-Path($sPfxFile)) -or (Test-Path($sCerFile)) -or (Test-Path($vPfxFile)) -or (Test-Path($vCerFile)))
{
Write-Warning "Failed, token_signing or token_validation files already exist in current directory."
Exit
}
function Get-NewCert ([string]$name)
{
New-SelfSignedCertificate `
-Subject $rootDomain `
-DnsName $rootDomain `
-FriendlyName $name `
-NotBefore (Get-Date) `
-NotAfter (Get-Date).AddYears(10) `
-CertStoreLocation "cert:CurrentUser\My" `
-KeyAlgorithm RSA `
-KeyLength 4096 `
-HashAlgorithm SHA256 `
-KeyUsage DigitalSignature, KeyEncipherment, DataEncipherment `
-Type Custom,DocumentEncryptionCert `
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1")
}
$securePass = ConvertTo-SecureString -String $password -Force -AsPlainText
# token signing certificate
$cert = Get-NewCert("IdentityServer Token Signing Credentials")
$store = 'Cert:\CurrentUser\My\' + ($cert.ThumbPrint)
Export-PfxCertificate -Cert $store -FilePath $sPfxFile -Password $securePass
Export-Certificate -Cert $store -FilePath $sCerFile
Write-Host "Token-signing thumbprint: " $cert.Thumbprint
# token validation certificate
$cert = Get-NewCert("IdentityServer Token Validation Credentials")
$store = 'Cert:\CurrentUser\My\' + ($cert.ThumbPrint)
Export-PfxCertificate -Cert $store -FilePath $vPfxFile -Password $securePass
Export-Certificate -Cert $store -FilePath $vCerFile
Write-Host "Token-validation thumbprint: " $cert.Thumbprint
Powershell: Upload Certificate to Azure Key Vault
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)][string]$password = "",
[Parameter(Mandatory=$true)][string]$pfxFilename = "",
[Parameter(Mandatory=$true)][string]$keyVaultName = "",
[Parameter(Mandatory=$true)][string]$secretName = ""
)
$cwd = Convert-Path .
$pfxFile = "$cwd\$pfxFilename.pfx"
# abort when file not found
if(!(Test-Path($pfxFile)))
{
Write-Warning "Failed, $pfxFilename.pfx not found $cwd"
Exit
}
# force Azure login, if needed
function CheckLogin
{
$needLogin = $true
Try
{
$content = Get-AzureRmContext
if ($content)
{
$needLogin = ([string]::IsNullOrEmpty($content.Account))
}
}
Catch
{
if ($_ -like "*Login-AzureRmAccount to login*")
{
$needLogin = $true
}
else
{
throw
}
}
if ($needLogin)
{
Login-AzureRmAccount
}
}
CheckLogin
# load the PFX
$flag = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
$coll = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
$coll.Import($pfxFile, $password, $flag)
# export to byte array
$type = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12
$bytes = $coll.Export($type)
# base64 encode
$base64 = [System.Convert]::ToBase64String($bytes)
$value = ConvertTo-SecureString -String $base64 -AsPlainText –Force
# send it to Azure KeyVault
$type = 'application/x-pkcs12'
Set-AzureKeyVaultSecret -VaultName $keyVaultName -Name $secretName -SecretValue $value -ContentType $type
Thread-Safe Key Vault Cache
public class KeyVaultCache
{
private KeyVaultClient _KeyVaultClient = null;
public KeyVaultClient KeyVaultClient
{
get
{
if(_KeyVaultClient is null)
{
var provider = new AzureServiceTokenProvider();
_KeyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(provider.KeyVaultTokenCallback));
}
return _KeyVaultClient;
}
}
private ConcurrentDictionary<string, string> SecretsCache = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public async Task<string> GetCachedSecret(string secretName)
{
if(!SecretsCache.ContainsKey(secretName))
{
var secretBundle = await KeyVaultClient.GetSecretAsync($"{AzureUris.KeyVaultSecrets}{secretName}").ConfigureAwait(false);
SecretsCache.TryAdd(secretName, secretBundle.Value);
}
return SecretsCache.ContainsKey(secretName) ? SecretsCache[secretName] : string.Empty;
}
}
Retreival of Deserialized Certificates
public async Task<X509Certificate2> TokenValidationCertificate() => PfxStringToCert(await cache.GetCachedSecret("x509-token-validation"));
public async Task<X509Certificate2> TokenSigningCertificate() => PfxStringToCert(await cache.GetCachedSecret("x509-token-signing"));
private X509Certificate2 PfxStringToCert(string pfx)
{
var bytes = Convert.FromBase64String(pfx);
var coll = new X509Certificate2Collection();
coll.Import(bytes, null, X509KeyStorageFlags.Exportable);
return coll[0];
}

- 9,572
- 5
- 48
- 64
One way to use a self-signed certificate to use for token signing with IdentityServer4 is to store the certificate with the application under the 'wwwroot' folder.
You can use OpenSSL to generate a self-signed certificate.
openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout example.key -out example.crt -subj "/CN=example.com" -days 3650
Then load the certificate in the 'Startup.cs' class/file.
public void ConfigureServices(IServiceCollection services)
{
.....other code .....
var fileName = Path.Combine(env.WebRootPath, "YOUR_FileName" );
if (!File.Exists(fileName))
{
throw new FileNotFoundException("Signing Certificate is missing!");
}
var cert = new X509Certificate2(fileName, "Your_PassPhrase" );
services.AddIdentityServer().AddSigningCredential(cert)
...other code.....
}

- 1,557
- 2
- 16
- 26
-
-
so you want an SSL cert on the Azure Web app to authenticate your App/domain name? – aaronR Mar 02 '18 at 21:31
-
I want to use default certificate from azure for identityserver authentication. Certificate that is made for azurewebsites.net domain. – sensei Mar 02 '18 at 21:32
-
I do not think you can since we do not have access to that cert. Your best bet is to create a self-signed certificate and use it as I suggested. – aaronR Mar 02 '18 at 21:34
-
A ok but then you need new domain or self signed for your azurewebsites.net domain? – sensei Mar 02 '18 at 21:38
-
-
-
1The domain is irrelevant on token signing and validation certificates. The certificate is only ever used internally by IS4. An SSL cert can be re-used (but not accessed in the way you asked) but technically a signing cert would be set up differently. All my certs and settings like connection strings are in Key Vault and it costs just pennies per month... – McGuireV10 Mar 03 '18 at 11:50