81 lines
4.9 KiB
C#
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;
|
|
}
|
|
} |