Skip to content

Commit

Permalink
Add KeycloakWebAppAuthenticationBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleksii Nikiforov committed Apr 24, 2024
1 parent 14d038f commit d65bda8
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
</PropertyGroup>

<PropertyGroup Label="Package">
<Product>Keycloak.AuthServices.Authorization</Product>
<Description>OICD + JWT Authentication provider. JWT Bearer Authentication for Keycloak</Description>
<Product>Keycloak.AuthServices.Authentication</Product>
<Description>OICD Authentication; JWT Bearer Authentication for Keycloak</Description>
<PackageTags>Keycloak;Authentication;Authrorization;authserver;JWT;OICD;jwt-authentication</PackageTags>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect"/>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,22 @@
public class KeycloakAuthenticationOptions : KeycloakInstallationOptions
{
/// <summary>
/// Default section name
/// Default section name.
/// </summary>
public const string Section = ConfigurationConstants.ConfigurationPrefix;

/// <summary>
/// Gets or sets the audience for the authentication. Takes priority over Resource
/// </summary>
public string? Audience { get; set; }

/// <summary>
/// Gets or sets the claim type used for roles.
/// </summary>
public string RoleClaimType { get; set; } = "role";

/// <summary>
/// Gets or sets the claim type used for the name.
/// </summary>
public string NameClaimType { get; set; } = "preferred_username";
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;

/// <summary>
/// Extensions for <see cref="AuthenticationBuilder"/> for startup initialization of web APIs.
Expand All @@ -18,8 +20,6 @@ public static class KeycloakWebApiAuthenticationBuilderExtensions
/// <param name="configuration">The configuration instance.</param>
/// <param name="configSectionName">The configuration section with the necessary settings to initialize authentication options.</param>
/// <param name="jwtBearerScheme">The JWT bearer scheme name to be used. By default it uses "Bearer".</param>
/// Set to true if you want to debug, or just understand the JWT bearer events.
/// </param>
/// <returns>The authentication builder to chain.</returns>
public static KeycloakWebApiAuthenticationBuilder AddKeycloakWebApi(
this AuthenticationBuilder builder,
Expand All @@ -37,14 +37,12 @@ public static KeycloakWebApiAuthenticationBuilder AddKeycloakWebApi(
}

/// <summary>
/// Protects the web API with Microsoft identity platform (formerly Azure AD v2.0).
/// Protects the web API with Keycloak
/// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options.
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/> to which to add this configuration.</param>
/// <param name="configurationSection">The configuration second from which to fill-in the options.</param>
/// <param name="jwtBearerScheme">The JWT bearer scheme name to be used. By default it uses "Bearer".</param>
/// Set to true if you want to debug, or just understand the JWT bearer events.
/// </param>
/// <returns>The authentication builder to chain.</returns>
public static KeycloakWebApiAuthenticationBuilder AddKeycloakWebApi(
this AuthenticationBuilder builder,
Expand All @@ -71,13 +69,12 @@ public static KeycloakWebApiAuthenticationBuilder AddKeycloakWebApi(
}

/// <summary>
/// Protects the web API with Microsoft identity platform (formerly Azure AD v2.0).
/// Protects the web API with Keycloak
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/> to which to add this configuration.</param>
/// <param name="configureJwtBearerOptions">The action to configure <see cref="JwtBearerOptions"/>.</param>
/// <param name="configureKeycloakOptions">The action to configure the <see cref="KeycloakAuthenticationOptions"/>.</param>
/// <param name="jwtBearerScheme">The JWT bearer scheme name to be used. By default it uses "Bearer".</param>
/// Set to true if you want to debug, or just understand the JWT bearer events.</param>
/// <returns>The authentication builder to chain.</returns>
public static KeycloakWebApiAuthenticationBuilder AddKeycloakWebApi(
this AuthenticationBuilder builder,
Expand Down Expand Up @@ -107,8 +104,45 @@ private static void AddKeycloakWebApiImplementation(
string jwtBearerScheme
)
{
// TODO: add merging logic
builder.AddJwtBearer(jwtBearerScheme, _ => { });

builder
.Services.AddOptions<JwtBearerOptions>(jwtBearerScheme)
.Configure<IServiceProvider, IOptionsMonitor<KeycloakAuthenticationOptions>>(
(options, serviceProvider, keycloakOptionsMonitor) =>
{
var keycloakOptions = keycloakOptionsMonitor.Get(jwtBearerScheme);
// Ensure a well-formed authority was provided
if (!string.IsNullOrWhiteSpace(keycloakOptions.KeycloakUrlRealm))
{
options.Authority = keycloakOptions.KeycloakUrlRealm;
}
var sslRequired =
string.IsNullOrWhiteSpace(keycloakOptions.SslRequired)
|| keycloakOptions.SslRequired.Equals(
"external",
StringComparison.OrdinalIgnoreCase
);
options.RequireHttpsMetadata = sslRequired;
var validationParameters = new TokenValidationParameters
{
ClockSkew = keycloakOptions.TokenClockSkew,
ValidateAudience = keycloakOptions.VerifyTokenAudience ?? true,
ValidateIssuer = true,
NameClaimType = keycloakOptions.NameClaimType,
RoleClaimType = keycloakOptions.RoleClaimType,
};
options.Audience = keycloakOptions.Audience ?? keycloakOptions.Resource;
options.TokenValidationParameters = validationParameters;
options.SaveToken = true;
options.Events ??= new JwtBearerEvents();
builder.AddJwtBearer(jwtBearerScheme, configureJwtBearerOptions);
configureJwtBearerOptions?.Invoke(options);
}
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public static KeycloakWebAppAuthenticationBuilder AddKeycloakWebApp(
}

/// <summary>
/// Add authentication with Microsoft identity platform.
/// Add authentication with Keycloak
/// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options.
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/> to which to add this configuration.</param>
Expand Down Expand Up @@ -82,7 +82,7 @@ public static KeycloakWebAppAuthenticationBuilder AddKeycloakWebApp(
}

/// <summary>
/// Add authentication with Microsoft identity platform.
/// Add authentication with Keycloak
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/> to which to add this configuration.</param>
/// <param name="configureKeycloakOptions">The action to configure <see cref="KeycloakAuthenticationOptions"/>.</param>
Expand Down Expand Up @@ -112,7 +112,7 @@ public static KeycloakWebAppAuthenticationBuilder AddKeycloakWebApp(
}

/// <summary>
/// Add authentication with Microsoft identity platform.
/// Add authentication with Keycloak
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/> to which to add this configuration.</param>
/// <param name="configureKeycloakOptions">The action to configure <see cref="KeycloakAuthenticationOptions"/>.</param>
Expand Down Expand Up @@ -150,7 +150,7 @@ IConfigurationSection configurationSection
}

/// <summary>
/// Add authentication with Microsoft identity platform.
/// Add authentication with Keycloak
/// </summary>
/// <param name="builder">The <see cref="AuthenticationBuilder"/> to which to add this configuration.</param>
/// <param name="configureKeycloakOptions">The action to configure <see cref="KeycloakAuthenticationOptions"/>.</param>
Expand Down Expand Up @@ -201,13 +201,12 @@ private static void AddKeycloakWebAppInternal(

if (!string.IsNullOrEmpty(cookieScheme))
{
Action<CookieAuthenticationOptions> emptyOption = option => { };
builder.AddCookie(cookieScheme, configureCookieAuthenticationOptions ?? emptyOption);
builder.AddCookie(cookieScheme, configureCookieAuthenticationOptions ?? (_ => { }));
}

if (!string.IsNullOrEmpty(displayName))
{
builder.AddOpenIdConnect(openIdConnectScheme, displayName: displayName, options => { });
builder.AddOpenIdConnect(openIdConnectScheme, displayName: displayName, _ => { });
}
else
{
Expand Down

0 comments on commit d65bda8

Please sign in to comment.