Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blazor Authorization - AuthorizeRouteView and RedirectToLogin not working. #52063

Open
1 task done
christallire opened this issue Nov 15, 2023 · 48 comments
Open
1 task done
Assignees
Labels
area-auth Includes: Authn, Authz, OAuth, OIDC, Bearer Docs This issue tracks updating documentation feature-identity-ui
Milestone

Comments

@christallire
Copy link

christallire commented Nov 15, 2023

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

I've created Blazor WebApp via VS 2022 template with individual identity.
No matter what I do, <AuthorizeRouteView> and <NotAuthorized> are not working and redirect any request to /Account/Login. putting <p>not working</p> doesn't help.

Expected Behavior

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)">
            <NotAuthorized>
                <p>not authorized</p>
            </NotAuthorized>
        </AuthorizeRouteView>
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
</Router>

Prints "not authorized" when you click "Auth Required" in the template app

image

Steps To Reproduce

  1. Create Blazor Web App with Server Interactive render mode, and with Individual Account Authentication type.
  2. Replace from "<RedirectToLogin />" to "<p>not authorized</p>" in Routes.razor (to see if your redirection is from RedirectToLogin component)
  3. Click "Auth Required" in template app.

Exceptions (if any)

No response

.NET Version

8.0.100

Anything else?

This is a blocker since I was migrating .NET 7.0 app to .NET 8.0, but It behaves very differently.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-blazor Includes: Blazor, Razor Components label Nov 15, 2023
@appsolab
Copy link

Same here. Since RC1 I can't migrate without this issue.

@MackinnonBuck
Copy link
Member

@halter73 Would you be able to look into this?

@christallire
Copy link
Author

christallire commented Nov 16, 2023

Another thing I noticed Is that an authorization check (the route with [Authorize] Attribute) is done before the component lifecycle or Routing.
For an example. I used to put OnInitialized and handle some logic in what we now call Routes.razor. When I refresh the page, no routing or component lifecycle logic runs. Is this where we have the bug?

.NET 7.0
No auth - Route OnInitialized = YES
Req Auth- Route OnInitialized = YES

.NET 8.0
No auth - Route Oninitialized = YES
Req Auth - Route OnInitialized = NO

Upon investigating all other interactivity - the same thing happens when refresh. It looks like there's something with pipeline.

@christallire
Copy link
Author

christallire commented Nov 16, 2023

it seems the new 8.0 routing adds pages with [Authorization] to route, so that they have authorization metadata and can be checked with AuthorizationMiddleware if we prerender or first render (when we have HttpContext)

The request runs through pipelines, Invoking Authentication middleware first, and if this fails (no login, so always) - doing redirection defined in middleware.
But this is different, especially when we navigate with SPA and there's no Authentication middleware (obviously), and AuthenticationStateProvider is invoked instead of the middleware.

I think someone really messed this up.

edit: When I add JwtBearer authentication to the application they just throw 401 so authorization middleware it is.

@christallire christallire changed the title Blazor InteractiveServer Identity - AuthorizeRouteView and RedirectToLogin not working no matter what I do. Blazor Authorization - AuthorizeRouteView and RedirectToLogin not working. Nov 16, 2023
@christallire
Copy link
Author

christallire commented Nov 16, 2023

@MackinnonBuck can we urgently have a look into this? this seems serious because Authorization in blazor is basically broken.

@joecuevasjr
Copy link

joecuevasjr commented Nov 16, 2023

I'm experiencing the same issue as @christallire. This was working as expected in NET 7. In my case I'm using a Cookie for auth but I don't utilize the Cookie's options.LoginPath configuration. I prefer to use the <NotAuthorized> template directive.

@augustevn
Copy link

augustevn commented Nov 16, 2023

@halter73 @MackinnonBuck @mkArtakMSFT

I did some digging, it seems like the user Claims are no longer returned from /manage/info from the .MapIdentityApi<User>().

This change broke my app, worked in RC2 not in RTM. Is this intentional? Possibly related.

IdentityApiEndpointRouteBuilderExtensions.cs, line 455:


    private static async Task<InfoResponse> CreateInfoResponseAsync<TUser>(TUser user, UserManager<TUser> userManager)
        where TUser : class
    {
        return new()
        {
            Email = await userManager.GetEmailAsync(user) ?? throw new NotSupportedException("Users must have an email."),
            IsEmailConfirmed = await userManager.IsEmailConfirmedAsync(user),
        };
    }

