1

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 ...

abbas-h
  • 392
  • 1
  • 4
  • 18
  • If possible, you could debug the code and check the value of the cookie. See whether it has properly assigned value to it. It could be possible that the cookie is empty or not properly assigned could cause the said issue. – Deepak-MSFT Feb 21 '22 at 06:10
  • @Deepak-MSFT i checked and cookie is good.. problem is after authentication success and when i want navigate to "/" ... the auth cookie dont sent back to reques ... – abbas-h Feb 21 '22 at 08:11

2 Answers2

1

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("/");
            }
        }
abbas-h
  • 392
  • 1
  • 4
  • 18
  • 1
    Thanks for sharing the solution to the issue. I would suggest you accept your own answer. It would help other community members in the future with similar issues. – Deepak-MSFT Mar 04 '22 at 08:01
0

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", "test@test.com", "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);
}
Michel
  • 38
  • 1
  • 7