abbas-h
abbas-h

Reputation: 450

blazor server authentication dont work with httpcontext cookie

i want authorize user with api controller and save claims to cookie

and after that authorize my blazor server with it

this is my code for api Controller

public async Task<IActionResult> Login([FromBody] userPassModel userPass)
        {
            try
            {

                DIMAuthUser user = await authService.GetUser(userPass.UserName);
                if (user == null) return Unauthorized();
                bool resCheck = await authService.CheckUserCredentialAsync(userPass.UserName, userPass.Password);
                if (resCheck == false) return Unauthorized();
                ClaimsPrincipal principal = new ClaimsPrincipal(new ClaimsIdentity(user.AllSettedClaims, CookieAuthenticationDefaults.AuthenticationScheme));
                await HttpContext.SignInAsync(principal);
                return Ok();
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message,this);
                return StatusCode(500);
            }
        }

user successfully loggin and cookie sent back to user ... but when i want redirect login page to main page my blazor server said not authorize

this is login page code

async Task OnClickLogin()
        {
            if (string.IsNullOrWhiteSpace(username)) return;
            if (string.IsNullOrWhiteSpace(password)) return;
            
            HttpResponseMessage mess = await HttpClient.PostAsJsonAsync( "/api/Athentication/login", new userPassModel
            {
                UserName=username,
                Password=password
            });
            if (mess.IsSuccessStatusCode)
            {
                if (mess.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    NavigationManager.NavigateTo("/");
                    return;
                }
                else if (mess.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                {
                    await SweetAlert2Service.ShowWarning("user or pass incorrect");
                    return;
                }
            }
            await SweetAlert2Service.ShowWarning("somthing went wrong");
        }

and this is main poge code

@page "/"
@attribute [Authorize]
<AuthorizeView>
    <Authorized>
        Authed
    </Authorized>
    <NotAuthorized>
        Noted
    </NotAuthorized>
</AuthorizeView>
<h1>INDEX</h1>

and this is program.cs

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
app.UseStaticFiles();
app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

after successful login with controller and redirected to main page show me "Noted"

i want user identity in cookie that can log activity in middleware with httpcontext ...

Upvotes: 1

Views: 2115

Answers (2)

Michel
Michel

Reputation: 68

You cannot create a cookie this way because everything happens on the server side and the httpcontext is not that of the user. Click --> signalR (server) --> httpClient (server) --> set cookie. The user needs to be the one to initiate the login request so the httpcontext is correct and the cookie can be set.

I achieved this by doing it via the JSInterop, so you create 2 javascript functions, one for the Login and one for the logout (dont forget to export the functions). And call them via the JSInterop like so:

private async Task LoginOnClick()
{
    var authModule = await _jsRuntime.InvokeAsync<IJSObjectReference>("import", "./js/auth.js");
    var result = await authModule.InvokeAsync<LoginResultDto>("Login", "[email protected]", "test123");

    if(result.IsSuccess)
    {
        _navManager.NavigateTo("", true);
    }
}
private async Task LogoutOnClick()
{
    var authModule = await _jsRuntime.InvokeAsync<IJSObjectReference>("import", "./js/auth.js");
    await authModule.InvokeVoidAsync("Logout");
    _navManager.NavigateTo("/login", true);
}

Upvotes: 0

abbas-h
abbas-h

Reputation: 450

Blazor Don't Completely access To httpContext So if You Want user Cookie Authentication that use httpcontex don't Make Login page with blazor ( make login page with Razor Or MVC Page )

in previously i sent authentication request from blazor page to controller and after that i navigate user to index, that is wrong ...

before every blazor page, authentication process must be done and after that navigate user to blazor page ...

so i must authentication process out of blazor pages and after that navigate to blazor pages

so :

i make a razor page in my Blazor project :

enter image description here

and all athentication logic added to it

public async Task<IActionResult> OnPost()
        {
            string username = Request.Form["username"].FirstOrDefault();
            string password = Request.Form["password"].FirstOrDefault();
            if(string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password)) return Page();
            DIMAuthUser user = await authService.GetUser(username);
            if (user == null)
            {
                AuthResult = "Wrong User";
                return Page();
            }
            bool resCred = await authService.CheckUserCredentialAsync(username, password);
            if (resCred == false)
            {
                AuthResult = "Wrong USer Or Password";
                return Page();
            }
            else
            {
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
                    user.ClaimsPrincipal);
                authService.AuthedUser = user;
                Log.Logger
                    .ForContext("Username",user.UserName)
                    .Information($"{user.UserName} Logged In ...",this);
                return Redirect("/");
            }
        }

Upvotes: 2

Related Questions