@augustevn
Copy link

@christallire How do you implement the AuthenticationStateProvider and do you pass your claims to it? If so, could you check whether your claims are empty or not?

@christallire
Copy link
Author

christallire commented Nov 17, 2023

@christallire How do you implement the AuthenticationStateProvider and do you pass your claims to it? If so, could you check whether your claims are empty or not?

(edit: oh shoot sorry I thought you're asking me about my "original" implementation)

I haven't changed anything from the template project except RedirectToLogin part.

@christallire
Copy link
Author

christallire commented Nov 18, 2023

Well, I found a workaround by:
define following class and register it where server initializes

public class BlazorAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler
{
    public Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
    {
        return next(context);
    }
}

and handler:

services.AddSingleton<IAuthorizationMiddlewareResultHandler, BlazorAuthorizationMiddlewareResultHandler>();

This class will prevent redirection from the new .net 8 authorization middleware response.
The problem still exists, but we can at least we can use .NET 8 new feature the way we used to in Blazor and .NET 7.

You may need to separate endpoint routing other than blazor routes since it basically renders serverside authorization (via .AddAuthentication(...).AddJwtBearer(...)) ineffective.

hope this helps, enjoy .net 8. while the team fixes the problem.

@Kumima
Copy link

Kumima commented Nov 20, 2023

After investigation, I can understand it's by design now. But this is still a very weird behavior of navigation.
If the interactive is not ready, the app is matching Static Stuff Routes, the request route is managed by the pipeline. It will be redirected by CookieAuthentication* stuff. Only after the app is ready to be interactive, the interactive Routes component takes over the routing. If you refresh the browser manually, there is no ready interactive component.

This is just one of the problems that may arise. A worse scenario is the pages may flicker caused by this. Because the Static Response during Prerender may significantly differ from the Interactive Content. Check #51203 to see the behavior.

A deeper investigation is under #52176

@mkArtakMSFT mkArtakMSFT added Docs This issue tracks updating documentation and removed investigate labels Nov 20, 2023
@christallire
Copy link
Author

I'm afraid I have to disagree that this problem can be solved with documentation.

@eholman
Copy link

eholman commented Jan 8, 2024

Well, I found a workaround by: define following class and register it where server initializes

public class BlazorAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler
{
    public Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
    {
        return next(context);
    }
}

and handler:

services.AddSingleton<IAuthorizationMiddlewareResultHandler, BlazorAuthorizationMiddlewareResultHandler>();

This class will prevent redirection from the new .net 8 authorization middleware response. The problem still exists, but we can at least we can use .NET 8 new feature the way we used to in Blazor and .NET 7.

You may need to separate endpoint routing other than blazor routes since it basically renders serverside authorization (via .AddAuthentication(...).AddJwtBearer(...)) ineffective.

hope this helps, enjoy .net 8. while the team fixes the problem.

The Blazor Server template with .Net 8 and Identity worked fine out of the box for me. But with the Jwt-Bearer as authentication the symptoms where exactly the same. The 401 http response code was thrown instead, before the AuthorizeRouteView component kicked in and isn't able to redirect to login this way.

The workaround of above works like a charm. I unfortunately don't have time to dig in further why this works.

This is my program minimal api authentication code:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    options.Events = new JwtBearerEvents
    {
        OnMessageReceived = context =>
        {
            if (context.Request.Cookies.TryGetValue("token", out var token))
            {
                context.Token = token;
            }

            return Task.CompletedTask;
        }
    };

    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateAudience = false,
        ValidateIssuerSigningKey = false,
        ValidateIssuer = false,
        SignatureValidator = (token, parameters) => new Microsoft.IdentityModel.JsonWebTokens.JsonWebToken(token)
    };
});

@jorg3roch4
Copy link

Well, I found a workaround by: define following class and register it where server initializes

public class BlazorAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler
{
    public Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
    {
        return next(context);
    }
}

and handler:

services.AddSingleton<IAuthorizationMiddlewareResultHandler, BlazorAuthorizationMiddlewareResultHandler>();

