pokashumbraco/POKASH/Keycloak/Extensions/KeycloakAuthenticationExten...

81 lines
4.9 KiB
C#

using System.IdentityModel.Claims;
using System.Text.Json;
using AspNet.Security.OAuth.Keycloak;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth;
using Umbraco.Cms.Core.Services;
using Umbraco.KeycloakShowcase.Web.Configuration;
namespace Umbraco.KeycloakShowcase.Web.Extensions;
public static class KeycloakAuthenticationExtension
{
public static IUmbracoBuilder AddBackOfficeKeycloakAuthentication(this IUmbracoBuilder builder)
{
var configuration = new KeycloakConfiguration(builder.Config);
builder.AddBackOfficeExternalLogins(logins =>
{
logins.AddBackOfficeLogin(
backOfficeAuthenticationBuilder =>
{
var schemeName = backOfficeAuthenticationBuilder.SchemeForBackOffice(KeycloakMemberExternalLoginProviderOptions.SchemeName);
ArgumentNullException.ThrowIfNull(schemeName);
backOfficeAuthenticationBuilder.AddKeycloak(
schemeName,
options =>
{
options.BaseAddress = new Uri(configuration.BaseAddress);
options.ClientId = configuration.ClientId;
options.ClientSecret = configuration.ClientSecret;
options.AccessType = KeycloakAuthenticationAccessType.Confidential;
options.Realm = configuration.Realm;
options.Version = new Version(configuration.Version ?? string.Empty);
options.CallbackPath = configuration.CallbackPath;
options.AuthorizationEndpoint = "https://auth.pokash.pl/realms/pokash/protocol/openid-connect/auth";
options.TokenEndpoint = "https://auth.pokash.pl/realms/pokash/protocol/openid-connect/token";
options.UserInformationEndpoint = "https://auth.pokash.pl/realms/pokash/protocol/openid-connect/userinfo";
options.SaveTokens = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub");
options.ClaimActions.MapJsonKey(ClaimTypes.Name, "preferred_username");
options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
options.Events = new OAuthEvents
{
OnCreatingTicket = async ctx =>
{
var request = new HttpRequestMessage(HttpMethod.Get, ctx.Options.UserInformationEndpoint);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", ctx.AccessToken);
var response = await ctx.Backchannel.SendAsync(request, ctx.HttpContext.RequestAborted);
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync();
using var jsonDocument = await JsonDocument.ParseAsync(responseStream);
var user = jsonDocument.RootElement;
ctx.RunClaimActions(user);
var userService = ctx.HttpContext.RequestServices.GetRequiredService<IUserService>();
var email = ctx.Principal?.FindFirst(ClaimTypes.Email)?.Value;
var username = ctx.Principal?.FindFirst(ClaimTypes.Name)?.Value;
if (!string.IsNullOrEmpty(email) && !string.IsNullOrEmpty(username))
{
var existingUser = userService.GetByEmail(email);
if (existingUser == null)
{
var newUser = userService.CreateUserWithIdentity(username, email);
newUser.IsApproved = true;
userService.Save(newUser);
}
else
{
existingUser.IsApproved = true;
userService.Save(existingUser);
}
}
}
};
});
});
});
return builder;
}
}