Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4839

How to integrate LDAP with .NET 8 based Blazor Web App (Server-Side)?

$
0
0

I am trying to integrate authentication with our LDAP server for .NET 8 Blazor Web App.

My launchSettings.json

{"$schema": "http://json.schemastore.org/launchsettings.json","iisSettings": {"windowsAuthentication": false,"anonymousAuthentication": true,"iisExpress": {"applicationUrl": "http://localhost:25412","sslPort": 44310,"environmentVariables": {"UserDomains": "mycorp=LDAP://mycorp.com"        }      }    },"profiles": {"http": {"commandName": "Project","dotnetRunMessages": true,"launchBrowser": true,"applicationUrl": "http://localhost:5102","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development","UserDomains": "mycorp=LDAP://mycorp.com"        }      },"https": {"commandName": "Project","dotnetRunMessages": true,"launchBrowser": true,"applicationUrl": "https://localhost:7038;http://localhost:5102","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development","UserDomains": "mycorp=LDAP://mycorp.com"        }      },"IIS Express": {"commandName": "IISExpress","launchBrowser": true,"environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development","UserDomains": "mycorp=LDAP://mycorp.com"        }      }    }  }

UserLogin.razor

@page "/userlogin"@using System.ComponentModel.DataAnnotations@using System.Text@using System.DirectoryServices@using RCBuisinessLogic@using RCBuisinessLogic.Authentication@using RCWebApp.Models@rendermode InteractiveServer@inject IHttpContextAccessor HttpContextAccessor@inject NavigationManager NavigationManager@inject UserInformation UserInformation<div class="user-login" style="height: 630px;"><EditForm Model="@Login" OnSubmit="HandleLogin" FormName="UserLoginForm"><DataAnnotationsValidator /><ValidationSummary /><div class="form-group"><label for="UserName">Username:</label><InputText id="UserName" class="form-control" @bind-Value="Login.UserName" /><ValidationMessage For="@(() => Login.UserName)" /></div><div class="form-group"><label for="Password">Password:</label><InputText id="Password" class="form-control" @bind-Value="Login.Password" Type="password" /><ValidationMessage For="@(() => Login.Password)" /></div><button type="submit" class="btn btn-primary">Login</button></EditForm></div>@code {    private Login Login { get; set; } = new Login();    private async Task HandleLogin()    {        string userDomains = Environment.GetEnvironmentVariable("UserDomains");        bool isValidLogin = IsValidLogin("LDAP://mycorp.com", "mycorp", Login.UserName, Login.Password, out string retMessage);        if (isValidLogin)        {            NavigationManager.NavigateTo("/dashboard");        }        else        {            NavigationManager.NavigateTo("/");        }    }    private bool IsValidLogin(string LDAPPath, string domainName, string userName, string password, out string retMessage)    {        bool returnValue = false;        retMessage = null;        try        {            // encode user input before being used in LDAP query.            string safeUserName = EscapeLdapSearchFilter(userName);            var userClaims = HttpContextAccessor.HttpContext?.User?.Claims;            bool isAuthenticated = HttpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false;            string email = HttpContextAccessor.HttpContext?.User?.            FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value;            var de = new DirectoryEntry(LDAPPath, userName, password);            using (var ds = new DirectorySearcher(de) { Filter = "samaccountname=" + safeUserName })            {                SearchResult sr = ds.FindOne();                if (sr == null)                {                    retMessage = "Invalid Login.";                }                else                {                    string userID = UserInformation.GetByName($"{domainName}\\{userName}", email);                    returnValue = true;                }            }        }        catch (Exception ex)        {            retMessage = $"Error during LDAP login: {ex.Message}";        }        return returnValue;    }    private static string EscapeLdapSearchFilter(string searchFilter)    {        StringBuilder escape = new StringBuilder();        for (int i = 0; i < searchFilter.Length; i++)        {            char current = searchFilter[i];            switch (current)            {                case '\\':                    escape.Append(@"\5c");                    break;                case '*':                    escape.Append(@"\2a");                    break;                case '(':                    escape.Append(@"\28");                    break;                case ')':                    escape.Append(@"\29");                    break;                case '\u0000':                    escape.Append(@"\00");                    break;                case '/':                    escape.Append(@"\2f");                    break;                default:                    escape.Append(current);                    break;            }        }        return escape.ToString();    }}

userClaims is empty, isAuthenticated is false, email is null in the below code from above file

var userClaims = HttpContextAccessor.HttpContext?.User?.Claims;             bool isAuthenticated = HttpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false;            string email = HttpContextAccessor.HttpContext?.User?.            FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value;

My Program.csIt has some Auth configuration I tried, but it didn't work, so that's commented.

using Microsoft.AspNetCore.Authentication;using RCBuisinessLogic.Authentication;using RCBuisinessLogic.DataAccess;using RCWebApp.Components;var builder = WebApplication.CreateBuilder(args);builder.Services.AddHttpContextAccessor();// Register IConfigurationbuilder.Services.AddSingleton<IConfiguration>(builder.Configuration);builder.Services.AddSingleton<BaseDAL>();// Register AuthenticationConfigurationbuilder.Services.AddSingleton<AuthenticationConfiguration>();// Register UserInformationbuilder.Services.AddTransient<UserInformation>();// Add services to the container.builder.Services.AddRazorComponents()    .AddInteractiveServerComponents();// Add authentication services and configure the custom authentication scheme.//builder.Services.AddAuthentication(options =>//{//    options.DefaultAuthenticateScheme = "LDAP";//    options.DefaultChallengeScheme = "LDAP";//})//.AddScheme<AuthenticationSchemeOptions, LdapAuthenticationHandler>("LDAP", options => { });// Add authorization services//builder.Services.AddAuthorization(options =>//{//    // You can configure authorization policies here if needed.//    options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser());//});var app = builder.Build();// Use authentication and authorization before handling routingapp.UseAuthentication();app.UseAuthorization();//app.Use(async (context, next) =>//{//    var user = context.User;//    // Only redirect authenticated users if they are NOT trying to access '/userlogin'//    if (user.Identity.IsAuthenticated && !context.Request.Path.StartsWithSegments("/userlogin"))//    {//        // Redirect authenticated users to the dashboard or another page//        context.Response.Redirect("/dashboard");//        return;//    }//    await next();  // Continue the request pipeline//});// Configure the HTTP request pipeline.if (!app.Environment.IsDevelopment()){    app.UseExceptionHandler("/Error", createScopeForErrors: true);    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.    app.UseHsts();}app.UseHttpsRedirection();app.UseStaticFiles();app.UseAntiforgery();app.MapRazorComponents<App>()    .AddInteractiveServerRenderMode();app.Run();

Tried out this middleware suggested by chatgpt but, it didn't work.

using Microsoft.AspNetCore.Authentication;using Microsoft.Extensions.Options;using RCBuisinessLogic.Authentication;using System.DirectoryServices;using System.Security.Claims;using System.Text.Encodings.Web;using System.Threading.Tasks;public class LdapAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>{    private readonly UserInformation _userInformation;    public LdapAuthenticationHandler(        IOptionsMonitor<AuthenticationSchemeOptions> options,        ILoggerFactory logger,        UrlEncoder encoder,        ISystemClock clock,        UserInformation userInformation)        : base(options, logger, encoder, clock)    {        _userInformation = userInformation;    }    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()    {        var username = Context.Request.Form["username"];        var password = Context.Request.Form["password"];        string domain = "mycorp.com";  // Adjust to your LDAP domain        // Perform LDAP authentication here.        var isAuthenticated = AuthenticateWithLdap(username, password, domain, out var userId);        if (isAuthenticated)        {            // Create claims and set the principal            var claims = new List<Claim>            {                new Claim(ClaimTypes.Name, username),                new Claim(ClaimTypes.NameIdentifier, userId),                new Claim(ClaimTypes.Email, userId)  // Adjust according to your LDAP setup            };            var claimsIdentity = new ClaimsIdentity(claims, "LDAP");            var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);            var ticket = new AuthenticationTicket(claimsPrincipal, "LDAP");            return AuthenticateResult.Success(ticket);        }        return AuthenticateResult.Fail("Invalid username or password.");    }    private bool AuthenticateWithLdap(string username, string password, string domain, out string userId)    {        userId = null;        try        {            var ldapPath = $"LDAP://{domain}";            using var de = new DirectoryEntry(ldapPath, username, password);            using var ds = new DirectorySearcher(de)            {                Filter = $"(sAMAccountName={username})"            };            var result = ds.FindOne();            if (result != null)            {                userId = result.Properties["sAMAccountName"][0].ToString(); // Or other user identifier                return true;            }        }        catch        {            // Log error or handle it        }        return false;    }}

Viewing all articles
Browse latest Browse all 4839

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>