This class will prevent redirection from the new .net 8 authorization middleware response. The problem still exists, but we can at least we can use .NET 8 new feature the way we used to in Blazor and .NET 7.
You may need to separate endpoint routing other than blazor routes since it basically renders serverside authorization (via .AddAuthentication(...).AddJwtBearer(...)) ineffective.
hope this helps, enjoy .net 8. while the team fixes the problem.

The Blazor Server template with .Net 8 and Identity worked fine out of the box for me. But with the Jwt-Bearer as authentication the symptoms where exactly the same. The 401 http response code was thrown instead, before the AuthorizeRouteView component kicked in and isn't able to redirect to login this way.

The workaround of above works like a charm. I unfortunately don't have time to dig in further why this works.

This is my program minimal api authentication code:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    options.Events = new JwtBearerEvents
    {
        OnMessageReceived = context =>
        {
            if (context.Request.Cookies.TryGetValue("token", out var token))
            {
                context.Token = token;
            }

            return Task.CompletedTask;
        }
    };

    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateAudience = false,
        ValidateIssuerSigningKey = false,
        ValidateIssuer = false,
        SignatureValidator = (token, parameters) => new Microsoft.IdentityModel.JsonWebTokens.JsonWebToken(token)
    };
});

You don't need that on the client side; the same happened to me. I removed it, and it worked perfectly. It's only used in the API code.

@Appli4Ever
Copy link

Appli4Ever commented May 16, 2024

I have a hosted Blazor WASM app in Asp.Net Core. I have prerendering enabled. My problem was, that builder.Services.AddCascadingAuthenticationState(); is not the same as CascadingAuthenticationState Componente in the Routes.razor despite being described as such. The differenz is while prerendering, the GetAuthenticationStateAsync() method is not called when adding the CascadingAuthenticationState via the ServiceCollection.

Since I have some specially authentication (anonymous user are being logged in with cookies) this was an essential part of my solution.

@Liandrel
Copy link

Liandrel commented Jun 2, 2024

If someone still struggles with this problem I found another workaround.

services.ConfigureApplicationCookie(opts => { opts.LoginPath = new PathString("/authorize/login"); });

With this workaround when accessing page with [Authorize] attribute it redirects to "/autorize/login" instead of "Account/Login"

Still it would be better if this was fixed on blazor framework level and AuthorizeRouteView worked like it should do

@cn-ml
Copy link

cn-ml commented Jun 3, 2024

I also just wasted a couple hours on debugging my requests until i found this. I just wanted to do some experimentations with blazor, but this is a real bummer.

@sinoergin
Copy link

it was working from me below that but #19855 is good idea.

..AddCookie(IdentityConstants.ApplicationScheme, opt => opt.LoginPath = "routeUrl")

@Usergitbit
Copy link

Usergitbit commented Jul 3, 2024

@flennic I'm also doing OIDC with IdentityServer and I don't seem to need anything more than

public class BlazorAuthorizationMiddlewareResultHandler() : IAuthorizationMiddlewareResultHandler
{
    public async Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
    {
        await next(context);
    }
}

In which case did you need that? User not logged in trying to access a page that requires authorization? How do you have the redirect to login provider implemented?

Also, is there any plan on making Blazor Server easier to integrate with OIDC? I'm doing some hacky stuff in order to refresh the access token and then get it updated in the cookie.

@flennic
Copy link

flennic commented Jul 11, 2024

@Usergitbit When combining an API and Blazor in the same project. I now do not remember the exact setup, but the API layer middleware comes before the request gets to Blazor. So e.g. "Unauthorized" should not be blocked by the API, but should be forwarded to Blazor to show a "Hey, you do not have permission to see this page" message. But "Challanged" should respond with the correct OAuth 2.0 / OIDC flow and not forward the request to Blazor.

So the redirect to the identity provider is the default OIDC ASP.NET implementation, it is not handled by Blazor.

And regarding you last point, I agree. The integration for projects where API and Blazor are mixed should be improved. Also I do not understand why refresh token generation is not enabled (or at least implemented) by default as there actually exist Microsoft examples which can be copy and pasted, maybe with minor adjustments which cloud be put into an Action<RefreshOptions> extension method.

There are even more quirks, e.g. only OAuth 2.0 (for example for an API) where only the JWKS endpoint is used, is also not supported by default. A friendly user provides his own library for fixing that, I think it should be part of the stack the same as OIDC. But there are probably more reasons for it why decisions are made as they are, I only see it from my perspective.

