Hi,
We need the IdentityService4 to use a specific fuction certificate and this is what we have manage so far :
Program
`
public class Program
{
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var Port = config["Port"];
var Identity = config["Identity"];
var Address = config["Address"];
Console.Title = $"{Identity} {Port}";
var host = new WebHostBuilder()
.UseKestrel()
.UseUrls($"https://{Address}:{Port}")
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
**Startup**
public Startup(IHostingEnvironment env)
{
Configuration = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.Build();
_devMode = Convert.ToBoolean(Configuration["dev"]);
}
private X509Certificate2 SetupFuctionCertificate()
{
//returning correct certificate from the store
}
public void ConfigureServices(IServiceCollection services)
{
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
var identitySqlConnection = Configuration.GetConnectionString("IdentityServer");
services.AddConsul(options => options
.SetAgentUris(Configuration["ConsulUri"])
);
services.AddDbContext<OrbitContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
var certificate = SetupFuctionCertificate();
if (_devMode)
{
services.AddDeveloperIdentityServer()
.SetSigningCredential(certificate)
.AddInMemoryClients(Config.GetClients())
.AddInMemoryScopes(Config.GetScopes())
.AddInMemoryStores();
}
else
{
services.AddIdentityServer()
.SetSigningCredential(certificate)
.AddInMemoryClients(Config.GetClients())
.AddInMemoryScopes(Config.GetScopes())
.AddOperationalStore(builder =>
builder.UseSqlServer(identitySqlConnection, options =>
options.MigrationsAssembly(migrationsAssembly)));
}
services
.AddTransient<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>()
.AddTransient<IAnvandareRepository, AnvandareRepository>()
.AddTransient<IEncryptionService, EncryptionService>();
}
`
Both the IdentityServer4 and the API(WCF service) is selfhosted so no IIS.
When i brows https://localhost:5000/.well-known/openid-configuration I get no page could be found? If I brows the http version I get :
{"issuer":"http://localhost:5000","jwks_uri":"http://localhost:5000/.well-known/openid-configuration/jwks","authorization_endpoint":"http://localhost:5000/connect/authorize","token_endpoint":"http://localhost:5000/connect/token","userinfo_endpoint":"http://localhost:5000/connect/userinfo","end_session_endpoint":"http://localhost:5000/connect/endsession","check_session_iframe":"http://localhost:5000/connect/checksession","revocation_endpoint":"http://localhost:5000/connect/revocation","introspection_endpoint":"http://localhost:5000/connect/introspect","frontchannel_logout_supported":true,"frontchannel_logout_session_supported":true,"scopes_supported":["openid","profile","offline_access","orbit.wcf"],"claims_supported":["sub","name","family_name","given_name","middle_name","nickname","preferred_username","profile","picture","website","gender","birthdate","zoneinfo","locale","updated_at"],"response_types_supported":["code","token","id_token","id_token token","code id_token","code token","code id_token token"],"response_modes_supported":["form_post","query","fragment"],"grant_types_supported":["authorization_code","client_credentials","refresh_token","implicit","password"],"subject_types_supported":["public"],"id_token_signing_alg_values_supported":["RS256"],"token_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post"],"code_challenge_methods_supported":["plain","S256"]}
Is there any way to make sure that the service really is online and that it is using the provided certificate over https?
To specify https cert change UseKestrel() to UseKestrel(options => options.UseHttps([https cert])).
In UseUrls() I had problem when the port was something else that didn't started with 443, so for example I'm using 44310 and that works.
thanks but I do not have UseHttp on the UseKestrel options? I got UseConnectionLogging but no other Use..?
Add the Microsoft.AspNetCore.Server.Kestrel.Https nuget package
Thanks, that and the port needed to be set to get it to work.
Now I need to client to beable to connect to the serivce and this is my code :
private async Task<TokenClient> GetTokenClient()
{
var identityServer = await _consulService.GetService(OrbitServices.IdentityServer);
if (identityServer == null)
throw new ConsuleCommunicationException();
var uri = $"https://{identityServer.Address}:44310/connect/token";
return _loginType.GetTokenClient(uri);
}
var tokenClient = await GetTokenClient();
var token = await tokenClient.RequestResourceOwnerPasswordAsync(username, password, scope: "api.wcf");
The RequestResourceOwner method will execute but the token is null and error is set to : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
The problem might be that the server certificate is issued for andother computer so I suspect that I need to bypass this check some how?
I can see this when browsing https://localhost:44310/.well-known/openid-configuration.
This is solved by using this :
var handler = new WebRequestHandler();
handler.ServerCertificateValidationCallback = PinPublicKey;
var url = $"https://{host}:44310/connect/token";
return new TokenClient(url, ClientTypes.Siths, "x", handler);
public static bool PinPublicKey(object sender, X509Certificate certificate, X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors ||
sslPolicyErrors == SslPolicyErrors.RemoteCertificateNotAvailable)
throw new CommunicationException(SslPolicyErrors.RemoteCertificateNotAvailable.ToString());
return true;
}
Exactly, there is a mismatch between the name in the certificate and the host name you are accessing IdentityServer via. Would actually be better to try to get a valid certificate for the hostname instead.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
To specify https cert change UseKestrel() to UseKestrel(options => options.UseHttps([https cert])).
In UseUrls() I had problem when the port was something else that didn't started with 443, so for example I'm using 44310 and that works.