4

I need to use KeyCloak as SSO server, to authorize, first, some Mvc web application and second, some Apis.

I'm at the point I need to configure Keycloak for my WebApp, so I manage to find that link :

enter link description here

but it is not very helpful.

I have Keycloak docker image running, I create my real, client and a user, so everything seems fine for KeyCloak, at least, I think so.

I created a basic ASP.NET Core MVC application and updated the program.cs class to setup as the example in the link so :

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using System.IdentityModel.Tokens.Jwt;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

builder.Services.AddMvc();

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

builder.Services.AddAuthentication(options =>
{
    // Store the session to cookies
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    // OpenId authentication
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
    .AddCookie("Cookies")
    .AddOpenIdConnect(options =>
    {
        // URL of the Keycloak server
        options.Authority = "https://localhost:8080/auth/realms/BrunoRealm";
        // Client configured in the Keycloak
        options.ClientId = "MonApplication";

        // For testing we disable https (should be true for production)
        options.RequireHttpsMetadata = false;
        options.SaveTokens = true;
        options.ClientId = "MonApplication";
        // Client secret shared with Keycloak
        options.ClientSecret = "nrnsK6od01BpzJ0NTzvdC2DLt0ta72zp";
        options.GetClaimsFromUserInfoEndpoint = true;

        // OpenID flow to use
        options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
    }); 

var app = builder.Build();

app.UseAuthentication();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

I put an [Authorize] attribute on the privacy method of home controller but when I try to access privacy page, I have an exception talking about SSL :

An unhandled exception occurred while processing the request.

IOException: Cannot determine the frame size or a corrupted frame was received.
System.Net.Security.SslStream.GetFrameSize(ReadOnlySpan buffer)

HttpRequestException: The SSL connection could not be established, see inner exception.

System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, bool async, Stream stream, CancellationToken cancellationToken)

IOException: IDX20804: Unable to retrieve document from: '[PII of type 'System.String' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(string address, CancellationToken cancel)

InvalidOperationException: IDX20803: Unable to obtain configuration from: '[PII of type 'System.String' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.

Microsoft.IdentityModel.Protocols.ConfigurationManager.GetConfigurationAsync(CancellationToken cancel)

Stack Query Cookies Headers Routing
IOException: Cannot determine the frame size or a corrupted frame was received.

System.Net.Security.SslStream.GetFrameSize(ReadOnlySpan buffer)
System.Net.Security.SslStream.ReceiveBlobAsync(TIOAdapter adapter)
System.Threading.Tasks.ValueTask.get_Result()
System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable+ConfiguredValueTaskAwaiter.GetResult()
System.Net.Security.SslStream.ForceAuthenticationAsync(TIOAdapter adapter, bool receiveFirst, byte[] reAuthenticationData, bool isApm)
System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, bool async, Stream stream, CancellationToken cancellationToken)

Show raw exception details
HttpRequestException: The SSL connection could not be established, see inner exception.

System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, bool async, Stream stream, CancellationToken cancellationToken)
System.Threading.Tasks.ValueTask.get_Result()
System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable+ConfiguredValueTaskAwaiter.GetResult()
System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken)
System.Threading.Tasks.ValueTask.get_Result()
System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable+ConfiguredValueTaskAwaiter.GetResult()
System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken)
System.Threading.Tasks.ValueTask.get_Result()
System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable+ConfiguredValueTaskAwaiter.GetResult()
System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage request)
System.Threading.Tasks.TaskCompletionSourceWithCancellation.WaitWithCancellationAsync(CancellationToken cancellationToken)
System.Threading.Tasks.ValueTask.get_Result()
System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable+ConfiguredValueTaskAwaiter.GetResult()
System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken)
System.Threading.Tasks.ValueTask.get_Result()
System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable+ConfiguredValueTaskAwaiter.GetResult()
System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken)
System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, bool async, CancellationToken cancellationToken)
System.Threading.Tasks.ValueTask.get_Result()
System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable+ConfiguredValueTaskAwaiter.GetResult()
System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken)
System.Net.Http.HttpClient.
g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, bool disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(string address, CancellationToken cancel)

Show raw exception details
IOException: IDX20804: Unable to retrieve document from: '[PII of type 'System.String' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.

Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(string address, CancellationToken cancel)
Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(string address, IDocumentRetriever retriever, CancellationToken cancel)
Microsoft.IdentityModel.Protocols.ConfigurationManager.GetConfigurationAsync(CancellationToken cancel)

Show raw exception details
InvalidOperationException: IDX20803: Unable to obtain configuration from: '[PII of type 'System.String' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
Microsoft.IdentityModel.Protocols.ConfigurationManager.GetConfigurationAsync(CancellationToken cancel)
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleChallengeAsyncInternal(AuthenticationProperties properties)
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleChallengeAsync(AuthenticationProperties properties)
Microsoft.AspNetCore.Authentication.AuthenticationHandler.ChallengeAsync(AuthenticationProperties properties)
Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties)
Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

I have no idea where to look at. Have I to configure SSL on my docker image. Must I implement a login page but, in that case how to call KeyCloak?

So in short what to do know?

3
  • 1
    Your WebApp is running on Windows? And you have hardened Windows to use Tls 1.3 explicitly? The Windows implementations of that is experimental and will break the way you show in your stack. Commented Jan 28, 2022 at 16:23
  • Keycloak uses port 8443 for HTTPS but you used 8080 in your URL. Check this possibly duplicate question Commented Jan 28, 2022 at 17:10
  • I am not sue HTTPS is wanted here, because of explicitly setting options.RequireHttpsMetadata = false Commented Jan 28, 2022 at 17:16

1 Answer 1

0

Keycloak does not support HTTPS on port 8080 (by default). Change https:// to http:// in

options.Authority = "https://localhost:8080/auth/realms/BrunoRealm";

so that it reads

options.Authority = "http://localhost:8080/auth/realms/BrunoRealm";
Sign up to request clarification or add additional context in comments.

2 Comments

Or use HTTPS on port 8443
@panagiotis-kanavos is right. From a security point of view that is what you should prefer. However, you then need to manage certificates and establish trust between your app and Keycloak.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.