Reputation: 21
I am still a junior working in .NET.
This is my first time trying to implement authentication and authorization without identity in Blazor Web App. My current project is using InteractiveServerRenderMode and global interactivity and it seems the httpContext always return null
as I followed this tutorial on Youtube. I just confused as I have followed each of the steps given.
The output I expected that the Authenticate is going to work but it did not turned out as expected from the tutorial I have followed.
For the sign up page, I am using MudBlazor as the UI.
<MudGrid Justify="Justify.Center" AlignItems="AlignItems.Center" MaxWidth=MudBlazor.MaxWidth.False Style="height: calc(100vh - 64px); display: flex; overflow: -moz-hidden-unscrollable;">
<MudHidden Breakpoint="Breakpoint.MdAndUp" Invert="true">
<MudItem xs="12" md="7" lg="7" Style="background-image: url('img/scrapitem.jpg'); background-size: cover; background-position: center; height: 100%;"></MudItem>
</MudHidden>
<MudItem xs="12" md="5" lg="5" Class="d-flex justify-center align-center" Style="height: 100%;">
<MudCard Elevation="25" Class="rounded-lg pa-4" Style="width: 100%; max-width: 500px;">
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h6" Style="color: black;" GutterBottom="true">Log Masuk /<MudElement HtmlTag="i"> Login</MudElement></MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<EditForm Model="user" OnValidSubmit="Authenticate" FormName="LoginForm">
<DataAnnotationsValidator />
<MudTextField Label="Email" Required="true" @bind-Value="user.EMAIL" For="@(() => user.EMAIL)" />
<MudTextField Label="Password" InputType="InputType.Password" Required="true" @bind-Value="user.PASSWORD" For="@(() => user.PASSWORD)" />
</EditForm>
</MudCardContent>
<MudCardActions Class="d-flex justify-between">
<MudButton ButtonType="MudBlazor.ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" @onclick="Authenticate">Login</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Secondary" Class="ml-2" @onclick="SignUp">Sign Up</MudButton>
</MudCardActions>
<MudCardActions>
<MudButton Variant="Variant.Text" Color="Color.Tertiary">Forgot Password?</MudButton>
</MudCardActions>
</MudCard>
</MudItem>
</MudGrid>
Below is the @code part:
@code {
[CascadingParameter]
public HttpContext? httpContext { get; set; }
[SupplyParameterFromForm]
public USER user { get; set; } = new();
private bool success;
private string errorMessage;
private async Task Authenticate()
{
var authenticatedUser = await loginService.AuthenticateAsync(user.EMAIL, user.PASSWORD);
if (authenticatedUser is null || authenticatedUser.PASSWORD != user.PASSWORD)
{
errorMessage = "Invalid username or password";
return;
}
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, authenticatedUser.EMAIL),
new Claim(ClaimTypes.Role, authenticatedUser.ROLE)
};
//Add policies
var userPolicies = await dataContext.USER_POLICY.Where(x => x.USER_ID == authenticatedUser.ID && x.IS_ENABLED).ToListAsync();
foreach (var userPolicy in userPolicies)
claims.Add(new Claim(userPolicy.USERPOLICY, "true"));
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var principal = new ClaimsPrincipal(identity);
await httpContext!.SignInAsync(principal);
if(authenticatedUser.ROLE == "CommonUser")
{
navigationManager.NavigateTo("/dashboardCompany");
}
else if (authenticatedUser.ROLE == "Enforcer")
{
navigationManager.NavigateTo("/dashboardAdmin");
}
}
private async Task SignUp()
{
navigationManager.NavigateTo("/signup");
}
}
Upvotes: 2
Views: 485
Reputation: 8631
In this video, the tutorial uses InteractiveServerRenderMode and per page/component interactivity. So when not specifying @rendermode InteractiveServer
, the page will always use server static rendering(SSR) by default.
But if you set it to global. Every page will be InteractiverServer by default.
The problem is the HttpContext is not null only in SSR mode. https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-8.0#ihttpcontextaccessorhttpcontext-in-razor-components-blazor.
So basically you need to give up any "direct interactive" usage. Such as the @onclick="SignUp"
. The only way to make button work with c# in SSR is "submit form/editform". So even you disable ServerInteractive, OnValidSubmit="Authenticate"
will still work as the video does.
If you want a SignUp entrance in this SSR page. Try don't use "onclick", but use "href" instead. Such as
<NavLink class="nav-link" href="/signup">
Upvotes: 0