DigiCypress.XAF.SingleSignOn.Keycloak.Blazor 24.1.5.1

dotnet add package DigiCypress.XAF.SingleSignOn.Keycloak.Blazor --version 24.1.5.1                
NuGet\Install-Package DigiCypress.XAF.SingleSignOn.Keycloak.Blazor -Version 24.1.5.1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DigiCypress.XAF.SingleSignOn.Keycloak.Blazor" Version="24.1.5.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add DigiCypress.XAF.SingleSignOn.Keycloak.Blazor --version 24.1.5.1                
#r "nuget: DigiCypress.XAF.SingleSignOn.Keycloak.Blazor, 24.1.5.1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install DigiCypress.XAF.SingleSignOn.Keycloak.Blazor as a Cake Addin
#addin nuget:?package=DigiCypress.XAF.SingleSignOn.Keycloak.Blazor&version=24.1.5.1

// Install DigiCypress.XAF.SingleSignOn.Keycloak.Blazor as a Cake Tool
#tool nuget:?package=DigiCypress.XAF.SingleSignOn.Keycloak.Blazor&version=24.1.5.1                

DigiCypress.XAF.SingleSignOn.Keycloak.Blazor

  • SingleSignOn.Keycloak.Blazor module for Devexpress XAF

  • Blazor Server

-- make sure startup uri launchSetting.json is equate Keycloak Server

-- Upgrade the package System.IdentityModel.Tokens.Jwt referenced in the Module and Blazor projects from the original 6.* to 8.* https://github.com/openiddict/openiddict-core/issues/2033

-- add in BlazorApplication

protected override List<Controller> CreateLogonWindowControllers()
{
    var result = base.CreateLogonWindowControllers();
    result.Add(new AdditionalLogonActionsCustomizationController());
    return result;
}

public override void LogOff()
{
    base.LogOff();
    var navigationManager = this.ServiceProvider.GetRequiredService<NavigationManager>();
    navigationManager.NavigateTo("Account/Logout", forceLoad: true);
}

-- appsettings.json

"Keycloak": {
  "Authority": "http://localhost:8080/realms/my-realm",
  "ClientId": "my-client",
  "ClientSecret": "rr7Fzu0KgVoutojhOUPd3qQWvTG7iTXE"    
}

-- Set Startup.cs --- add the following in builder.Security section

....
.AddPasswordAuthentication(options => {
    options.IsSupportChangePassword = true;
})
.AddAuthenticationProvider<KeycloakAuthenticationProvider>(); 

--- add the following in authentication section

authentication.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, "Keycloak", options =>
{
    options.Authority = Configuration["Keycloak:Authority"];
    options.ClientId = Configuration["Keycloak:ClientId"];
    options.ClientSecret = Configuration["Keycloak:ClientSecret"];
    options.SaveTokens = true;
    options.RequireHttpsMetadata = false;

    //https://stackoverflow.com/questions/74052650
    options.SignOutScheme = OpenIdConnectDefaults.AuthenticationScheme;

    //https://stackoverflow.com/questions/74327614
    options.Scope.Add("openid");

    options.Events.OnRedirectToIdentityProvider = async context =>
    {
        context.ProtocolMessage.RedirectUri = context.ProtocolMessage.RedirectUri.Replace("http:", "https:");
        await Task.FromResult(0);
    };
});

--- add the following in app.UseEndpoints section

....
endpoints.MapGet("/Account/Logout", async context =>
{
    if (context.User.Identity.AuthenticationType == "AuthenticationTypes.Federation")
        await context.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);

    await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme, new AuthenticationProperties
    {
        RedirectUri = "/"
    });
}).RequireAuthorization();

endpoints.MapControllers();
  • Web API

-- appsettings.json

"Keycloak": {
  "Authority": "http://localhost:8080/realms/my-realm",
  "ClientId": "my-client",
  "ClientSecret": "rr7Fzu0KgVoutojhOUPd3qQWvTG7iTXE"    
}

-- Modify API\AuthenticationController.cs

public class AuthenticationController : ControllerBase
{
    readonly IAuthenticationTokenProvider tokenProvider;
    readonly KeycloakAuthorizationService keycloakAuthorizationService;
    public AuthenticationController(IAuthenticationTokenProvider tokenProvider, KeycloakAuthorizationService keycloakAuthService = null)
    {
        this.tokenProvider = tokenProvider;
        this.keycloakAuthorizationService = keycloakAuthService;
    }
    //[HttpPost("Authenticate")]
    //[SwaggerOperation("Checks if the user with the specified logon parameters exists in the database. If it does, authenticates this user.", "Refer to the following help topic for more information on authentication methods in the XAF Security System: <a href='https://docs.devexpress.com/eXpressAppFramework/119064/data-security-and-safety/security-system/authentication'>Authentication</a>.")]
    //public IActionResult Authenticate(
    //    [FromBody]
    //    [SwaggerRequestBody(@"For example: <br /> { ""userName"": ""Admin"", ""password"": """" }")]
    //    AuthenticationStandardLogonParameters logonParameters
    //) {
    //    try {
    //        return Ok(tokenProvider.Authenticate(logonParameters));
    //    }
    //    catch(AuthenticationException ex) {
    //        return Unauthorized(ex.GetJson());
    //    }
    //}

    [HttpPost("KeycloakAuthenticate")]
    [SwaggerOperation("Checks if the user with the specified logon parameters exists in the database. If it does, authenticates this user.", "Refer to the following help topic for more information on authentication methods in the XAF Security System: <a href='https://docs.devexpress.com/eXpressAppFramework/119064/data-security-and-safety/security-system/authentication'>Authentication</a>.")]
    public async Task<IActionResult> KeycloakAuthenticate(
        [FromBody]
        [SwaggerRequestBody(@"For example: <br /> { ""userName"": ""Admin"", ""password"": """" }")]
        AuthenticationStandardLogonParameters logonParameters
    )
    {
        try
        {
            var token = await keycloakAuthorizationService.LoginAsync(logonParameters.UserName, logonParameters.Password);
            return Ok(token.AccessToken);
        }
        catch (AuthenticationException ex)
        {
            return Unauthorized(ex.GetJson());
        }
    }
}

-- Set Startup.cs --- add the following in builder.Security section

....
.AddPasswordAuthentication(options => {
    options.IsSupportChangePassword = true;
})
.AddAuthenticationProvider<KeycloakAuthenticationProvider>(); 

--- replace services.AddAuthentication section

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = Configuration["Keycloak:Authority"],

            ValidateAudience = true,
            ValidAudience = "account",

            ValidateIssuerSigningKey = true,
            ValidateLifetime = false,

            IssuerSigningKeyResolver = (token, securityToken, kid, parameters) =>
            {
                var client = new HttpClient();
                var keyUri = $"{parameters.ValidIssuer}/protocol/openid-connect/certs";
                var response = client.GetAsync(keyUri).Result;
                var keys = new JsonWebKeySet(response.Content.ReadAsStringAsync().Result);

                return keys.GetSigningKeys();
            }
        };

        options.RequireHttpsMetadata = false; // Only in develop environment
        options.SaveToken = false;
    });
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
24.1.5.1 84 12/9/2024