@Joaomfcarmo
Copy link

Well, I found a workaround by: define following class and register it where server initializes

public class BlazorAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler
{
    public Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
    {
        return next(context);
    }
}

and handler:

services.AddSingleton<IAuthorizationMiddlewareResultHandler, BlazorAuthorizationMiddlewareResultHandler>();

This class will prevent redirection from the new .net 8 authorization middleware response. The problem still exists, but we can at least we can use .NET 8 new feature the way we used to in Blazor and .NET 7.
You may need to separate endpoint routing other than blazor routes since it basically renders server-side authorization (via .AddAuthentication(...).AddJwtBearer(...)) ineffective.
hope this helps, enjoy .net 8. while the team fixes the problem.

Encountering the same problem and ended up using your recommended workaround, so thanks a lot for the hint. This unfortunately has some implications. The project I am working on using OIDC for logging in users, so the authorization result Challenged still needs to intercept to call for the OAuth 2.0 redirect to the identity provider. I have solved this by making this adjustment:

public async Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
{
    if (authorizeResult.Challenged)
        await _defaultHandler.HandleAsync(next, context, policy, authorizeResult);
    else
        await next(context);
}

However, my biggest concern is the implication which you already mentioned. This more or less disables the ASP.NET authorization layer, so if you have an API you must move that one to another project. I would like to re-use the cookie session but this is not as straight forward anymore. I will look into using a shared state for the cookie data protection and might be able to re-use the cookie when Blazor project and API are running under the same domain. Another way would be to either re-use the id_token or access_token for the API. Probably the id_token because this is the token meant to be for the application and not the underlying APIs (so a different API layer). So to say the JWT bearer.

Nevertheless—even assuming finding a good solution—this definitely does not seem optimal and might be difficult for not so experienced programmers. It would be nice if the ASP.NET middleware somehow knows when a request is meant to be routed to Blazor. I have not looked too much into it yet, but as HttpContext, AuthorizationPolicy and PolicyAuthorizationResult are available one could probably build something here.

The main thing is, it does not really feel "round", it would be nice if Blazor projects with authentication and authorization would be carved into one stone. I do not have a good solution here, but hope that I could lay out the problem a bit more in detail.

Edit: On another note, I also noticed another issue if you use Blazor SSR and WebAssembly only for interactivity. In this case, no AuthenticationStateProvider is registered, which means that you will get a runtime exception when using builder.Services.AddCascadingAuthenticationState();. It feels that a default implementation mapping the authentication state, the same way at the Blazor server project uses, would suffice as a good starting point. It feels that there are so many "manual" tweaks one has to do to get a standard setup "Blazor with OIDC" to work properly.

Thanks for reading!

Hi, can you show me your _defaultHandler declaration, please.

@flennic
Copy link

flennic commented Jul 18, 2024

@Joaomfcarmo It is a field in the IAuthorizationMiddlewareResultHandler declared like this:

private readonly AuthorizationMiddlewareResultHandler _defaultHander = new();

@killyp
Copy link

killyp commented Jul 20, 2024

Is there official documentation on this yet? I am still using the IAuthorizationMiddlewareResultHandler workaround on my Blazor Webapp to get the NotAuthorized component to trigger and redirect to a landing page.

@danieldespainTLS
Copy link

The template code is very misleading. Looking at Routes.razor makes it look like the <RedirectToLogin /> component is where the "magic" happens - which is the way it used to be. As mentioned, that component isn't involved anymore (so why is it in the Routes template??). You can open up the RedirectToLogin.razor file and change the NavigateTo(...) path but it will still take you to Account/Login?…. You can put a breakpoint in that component, and it never gets hit.

The solution from @Liandrel about services.ConfigureApplicationCookie(…) is what finally helped me out - after wasting way too many hours.

@Appli4Ever
Copy link

The template code is very misleading. Looking at Routes.razor makes it look like the <RedirectToLogin /> component is where the "magic" happens - which is the way it used to be. As mentioned, that component isn't involved anymore (so why is it in the Routes template??). You can open up the RedirectToLogin.razor file and change the NavigateTo(...) path but it will still take you to Account/Login?…. You can put a breakpoint in that component, and it never gets hit.

The solution from @Liandrel about services.ConfigureApplicationCookie(…) is what finally helped me out - after wasting way too many hours.

