Moving your local Single-Sign-On (SSO) solution onto production can be scary, but with this essential configuration, you will be on the right track.
This article follows on from my previous SSO quick start article, to get a solution using the template running on your local machine.
Below are the tasks we recommend you complete to deploy to production successfully.
Identity Server Sample
1. Update The Version
It is good practice to use the latest version of IdentityServer, so make sure you have updated your solution to the latest version. Don’t forget to check also the version compatibility with AdminUI.
The packages to update are:
- Duende.IdentityServe
- Duende.IdentityServer.AspNetIdentity
- Duende.IdentityServer.EntityFramework
2. Add An IdentityServer Production License
Add your Identity Server Duende license key for production. Set the "LicenseKey" property in the appsettings.json file.
3. Remove “isDemo” Code
The Demo logic of the sample contains a couple of fake classes that relax some security logic to make it easier to run IdentityServer locally, but they must not go into production. These fake classes remove the CORS policy and redirect URI validation.
The good news is that IdentityServer already implements CORS policy and URI validation by default, so you need to stop using the code under the “IsDemo” flag.
There are two ways of tackling this:
- The recommended way is to remove all the references in the code. You will find references to “IsDemo” in Program.cs and StartUp.cs. Remove the “IsDemo” property and the if statements dependent on it with the code inside curly brackets.
- The quickest way is to set “IsDemo” to false in appsettings file.
4. Remove Non-HTTPS Code
HTTPS encrypts requests and responses from end to end. If you communicate with your IdentityServer in plain HTTP, any attacker intercepting the message could read it. Therefore, the HTTP code is intended only for demos as it is unsafe.
Once more, there are two ways of solving this:
- Again, the recommended way is to remove the references to that setting in Startup.cs.
Update these lines:
services.Configure<CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme, options =>
{
options.Cookie.SameSite = IsHttps ? SameSiteMode.None : SameSiteMode.Lax;
options.Cookie.SecurePolicy = IsHttps ? CookieSecurePolicy.SameAsRequest : CookieSecurePolicy.None;
options.Cookie.IsEssential = true;
});
With these:
services.Configure<CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme, options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy =CookieSecurePolicy.SameAsRequest;
options.Cookie.IsEssential = true;
});
And remove these:
if (!IsHttps)
{
services.ConfigureApplicationCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.SecurePolicy = CookieSecurePolicy.None;
options.Cookie.IsEssential = true;
});
services.ConfigureExternalCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.SecurePolicy = CookieSecurePolicy.None;
options.Cookie.IsEssential = true;
});
}
- The quickest way is to set that "IsHttps" to true.
5. Add Automatic Key Management
IdentityServer uses keys to sign tokens. For security, these keys should change regularly, which you must also configure. The sample comes with a test certificate to sign IdentityServer keys. As this sample is publicly accessible, you must add a new certificate that you have to create or if you have a Duende Business or Enterprise use automatic key rotation. For Automatic key rotation you only have to replace this line of code in Startup.cs:
.AddSigningCredential(GetEmbeddedCertificate())
With this:
.AddKeyManagement()
After that, you can do extra cleaning, removing the “GetEmbeddedCertificate” method and the certificate.
6. Add Data Protection
Data Protection is an ASP.NET Core feature that is used to encrypt stored data, so if an attacker gets access to your database, they won’t be able to understand the data because they will still need the keys from Data Protection to decrypt it.
IdentityServer relies on this feature, so you must add it in your Startup.cs:
services.AddDataProtection()
After that, you must configure where to store the Data Protection keys. Don’t store the Data Protection keys using the same credentials as the keys themselves. Use alternative storage such as Azure KeyVault.
Also, you must configure how to protect the keys and assign an application name specific to your IdentityServer.
You can find more information here:
7. Other Features To Consider
The sample includes a couple of extra features that you can configure or remove from the sample. These are:
- Google authentication
// optional Google authentication
var googleClientId = Configuration.GetValue<string>("Google_ClientId");
var googleClientSecret = Configuration.GetValue<string>("Google_ClientSecret");
if (!string.IsNullOrWhiteSpace(googleClientId) && !string.IsNullOrWhiteSpace(googleClientSecret))
{
services
.AddAuthentication()
.AddGoogle(options =>
{
options.SignInScheme = "Identity.External"; // ASP.NET Core Identity Extneral User Cookie
options.ClientId = googleClientId; // ClientId Configured within Google Admin
options.ClientSecret = googleClientSecret; // ClientSecret Generated within Google Admin
});
}
- Dynamic Providers (including the extension for SAML Dynamic Providers)
// Configure Dynamic Authentication
var dynamicAuthMode = Configuration.GetValue<string>("DynamicAuth:Mode");
switch (dynamicAuthMode)
{
case "Duende":
idsBuilder.AddSamlDynamicProvider(options =>
{
options.Licensee = Configuration.GetValue<string>("DynamicAuth:SamlLicensee");
options.LicenseKey = Configuration.GetValue<string>("DynamicAuth:SamlLicenseKey");
// Uncommenting these lines will overwrite at runtime the SignInScheme
// and SignOutScheme configured on any Saml Dynamic Authentication
// options.SignInScheme = "Identity.External";
// options.SignOutScheme = "Identity.External";
})
.AddIdentityProviderStore<SamlIdentityProviderStore>();
break;
case "Rsk":
services.AddDynamicProviders(options =>
{
// Component setup
options.Licensee = Configuration.GetValue<string>("DynamicAuth:RskComponentLicensee");
options.LicenseKey = Configuration.GetValue<string>("DynamicAuth:RskComponentLicenseKey");
})
.AddEntityFrameworkStore(options => options.UseSqlServer(identityServerConnectionString))
.AddOpenIdConnect()
.AddSaml(o =>
{
o.Licensee = Configuration.GetValue<string>("DynamicAuth:SamlLicensee");
o.LicenseKey = Configuration.GetValue<string>("DynamicAuth:SamlLicenseKey");
});
break;
}
Remove the relevant code from Startup.cs and related NuGet packages if you don't want any of them.
8. Change Your Database Connections
Update the connections to the production databases. There are three database connections to set:
- IdentityConnectionString
- IdentityServerConnectionString
- AuditConnectionString
IdentityServer and Audit connection strings default to the IdentityServer connection string if you leave them empty.
Remember that it is recommended to set Data Protection in a different database (if you have configured persistence to the database).
AdminUI Sample
1. Update The Version
It is good practice to use the latest version of AdminUI, so make sure you have updated your solution to the latest version. Don’t forget to check also the version compatibility with IdentityServer.
The package to update is:
- Rsk.AdminUI
2. Add An AdminUI Production License
If you still do not have a production license, you can get one from here.
3. Set A Secure Client Secret
AdminUI frontend authenticates with IdentityServer using Authorization Code + PKCE. To set up this connection, a Client Secret is needed. If you have not changed anything on the appsettings file, this secret will be “dev”. You must change and secure that string to be unguessable and unreachable by attackers. A common way of securing this secret is storing it in a key vault outside the appsettings file. file.
4. Set Data Protection
In AdminUI, Data Protection encrypts the end cookie that holds all user tokens and claims, so it is necessary to configure it for production.
The configuration should be different, especially the “protection” credentials; the “persistence” could technically be the same, but it is recommended to store them separately.
You don’t need to add Data Protection programmatically (like in IdentityServer); there are already settings in AdminUI for that.
5. Change Your Database Connections
Update the connections to the production databases. There are four database connections to set:
- IdentityConnectionString
- IdentityServerConnectionString
- AuditConnectionString
- DataProtectionConnectionString
If you leave them empty, the Audit and Data Protection connections will default to the IdentityServer connection string. It is recommended to set Data Protection in a different database (if you have configured persistence to the database).
6. Bootstrap Consideration
For AdminUI to run the user and IdentityServer configuration database needs to be initialised with some seed data. For example AdminUI Client and a default AdminUI admin user. AdminUI has the tool to populate your database with this data automatically.
If you have multiple instances of AdminUI, you need to disable bootstrap from the appsettings file to avoid conflicts:
“DisableBootstrap”: true
However, you must ensure the bootstrap runs once on your production database. You can do so from the command line:
dotnet IdentityExpress.Manager.UI.dll -bootstrap
However, you can also run only specific migrations if you want to.
8. Replace The Default AdminUI User
AdminUI adds a default user to the database when running the bootstrap process. Before making your solution available on the internet, you replace these credentials. To do that, you only need to log in to AdminUI using the credentials (you can do it by running the solution locally but pointing to the production database):
- Username: [email protected]
- Password: Password123!
After logging in, you will get prompted with a page to replace the credentials with your desired ones.
What Next
After following these steps, you now have a safer solution to prepare to push into your production environment. However, you can do more to have a safer production environment. The related articles below will give you some great tools to increase the resilience of your setup.
Need support in creating a production-ready solution or review your current one? Or do you need an expert partner to build a solution for you? Look no further! Our team of experienced professionals is here to help you every step of the way. We're committed to providing you with the best possible service. To get started, email us at [email protected] or check out our services section to learn more.