IdentityServer4 with certificate?

Created on 17 Jan 2017  路  7Comments  路  Source: IdentityServer/IdentityServer4

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?

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.

All 7 comments

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.

Was this page helpful?
0 / 5 - 0 ratings