admin管理员组文章数量:1315225
I am trying to implement JWT auth on a Blazor App 9 (using Server interactivity) but I can't seem to get app to route to the Login page when the user first starts the app. The Index has an [Authorize] attribute and when i run the app i get a "Page isn't working right now, error 401" instead of redirecting me to the Login page. Going to an unsecured page before trying to navigate to index works. Here is my Routes code
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<RedirectToLogin />
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
I have also added the following code to try to force it but the OnIntitializedAsync function isn't even being called.
protected override async Task OnInitializedAsync()
{
var authState = await AuthStateProvider.GetAuthenticationStateAsync();
if (!authState.User.Identity.IsAuthenticated)
{
NavigationManager.NavigateTo("login");
}
}
The component has a simple navigation manager on the init function that routes to /login.
It seems that I have to re-learn blazor after every update.
Edit 1 I am using the builder.Services.AddCascadingAuthenticationState(); in the Program file instead of the surrounding the Router
I am trying to implement JWT auth on a Blazor App 9 (using Server interactivity) but I can't seem to get app to route to the Login page when the user first starts the app. The Index has an [Authorize] attribute and when i run the app i get a "Page isn't working right now, error 401" instead of redirecting me to the Login page. Going to an unsecured page before trying to navigate to index works. Here is my Routes code
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<RedirectToLogin />
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
I have also added the following code to try to force it but the OnIntitializedAsync function isn't even being called.
protected override async Task OnInitializedAsync()
{
var authState = await AuthStateProvider.GetAuthenticationStateAsync();
if (!authState.User.Identity.IsAuthenticated)
{
NavigationManager.NavigateTo("login");
}
}
The component has a simple navigation manager on the init function that routes to /login.
It seems that I have to re-learn blazor after every update.
Edit 1 I am using the builder.Services.AddCascadingAuthenticationState(); in the Program file instead of the surrounding the Router
Share Improve this question edited Feb 1 at 11:47 Cuvin Stefan asked Jan 30 at 7:22 Cuvin StefanCuvin Stefan 631 gold badge1 silver badge6 bronze badges 02 Answers
Reset to default 0I have also added the following code to try to force it but the OnIntitializedAsync function isn't even being called.
If the OnIntitializedAsync method in your RedirectToLogin
component is not called,it was the http request to "/index"
was blocked by authentication middleware
you may try configure a redirect path when you add Authentication related services
or add a middleware like:
app.Use(async (context,next) =>
{
await next.Invoke();
if(context.Response.StatusCode==StatusCodes.Status401Unauthorized)
{
context.Response.Redirect("{your login path with return url}");
}
});
before authentication middleware
After taking a look at the Identity Individual Users template for Blazor Web App 9 (with Server/Global render mode) I've managed to make JWT Auth Work!
Step 1 - Program.cs All the code required for authentication / Authorization is as follows:
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "your-issuer",
ValidAudience = "your-audience",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your-secr479458959et-ke41882928418191y1"))
};
options.Events = new JwtBearerEvents
{
OnChallenge = context =>
{
context.HandleResponse();
context.Response.Redirect("/login");
return Task.CompletedTask;
}
};
});
builder.Services.AddAuthorizationCore();
Also add:
app.UseAuthentication();
app.UseAuthorization();
Step 2 - CustomAuthenticationStateProvider I've used BlazoredLocalStorage to store my Token, but anything else can be used
public class CustomAuthenticationStateProvider(ILocalStorageService localStorageService) : AuthenticationStateProvider
{
private readonly ILocalStorageService _localStorage = localStorageService;
private const string TokenKey = "authToken";
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
try
{
var token = await _localStorage.GetItemAsync<string>(TokenKey);
if (string.IsNullOrWhiteSpace(token))
{
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
var claims = ParseClaimsFromJwt(token);
var identity = new ClaimsIdentity(claims, "jwt");
var user = new ClaimsPrincipal(identity);
return new AuthenticationState(user);
}
catch (JSException ex)
{
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
catch (Exception)
{
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
}
public void NotifyUserAuthentication(string token)
{
var claims = ParseClaimsFromJwt(token);
var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(claims, "jwt"));
var authState = Task.FromResult(new AuthenticationState(authenticatedUser));
NotifyAuthenticationStateChanged(authState);
}
public void NotifyUserLogout()
{
var anonymousUser = new ClaimsPrincipal(new ClaimsIdentity());
var authState = Task.FromResult(new AuthenticationState(anonymousUser));
NotifyAuthenticationStateChanged(authState);
}
private static IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
{
var handler = new JwtSecurityTokenHandler();
var token = handler.ReadJwtToken(jwt);
return token.Claims;
}
}
Step 3 - Modify the App.razor file No clue what this actually does but i guess it is required
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
<link rel="stylesheet" href="@Assets["app.css"]" />
<link rel="stylesheet" href="@Assets["BlazorApp1-Jwt.styles.css"]" />
<ImportMap />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet @rendermode="PageRenderMode" />
</head>
<body>
<Routes @rendermode="PageRenderMode" />
<script src="_framework/blazor.web.js"></script>
</body>
</html>
@code {
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
private IComponentRenderMode? PageRenderMode =>
HttpContext.AcceptsInteractiveRouting() ? InteractiveServer : null;
}
Step 4 - Configure the Routes.razor file
@using Microsoft.AspNetCore.Components.Authorization
<Router AppAssembly="typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)">
<NotAuthorized>
<RedirectToLogin />
</NotAuthorized>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>
This code is missing the NotFound attribute becuase it is no longer being used by Blazor Web App 8 and 9
Step 5 - RedirectToLogin create a component that redirects to the Login page when the user is trying to access a secured page
@inject NavigationManager NavigationManager
@code {
protected override void OnInitialized()
{
NavigationManager.NavigateTo("login", forceLoad: true);
}
}
Step 6 - Login the User Aquire your Token, save it in LocalStorage (or handle it however you want) and Notify the AuthStateProvider
((CustomAuthenticationStateProvider)AuthenticationStateProvider).NotifyUserAuthentication(token);
Step 7 - Secure Pages
Use the Authorize attribute on any page you want secured
Note: I am no expert. This is how i got it to work.. Please write / redirect to a better solution if what i wrote here is terrible code
本文标签: routesBlazor Web App 9 (ServerGloabl) JWT AuthenticationStack Overflow
版权声明:本文标题:routes - Blazor Web App 9 (ServerGloabl) JWT Authentication - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741980380a2408360.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论