openiddict / openiddict-core

Flexible and versatile OAuth 2.0/OpenID Connect stack for .NET
https://openiddict.com/
Apache License 2.0
4.48k stars 528 forks source link

Unable to obtain configuration from: '/.well-known/openid-configuration' when hosted on IIS #628

Closed muehan closed 6 years ago

muehan commented 6 years ago

Hi

I use Version: OpenIddict 2.0.0-rc2-final OpenIddict.EntityFrameworkCore 2.0.0-rc2-final OpenIddict.Mvc 2.0.0-rc2-final

with the folowing configuration:

services.AddOpenIddict(options =>
{
    // Register the Entity Framework stores.
    options.AddEntityFrameworkCoreStores<AuthContext>();

    options.AddMvcBinders();

    // Enable the token endpoint (required to use the password flow).
    options.EnableTokenEndpoint("/api/authorization/token")
           .EnableLogoutEndpoint("/api/authorization/logout");

    options.AllowPasswordFlow()
        .AllowRefreshTokenFlow()
        .SetAccessTokenLifetime(TimeSpan.FromHours(2))
        .SetRefreshTokenLifetime(TimeSpan.FromDays(180));

    options.DisableHttpsRequirement();
    options.AddSigningCertificate(cert);
    options.UseJsonWebTokens();
});

//// configure Jwt access token authentication
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();

services
    .AddAuthentication(o =>
    {
        o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        options.Authority = configuration["JwtConfiguration:Authority"]?.ToString();
        options.Audience = "resource_server";
        options.MetadataAddress = "/.well-known/openid-configuration";
        options.RequireHttpsMetadata = false;
        options.IncludeErrorDetails = true;
        options.TokenValidationParameters = new TokenValidationParameters()
        {
            NameClaimType = OpenIdConnectConstants.Claims.Subject,
            RoleClaimType = OpenIdConnectConstants.Claims.Role,
        };
    });

OpenIddict is included in my API, also my SpaClient runs inside this single Application. If I run this in my Visual Studio with IISExpress everything works fine. But on my Test Server I have this error:

System.InvalidOperationException: IDX10803: Unable to obtain configuration from: '/.well-known/openid-configuration'. ---> System.IO.IOException: IDX10804: Unable to retrieve document from: '/.well-known/openid-configuration'. ---> System.InvalidOperationException: An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set.

I tried diffrent configurations for the MetadataAddress but nothing works. Local and on the server I can open the endpoint "/.well-known/openid-configuration" without any problem.

I also tried to remove the IP binding from the website as described here: https://github.com/openiddict/openiddict-core/issues/509 sadly with no success.

Any idea what is wrong? After 2 days of try and error on this single problem I run out of ideas...

kevinchalet commented 6 years ago

Hi,

The exception seems very clear to me: options.MetadataAddress = "/.well-known/openid-configuration" is not valid and should be an absolute URL, like options.MetadataAddress = "http://localhost:[port]/.well-known/openid-configuration".

Usually, it's better not to set this property and simply set options.Authority with the absolute URL of your authorization server, without the /.well-known/openid-configuration part.

(note: it's not specific to OpenIddict as the JWT bearer handler is not developed here and maintained by Microsoft).

muehan commented 6 years ago

Thanks for the response. config:

.AddJwtBearer(options =>
{
    options.Authority = configuration["JwtConfiguration:Authority"]?.ToString();
    options.Audience = "resource_server";
    //options.MetadataAddress = "/.well-known/openid-configuration";
    options.RequireHttpsMetadata = false;
    options.IncludeErrorDetails = true;
    options.TokenValidationParameters = new TokenValidationParameters()
    {
        NameClaimType = OpenIdConnectConstants.Claims.Subject,
        RoleClaimType = OpenIdConnectConstants.Claims.Role,
    };
});

New Error:

IDX10803: Unable to obtain configuration from: 'https://transportq.company.com/.well-known/openid-configuration'. ---> System.IO.IOException: IDX10804: Unable to retrieve document from: 'https://transportq.company.com/.well-known/openid-configuration'. ---> System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.

The configuration endpoint is working:

{
    "issuer": "https://transportq.company.com/",
    "token_endpoint": "https://transportq.company.com/api/authorization/token",
    "end_session_endpoint": "https://transportq.company.com/api/authorization/logout",
    "jwks_uri": "https://transportq.company.com/.well-known/jwks",
    "grant_types_supported": ["password",
    "refresh_token"],
    "scopes_supported": ["openid",
    "offline_access"],
    "id_token_signing_alg_values_supported": ["RS256"],
    "subject_types_supported": ["public"],
    "token_endpoint_auth_methods_supported": ["client_secret_basic",
    "client_secret_post"],
    "claims_supported": ["aud",
    "exp",
    "iat",
    "iss",
    "sub"],
    "claims_parameter_supported": false,
    "request_parameter_supported": false,
    "request_uri_parameter_supported": false
}

The certificate I'm using is valid, I reused the one from the windows store as PFX: image

muehan commented 6 years ago

And all that is working on my local machine without any problem

muehan commented 6 years ago

sorry, wrong button

muehan commented 6 years ago

i just deployed the application to the IIS on my win7 dev machine and its working there as well. why is the server not happy with the certificate which works fine on my machine?

kevinchalet commented 6 years ago

why is the server not happy with the certificate which works fine on my machine?

No idea. It's clearly not an OpenIddict issue so I suggest pinging the ASP.NET folks if you need assistance with TLS or with how to register your TLS certificate: https://github.com/aspnet/Home

muehan commented 6 years ago

I now tried to load the certificate directly from the store:

options.AddSigningCertificate(configuration["JwtConfiguration:thumbprint"]?.ToString(), StoreName.My, StoreLocation.LocalMachine);

I tested several different certificates which all are valid and working for SSL. So I don't think this is a certificate problem if none of them work. I guess there is something wrong on the server or iis config, but how should I find that? Any idea?

kevinchalet commented 6 years ago

It really has nothing to do with the signing certificate (only used by OpenIddict to... sign tokens).

It's a transport security issue: for some reasons, your TLS certificate - used to encrypt the HTTP/TCP communications - is not considered valid by your system. It's not an OpenIddict problem.

muehan commented 6 years ago

Ok, maybe the problem ist that on the server we have dotnet 4.6.1 and the solution target is net47...

sadly I have to wait until beginning of next week until infrastructure team has installed the new version on the test server... I'm not allowed to do that :-(

so then I close this issue and if I somehow find a fix I add the info here. many thanks for you help and also thanks for the library!

muehan commented 6 years ago

.net Version was not the problem. Our Admin installed the intermediate certificate in the personal store and wasted 2 weeks of my live... probably more. The certificate looked corrected if you open it in the certificate manager. the problem is only visible if you open the page with IE on the server (clients all have the certificate correctly installed). Who does open a angular page in IE on the server?

lutvdh commented 6 years ago

@muehan , did you get resolve this issue?

muehan commented 5 years ago

@lutvdh sorry for the late response. Yes, as mentioned in the comment before, the intermediate certificate was not installed in the intermediate store. it was in the personal store. so in the vertificate manager the cert and the chain was shown as valid. but the browser was not able to verify the certificate chain because he did not found the intermediate cert in the intermediate store. moving the cert into the right place fixed my problem.

AKlaus commented 2 years ago

Confirm the issue on .NET 6, Windows 10 (doesn't happen on macOS and Linux). It's occurred on the client side, so clearly the .NET Identity problem, not OpenIdDict. I suspect it's caused by a self-issued certificate. Also confirm that setting options.MetadataAddress and options.RequireHttpsMetadata (as discussed above) didn't make a difference.