So I know what the "problem" semes to be: Prerender

  1. Create a new Blazor Web App
  2. Select Individual Accounts
  3. Select Interactive Render Mode
  4. Change NavigateTo(...) to counter page (or anything else)
  5. Start project.
  6. You will get redirected to counter always.

Something to look out for, if you have prerender enabled:
I does not use RedirectToLogin.razor when you prerender a page with @attribute [Authorize].

This is because:

app.MapRazorComponents<App>()
    .[your render modes]
    .AddAdditionalAssemblies(typeof(test.Client._Imports).Assembly); 

redirects you to the login page, befor App renders Routes.

Simple Fix:

app.MapRazorComponents<App>()
    .[your render modes]
    .AddAdditionalAssemblies(typeof(test.Client._Imports).Assembly)
    .AllowAnonymous();

@Appli4Ever
Copy link

Appli4Ever commented Jul 26, 2024

To be more specific: Asp.Net Core Redirects you while prerender, not Blazor. If you call .AllowAnonymous() App.razor will prerender anonymous and Routes will execute RedirectToLogin or anything else in

<NotAuthorized>
...
 </NotAuthorized>

Use this: if you want to change the behavior of Asp.Net core redirecting ur API calls:

.AddIdentityCookies(o =>
{
    o.ApplicationCookie?.Configure(
        co =>
        {
            co.Events.OnRedirectToLogin = e =>
            {
                e.Response.StatusCode = 401;
                return Task.CompletedTask;
            };
            co.Events.OnRedirectToAccessDenied = e =>
            {
                e.Response.StatusCode = 401;
                return Task.CompletedTask;
            };
            ...
        });
});

This way, API Endpoints wont send back a redirect result when called from Blazor WASM.

@Liandrel
Copy link

That solution works like a charm. I didn't think about it initially, but it makes perfect sense that it was redirecting to the default login path because of the pre-render on the server. And by allowing all paths to be anonymous, it reaches App.razor and displays the NotAuthorized content.

@Mecerburn
Copy link

Mecerburn commented Aug 6, 2024

I had the same issue as described in this post
#52317
But instead of doing this overwrite
public class BlazorAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler { public Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult) { return next(context); } }

I went with making splash screen on routes rather
Screenshot 2024-08-06 123804

This way the refresh can happen and after render my javascript interop that reads session for token on auth will work. Wanted to post on initial post but it was close. Hope someone finds this as an helpfull way to workaround the issue and is a better work around without messing with the rest of the auth

@nemtajo
Copy link

nemtajo commented Aug 23, 2024

I have the same problem. I tried creating custom auth library with Cookie authentication scheme, but it seems whatever is in the Router is not rendered at all.

In all my components where AuthorizeView is used, even though all custom cookies are deleted and the user is logged out via
await _httpContextAccessor.HttpContext.SignOutAsync(LingoDub.Blazor.Auth.Model.Constants.AuthenticationScheme, new AuthenticationProperties { RedirectUri = "/" });
The components always render Authorized content...

It would be great if Microsoft provided example implementation of different custom sign in options (openid, jwt bearer, cookie, etc) on both WebAssembly and Server hosting models.

@Mecerburn
Copy link

I have the same problem. I tried creating custom auth library with Cookie authentication scheme, but it seems whatever is in the Router is not rendered at all.

In all my components where AuthorizeView is used, even though all custom cookies are deleted and the user is logged out via await _httpContextAccessor.HttpContext.SignOutAsync(LingoDub.Blazor.Auth.Model.Constants.AuthenticationScheme, new AuthenticationProperties { RedirectUri = "/" }); The components always render Authorized content...

It would be great if Microsoft provided example implementation of different custom sign in options (openid, jwt bearer, cookie, etc) on both WebAssembly and Server hosting models.

If you use the browser storage then the components need to complete the rendering to be able to access the storage. That is the issue, so adding the loading as I given in the image will sort that out. When you logout are you calling the NotifyAuthenticationStateChanged so that blazor can rerender? For me calling that logs out and no more authorized views show. Only issue is using the browser storage to read and write the auth tokens or cookies, this can be worked around with the loading stuff I shared

@nemtajo
Copy link

nemtajo commented Sep 15, 2024

