Duende.IdentityServer.Admin
Duende.IdentityServer.Admin copied to clipboard
Adding Consumer in Project Causes SSL Partial Chain Failure
Question
Using Docker. Admin works with certificates installed.
When adding a consumer to the project, we get a "SSL Partial Chain Error". identity provider base url is set to "https://sts.skoruba.local".
As mentioned, admin can be logged into.
I got past this doing a number of steps:
Found this article on stackoverflow that clued me in on what was going on. Went through the sts code and found the following 2 events:
- OnRedirectToIdentityProvider
- OnRedirectToIdentityProviderForSignOut
added those in.
.AddOpenIdConnect("oidc", options =>
{
options.Authority = identityOptions.OpenId.Authority;
options.ClientId = identityOptions.OpenId.ClientId;
options.ClientSecret = identityOptions.OpenId.ClientSecret;
options.ResponseType = identityOptions.OpenId.ResponseType;
options.SaveTokens = identityOptions.OpenId.SaveTokens;
options.RequireHttpsMetadata = identityOptions.OpenId.RequireHttpsMetadata;
options.GetClaimsFromUserInfoEndpoint = true;
// https://github.com/AzureAD/microsoft-identity-web/issues/115#issuecomment-618984571
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = context => OnRedirectToIdentityProvider(context, identityOptions),
OnRedirectToIdentityProviderForSignOut = context => OnRedirectForSignOut(context, identityOptions)
};
});
/// ...
static Task OnRedirectToIdentityProvider(RedirectContext context, IdentityServerOptions adminConfiguration)
{
if (!string.IsNullOrEmpty(adminConfiguration.OpenId.SignInRedirectUri))
{
var fullUri = $"https://{context.HttpContext.Request.Host}{adminConfiguration.OpenId.SignInRedirectUri}";
context.ProtocolMessage.RedirectUri = fullUri;
}
return Task.CompletedTask;
}
static Task OnRedirectForSignOut(RedirectContext context, IdentityServerOptions adminConfiguration)
{
if (!string.IsNullOrEmpty(adminConfiguration.OpenId.SignOutRedirectUri))
{
var fullUri = $"https://{context.HttpContext.Request.Host}{adminConfiguration.OpenId.SignOutRedirectUri}";
context.ProtocolMessage.PostLogoutRedirectUri = fullUri;
}
return Task.CompletedTask;
}
Also had to go source the DockerHelper code to import the ca cert
public class DockerHelpers
{
public static void UpdateCaCertificates()
{
"update-ca-certificates".Bash();
}
public static void ApplyDockerConfiguration(IConfiguration configuration)
{
DockerConfiguration dockerConfiguration = configuration.GetSection("DockerConfiguration").Get<DockerConfiguration>();
if (dockerConfiguration != null && dockerConfiguration.UpdateCaCertificate)
{
UpdateCaCertificates();
}
}
}
Also had to be sure that the certs were the certs generated by mkcert and were mapped via volumes.
pakilti.identityserver.customer.admin:
image: ${DOCKER_REGISTRY-}pakiltiidentityservercustomeradmin
build:
context: .
dockerfile: src/Pakilti.IdentityServer.Customer.Admin/Dockerfile
environment:
- VIRTUAL_HOST=customer-admin.skoruba.local
- DockerConfiguration__UpdateCaCertificate=true
container_name: pakilti-identity-server-customer-admin
volumes:
- './shared/nginx/certs/cacerts.crt:/usr/local/share/ca-certificates/cacerts.crt'
networks:
identityserverui:
aliases:
- customer-admin.skoruba.local
New problem though:
warn: Microsoft.AspNetCore.Http.ResponseCookies[1]
The cookie '.AspNetCore.OpenIdConnect.Nonce.CfDJ8Ev4r73UydVDoDKIdodzhZzaMQzXuSYN7LxmRWFmWKzvUqeBmkeCYmynh32jRw-9I8ZKzBJm4WahAP-jDHPFnBCHyubvXjzpyix1yujzklhOR3dTiH9N_euhDD1GeyF4CjD_xn1HdylMj2S-rD-7qjNRsUxtOWXIZX6czvqbM5MTyxJzQMiakG5uMx_oCNfpFCNdvb2GnxSZmnnhHluPL2u4tjeNJn-jEDTAS15lwE1KhxhysyMJUXBQH0TZ2unQAH5yEo_Cg738SgoyHoXBEPI' has set 'SameSite=None' and must also set 'Secure'.
warn: Microsoft.AspNetCore.Http.ResponseCookies[1]
The cookie '.AspNetCore.Correlation.Vumn2KQaKvh3Pk48WKw8hgGVDL7wL2jpMcfoyZS2oYc' has set 'SameSite=None' and must also set 'Secure'.
warn: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[15]
'.AspNetCore.Correlation.Vumn2KQaKvh3Pk48WKw8hgGVDL7wL2jpMcfoyZS2oYc' cookie not found.
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.Exception: An error was encountered while handling the remote login.
---> System.Exception: Correlation failed.
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
even after importing the authentication helpers for cookies.
builder.Services.Configure<CookiePolicyOptions>(options =>
{
//options.Secure = CookieSecurePolicy.Always;
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.Secure = CookieSecurePolicy.SameAsRequest;
options.OnAppendCookie = cookieContext =>
AuthenticationHelpers.CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
AuthenticationHelpers.CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
They seriously make working in a container almost impossible....
What did I miss @skoruba ?
I resolved this by implementing the docker helpers in my own code and also setting the OpenID stuff appropriately.
builder.Services.Configure<CookiePolicyOptions>(options =>
{
//options.Secure = CookieSecurePolicy.Always;
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.Secure = CookieSecurePolicy.Always;
options.OnAppendCookie = cookieContext =>
AuthenticationHelpers.CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
AuthenticationHelpers.CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
var identityOptions = builder.Configuration.GetSection("IdentityServer").Get<IdentityServerOptions>();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = AuthenticationConsts.OidcAuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultForbidScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => {
options.Cookie.Name = identityOptions.CookieName;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
})
//.AddJwtBearer(options => {
// options.Authority = identityOptions.OpenId.Authority;
// options.RequireHttpsMetadata = identityOptions.OpenId.RequireHttpsMetadata;
// options.Audience = "pakilticustomeradmin";
//});
.AddOpenIdConnect(AuthenticationConsts.OidcAuthenticationScheme, options =>
{
options.Authority = identityOptions.OpenId.Authority;
options.ClientId = identityOptions.OpenId.ClientId;
options.ClientSecret = identityOptions.OpenId.ClientSecret;
options.ResponseType = identityOptions.OpenId.ResponseType;
options.RequireHttpsMetadata = identityOptions.OpenId.RequireHttpsMetadata;
options.NonceCookie.SecurePolicy = CookieSecurePolicy.Always;
options.CorrelationCookie.SecurePolicy = CookieSecurePolicy.Always;
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Scope.Clear();
foreach (var scope in identityOptions.OpenId.Scopes)
{
options.Scope.Add(scope);
}
options.ClaimActions.MapJsonKey(identityOptions.OpenId.TokenValidationClaimRole, identityOptions.OpenId.TokenValidationClaimRole, identityOptions.OpenId.TokenValidationClaimRole);
options.SaveTokens = identityOptions.OpenId.SaveTokens;
options.GetClaimsFromUserInfoEndpoint = true;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = identityOptions.OpenId.TokenValidationClaimName,
RoleClaimType = identityOptions.OpenId.TokenValidationClaimRole
};
// https://github.com/AzureAD/microsoft-identity-web/issues/115#issuecomment-618984571
options.Events = new OpenIdConnectEvents
{
OnMessageReceived = context => OnMessageReceived(context, identityOptions),
OnRedirectToIdentityProvider = context => OnRedirectToIdentityProvider(context, identityOptions),
OnRedirectToIdentityProviderForSignOut = context => OnRedirectForSignOut(context, identityOptions)
};
});
builder.Services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy.
options.FallbackPolicy = options.DefaultPolicy;
});
DockerHelpers.ApplyDockerConfiguration(builder.Configuration);
var app = builder.Build();
app.UseForwardedHeaders();