|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace Microsoft.Extensions.DependencyInjection;
/// <summary>
/// Provides extension methods for registering Keycloak-related services in an <see cref="AuthenticationBuilder"/>.
/// </summary>
public static class AspireKeycloakExtensions
{
private const string KeycloakBackchannel = nameof(KeycloakBackchannel);
/// <summary>
/// Adds Keycloak JWT Bearer authentication to the application.
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder" /> to add services to.</param>
/// <param name="serviceName">The name of the service used to resolve the Keycloak server URL.</param>
/// <param name="realm">The realm of the Keycloak server to connect to.</param>
/// <remarks>
/// The <paramref name="serviceName"/> is used to resolve the Keycloak server URL and is combined with the realm to form the authority URL.
/// For example, if <paramref name="serviceName"/> is "keycloak" and <paramref name="realm"/> is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
/// </remarks>
public static AuthenticationBuilder AddKeycloakJwtBearer(this AuthenticationBuilder builder, string serviceName, string realm)
=> builder.AddKeycloakJwtBearer(serviceName, realm, JwtBearerDefaults.AuthenticationScheme, null);
/// <summary>
/// Adds Keycloak JWT Bearer authentication to the application.
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder" /> to add services to.</param>
/// <param name="serviceName">The name of the service used to resolve the Keycloak server URL.</param>
/// <param name="realm">The realm of the Keycloak server to connect to.</param>
/// <param name="authenticationScheme">The authentication scheme name. Default is "Bearer".</param>
/// <remarks>
/// The <paramref name="serviceName"/> is used to resolve the Keycloak server URL and is combined with the realm to form the authority URL.
/// For example, if <paramref name="serviceName"/> is "keycloak" and <paramref name="realm"/> is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
/// </remarks>
public static AuthenticationBuilder AddKeycloakJwtBearer(this AuthenticationBuilder builder, string serviceName, string realm, string authenticationScheme)
=> builder.AddKeycloakJwtBearer(serviceName, realm, authenticationScheme, null);
/// <summary>
/// Adds Keycloak JWT Bearer authentication to the application.
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder" /> to add services to.</param>
/// <param name="serviceName">The name of the service used to resolve the Keycloak server URL.</param>
/// <param name="realm">The realm of the Keycloak server to connect to.</param>
/// <param name="configureOptions">An optional action to configure the <see cref="JwtBearerOptions"/>.</param>
/// <remarks>
/// The <paramref name="serviceName"/> is used to resolve the Keycloak server URL and is combined with the realm to form the authority URL.
/// For example, if <paramref name="serviceName"/> is "keycloak" and <paramref name="realm"/> is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
/// </remarks>
public static AuthenticationBuilder AddKeycloakJwtBearer(this AuthenticationBuilder builder, string serviceName, string realm, Action<JwtBearerOptions>? configureOptions)
=> builder.AddKeycloakJwtBearer(serviceName, realm, JwtBearerDefaults.AuthenticationScheme, configureOptions);
/// <summary>
/// Adds Keycloak JWT Bearer authentication to the application.
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder" /> to add services to.</param>
/// <param name="serviceName">The name of the service used to resolve the Keycloak server URL.</param>
/// <param name="realm">The realm of the Keycloak server to connect to.</param>
/// <param name="authenticationScheme">The authentication scheme name. Default is "Bearer".</param>
/// <param name="configureOptions">An action to configure the <see cref="JwtBearerOptions"/>.</param>
/// <remarks>
/// The <paramref name="serviceName"/> is used to resolve the Keycloak server URL and is combined with the realm to form the authority URL.
/// For example, if <paramref name="serviceName"/> is "keycloak" and <paramref name="realm"/> is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
/// </remarks>
public static AuthenticationBuilder AddKeycloakJwtBearer(
this AuthenticationBuilder builder,
string serviceName,
string realm,
string authenticationScheme,
Action<JwtBearerOptions>? configureOptions)
{
ArgumentNullException.ThrowIfNull(builder);
builder.AddJwtBearer(authenticationScheme);
builder.Services.AddHttpClient(KeycloakBackchannel);
builder.Services
.AddOptions<JwtBearerOptions>(authenticationScheme)
.Configure<IConfiguration, IHttpClientFactory, IHostEnvironment>((options, configuration, httpClientFactory, hostEnvironment) =>
{
options.Backchannel = httpClientFactory.CreateClient(KeycloakBackchannel);
options.Authority = GetAuthorityUri(serviceName, realm);
configureOptions?.Invoke(options);
});
return builder;
}
/// <summary>
/// Adds Keycloak OpenID Connect authentication to the application.
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder" /> to add services to.</param>
/// <param name="serviceName">The name of the service used to resolve the Keycloak server URL.</param>
/// <param name="realm">The realm of the Keycloak server to connect to.</param>
/// <remarks>
/// The <paramref name="serviceName"/> is used to resolve the Keycloak server URL and is combined with the realm to form the authority URL.
/// For example, if <paramref name="serviceName"/> is "keycloak" and <paramref name="realm"/> is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
/// </remarks>
public static AuthenticationBuilder AddKeycloakOpenIdConnect(this AuthenticationBuilder builder, string serviceName, string realm)
=> builder.AddKeycloakOpenIdConnect(serviceName, realm, OpenIdConnectDefaults.AuthenticationScheme, null);
/// <summary>
/// Adds Keycloak OpenID Connect authentication to the application.
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder" /> to add services to.</param>
/// <param name="serviceName">The name of the service used to resolve the Keycloak server URL.</param>
/// <param name="realm">The realm of the Keycloak server to connect to.</param>
/// <param name="authenticationScheme">The OpenID Connect authentication scheme name. Default is "OpenIdConnect".</param>
/// <remarks>
/// The <paramref name="serviceName"/> is used to resolve the Keycloak server URL and is combined with the realm to form the authority URL.
/// For example, if <paramref name="serviceName"/> is "keycloak" and <paramref name="realm"/> is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
/// </remarks>
public static AuthenticationBuilder AddKeycloakOpenIdConnect(this AuthenticationBuilder builder, string serviceName, string realm, string authenticationScheme)
=> builder.AddKeycloakOpenIdConnect(serviceName, realm, authenticationScheme, null);
/// <summary>
/// Adds Keycloak OpenID Connect authentication to the application.
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder" /> to add services to.</param>
/// <param name="serviceName">The name of the service used to resolve the Keycloak server URL.</param>
/// <param name="realm">The realm of the Keycloak server to connect to.</param>
/// <param name="configureOptions">An action to configure the <see cref="OpenIdConnectOptions"/>.</param>
/// <remarks>
/// The <paramref name="serviceName"/> is used to resolve the Keycloak server URL and is combined with the realm to form the authority URL.
/// For example, if <paramref name="serviceName"/> is "keycloak" and <paramref name="realm"/> is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
/// </remarks>
public static AuthenticationBuilder AddKeycloakOpenIdConnect(this AuthenticationBuilder builder, string serviceName, string realm, Action<OpenIdConnectOptions>? configureOptions)
=> builder.AddKeycloakOpenIdConnect(serviceName, realm, OpenIdConnectDefaults.AuthenticationScheme, configureOptions);
/// <summary>
/// Adds Keycloak OpenID Connect authentication to the application.
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder" /> to add services to.</param>
/// <param name="serviceName">The name of the service used to resolve the Keycloak server URL.</param>
/// <param name="realm">The realm of the Keycloak server to connect to.</param>
/// <param name="authenticationScheme">The OpenID Connect authentication scheme name. Default is "OpenIdConnect".</param>
/// <param name="configureOptions">An action to configure the <see cref="OpenIdConnectOptions"/>.</param>
/// <remarks>
/// The <paramref name="serviceName"/> is used to resolve the Keycloak server URL and is combined with the realm to form the authority URL.
/// For example, if <paramref name="serviceName"/> is "keycloak" and <paramref name="realm"/> is "myrealm", the authority URL will be "https+http://keycloak/realms/myrealm".
/// </remarks>
public static AuthenticationBuilder AddKeycloakOpenIdConnect(
this AuthenticationBuilder builder,
string serviceName,
string realm,
string authenticationScheme,
Action<OpenIdConnectOptions>? configureOptions)
{
ArgumentNullException.ThrowIfNull(builder);
builder.AddOpenIdConnect(authenticationScheme, options => { });
builder.Services.AddHttpClient(KeycloakBackchannel);
builder.Services
.AddOptions<OpenIdConnectOptions>(authenticationScheme)
.Configure<IConfiguration, IHttpClientFactory, IHostEnvironment>((options, configuration, httpClientFactory, hostEnvironment) =>
{
options.Backchannel = httpClientFactory.CreateClient(KeycloakBackchannel);
options.Authority = GetAuthorityUri(serviceName, realm);
configureOptions?.Invoke(options);
});
return builder;
}
private static string GetAuthorityUri(
string serviceName,
string realm)
{
return $"https+http://{serviceName}/realms/{realm}";
}
}
|