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

Blazor Web app, understanding of Authentication flow

$
0
0

I am using blazor Web App for a project, I am using InteractiveAutoRenderMode and in my server project i have controllers that i am calling from client project. i have written a CustomHttpClientHandler which will attach the JWT token to every outgoing request.

In my login endpoint, i return JWT token, and set cookie as well, so for blazor SSR pages it uses cookies and for interactive pages it uses token, and my controllers are secured with jwt schema i.e

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

I have also written a CustomAuthenticationStateProvider which returns me AuthenticationState from either IHttpContextAccessor or from JWT token depending upon if code is running for SSR, Blazor server or Blazor WASM mode.

here is what it looks like.

public class CustomAuthenticationStateProvider : AuthenticationStateProvider{    private readonly ILocalStorageService localStorageService;    private readonly IHttpContextAccessor httpContextAccessor;    public CustomAuthenticationStateProvider(ILocalStorageService LocalStorageService, IHttpContextAccessor httpContextAccessor)    {        localStorageService = LocalStorageService;        this.httpContextAccessor = httpContextAccessor;    }    public override async Task<AuthenticationState> GetAuthenticationStateAsync()    {        //running for SSR & blazor server mode        if(httpContextAccessor.HttpContext != null)        {            var claims = httpContextAccessor.HttpContext.User.Claims;            if(claims.Count() == 0)            {                return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));            }            var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "jwt"));            var authState = new AuthenticationState(claimsPrincipal);            return authState;        }        //getting from token.        var authStateTask = GetAuthState();        return await authStateTask;    }}

the above if check if(httpContextAccessor.HttpContext != null) is currently running for both SSR pages and blazor server Mode, when running in blazor server and accessing it in my controller endpoint which is authorized using [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] it shows user is authenticated and return AuthenticationState, all fine, but now if i do not use the Authorize attribute and everything else is same, it shows that the user is not authenticated and do not returns any claims.

after reserching and debugging i find out that it might be because when i send http request to controller endpoint, and the code is running in blazor server, the http call is actually getting sent from server to server hence no cookies are attached, but then how come my CustomHttpClientHandler is attaching the token by accessing browser storage, and how come when i apply Authorize attribute the httpContext starts showing claims?

Currently for testing i switched from InteractiveAutoRenderMode to InteractiveServerRenderMode to figure out how all of this is working.

below is my CustomHttpClientHandler. NOTE: i have injected IHttpContextAccessor here only for debugging purpose.

public class CustomHttpClientHandler : HttpClientHandler{    private readonly ILocalStorageService localStorageService;    private readonly NavigationManager navigationManager;    private readonly ISnackbar snackbar;    private readonly IHttpContextAccessor httpContextAccessor;    public ILoaderService loaderService { get; set; }    public CustomHttpClientHandler(ILocalStorageService localStorageService, NavigationManager NavigationManager, ILoaderService loaderService, ISnackbar Snackbar, IHttpContextAccessor httpContextAccessor)    {        this.localStorageService = localStorageService;        navigationManager = NavigationManager;        this.loaderService = loaderService;        snackbar = Snackbar;        this.httpContextAccessor = httpContextAccessor;    }    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)    {        var token = await localStorageService.GetItemAsStringAsync(Auth.Token.ToString());        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);        //it is null in WASM mode, but in Server mode it is not null, and have the correct claims        //but token is also available in server mode? how, if it is running in server?        //and if it is running it in browser, why cookie is not being attached?        var x = httpContextAccessor?.HttpContext;        if(x == null)        {        }        var response = await base.SendAsync(request, cancellationToken);        return response;    }}

becuase token is getting attached to all http request so i debug my CustomHttpClientHandler and injected IHttpContextAccessor and again in blazor server mode it shows that httpContext is available and has the correct claims? (because it is running on blazor server) but how come then token is also available from browser storage? and when i run it in InteractiveWebAssemblyRenderMode it show httpContext is null.


Viewing all articles
Browse latest Browse all 4839

Trending Articles



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