@Mecerburn Thank you for sharing a possible solution. I think wrapping Router in an if statement, whose condition is changed only after rendering the page, disables prerendering completely for the whole webapp, and therefore might not be a suitable solution for everyone. Afterall, I want to have prerendering enabled for some pages - it is an awesome feature to have.

I discovered that my issue would be resolved with the workaround proposed above, if I didn't have additional problems in my auth library. I just want to mention the solution, in case someone else wants to implement auth library of their own. There is a very unclear behaviour of ClaimsIdentity constructor, depending on which parameters you pass in, you will get IsAuthenticated property set to always true or always false. I hope that ASP.NET Core team cleans up this confusion. For reference, this blog helped me tackle my problem:
https://www.benday.com/2021/08/13/3-common-problems-with-claimsidentity-and-claimsprincipal-in-asp-net-core/

@mkArtakMSFT mkArtakMSFT removed the area-blazor Includes: Blazor, Razor Components label Sep 16, 2024
@mkArtakMSFT mkArtakMSFT modified the milestones: 9.0-rc2, 9.0.0 Sep 25, 2024
@Woudjee
Copy link

Woudjee commented Oct 31, 2024

To be more specific: Asp.Net Core Redirects you while prerender, not Blazor. If you call .AllowAnonymous() App.razor will prerender anonymous and Routes will execute RedirectToLogin or anything else in

<NotAuthorized>
...
 </NotAuthorized>

Use this: if you want to change the behavior of Asp.Net core redirecting ur API calls:

.AddIdentityCookies(o =>
{
    o.ApplicationCookie?.Configure(
        co =>
        {
            co.Events.OnRedirectToLogin = e =>
            {
                e.Response.StatusCode = 401;
                return Task.CompletedTask;
            };
            co.Events.OnRedirectToAccessDenied = e =>
            {
                e.Response.StatusCode = 401;
                return Task.CompletedTask;
            };
            ...
        });
});

This way, API Endpoints wont send back a redirect result when called from Blazor WASM.

@Appli4Ever I believe your cookie approach is the best solution. However, when attempting it myself, it does not work for me. I also tried setting the RedirectUri, but this also seems to not be doing anything. Any suggestions what else I could do?

@Zzzzjle
Copy link

Zzzzjle commented Nov 9, 2024

app.MapRazorComponents()
.[your render modes]
.AddAdditionalAssemblies(typeof(test.Client._Imports).Assembly)
.AllowAnonymous();

Thanks, this works for me.

@Appli4Ever
Copy link

@Woudjee what exactly did not work? Can you share some code?

@Woudjee
Copy link

Woudjee commented Nov 9, 2024 via email

@Appli4Ever
Copy link

Appli4Ever commented Nov 9, 2024

The template code is very misleading. Looking at Routes.razor makes it look like the <RedirectToLogin /> component is where the "magic" happens - which is the way it used to be. As mentioned, that component isn't involved anymore (so why is it in the Routes template??). You can open up the RedirectToLogin.razor file and change the NavigateTo(...) path but it will still take you to Account/Login?…. You can put a breakpoint in that component, and it never gets hit.

The solution from @Liandrel about services.ConfigureApplicationCookie(…) is what finally helped me out - after wasting way too many hours.

So I know what the "problem" semes to be: Prerender

  1. Create a new Blazor Web App

  2. Select Individual Accounts

  3. Select Interactive Render Mode

  4. Change NavigateTo(...) to counter page (or anything else)

  5. Start project.

  6. You will get redirected to counter always.

Something to look out for, if you have prerender enabled:

I does not use RedirectToLogin.razor when you prerender a page with @attribute [Authorize].

This is because:


app.MapRazorComponents<App>()

    .[your render modes]

    .AddAdditionalAssemblies(typeof(test.Client._Imports).Assembly); 

redirects you to the login page, befor App renders Routes.

Simple Fix:


app.MapRazorComponents<App>()

    .[your render modes]

    .AddAdditionalAssemblies(typeof(test.Client._Imports).Assembly)

    .AllowAnonymous();

I recently published a blogpost about this with video showing it: https://www.databinding.net/prerender-mit-blazor-webassembly-wasm-in-asp-net-core-8-teil-3/

It is in german but I am sure your browser can translate it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-auth Includes: Authn, Authz, OAuth, OIDC, Bearer Docs This issue tracks updating documentation feature-identity-ui
Projects
None yet
Development

No branches or pull requests