What is Blazor? A Tutorial on Building Web Apps with Authentication

Hi Andrea,
I really appreciate you continuing to respond to all these messages! I hope you find a lead. I can’t find it myself

2 Likes

Andrea - Thanks for putting this post together. Super helpful! I’m building a Blazor Server app in .NET 7.0 and everything seems to be working great, except for one thing. The callback URL never appears to be called after a successful login. My code in Program.cs is:

builder.Services.AddAuth0WebAppAuthentication(o => {
    o.CallbackPath = "/auth0";
    o.ClientId = SettingsUtil.Settings.CellaretAdminAuth0ClientId;
    o.ClientSecret = SettingsUtil.Settings.CellaretAdminAuth0ClientSecret;
    o.Domain = SettingsUtil.Settings.Auth0Domain;
    o.Scope = "openid profile email";
});

When I put a breakpoint in my /auth0

OnGet()

method, it never gets hit. Any thoughts? Thanks!

Hey @cellaret,
The CallbackPath property is intended to be handled by the OIDC middleware. Its default value is /signin-oidc and you can change it just in case it conflicts with an existing endpoint in your application. Normally you don’t need to change it, and you can’t override its behavior anyway.

If your goal is to redirect the user to a specific page after login, you should specify the redirect URL using the redirectUri parameter.

Referring to the article’s sample project, if you want to redirect your user to the /auth0 page, you need to change the AccessControl.razor component as follows:

<AuthorizeView>
    <Authorized>        
        <a href="logout">Log out</a>
    </Authorized>
    <NotAuthorized>
        <a href="login?redirectUri=/auth0">Log in</a>
    </NotAuthorized>
</AuthorizeView>

I hope everything is clear.

1 Like

This was fairly straightforward and I got it redirecting to my Blazor page endpoint /auth0, but now I am getting an odd OpenIdConnectAuthenticationHandler exception. It reads:

An unhandled exception occurred while processing the request.
Exception: OpenIdConnectAuthenticationHandler: message.State is null or empty.
Unknown location

Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<TOptions>.HandleRequestAsync()

Stack Query Cookies Headers Routing
Exception: OpenIdConnectAuthenticationHandler: message.State is null or empty.

Show raw exception details
System.Exception: OpenIdConnectAuthenticationHandler: message.State is null or empty.
Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<TOptions>.HandleRequestAsync()
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

Show raw exception details
System.Exception: An error was encountered while handling the remote login.
 ---> System.Exception: OpenIdConnectAuthenticationHandler: message.State is null or empty.
   --- End of inner exception stack trace ---
   at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

I’ve tried both a Blazor component/page and a .CSHTML page (with model) and both give the same error. Is there something extra that needs to be added to the Startup.cs class to make this work?

I’ve even tried adding the following to my Startup.cs class with no effect:

builder.Services.AddHttpContextAccessor();

The code for my callback doesn’t even reach the breakpoint shown:

Thoughts?

Hey @cellaret,
To redirect users to a specific page, all you need to do is specify it in the redirectUri parameter.
If you use the Blazor project attached to my article and modify the AccessControl.razor component as follows, your users will be redirected to the quizViewer page instead of the home page:

<AuthorizeView>
    <Authorized>        
        <a href="logout">Log out</a>
    </Authorized>
    <NotAuthorized>
        <a href="login?redirectUri=/quizViewer">Log in</a>
    </NotAuthorized>
</AuthorizeView>

Nothing else is required.

It seems that your error is related to the OpenID Connect middleware. Make sure it is configured correctly. Did you remove the CallbackPath setting?

Also, be careful with using HttpContextAccessor in Blazor Server (see this). BTW, there is a typo in the code highlighted by your breakpoint (HttpContextAccssor instead of HttpContextAccessor )

To access your user data, you should use the authentication state, as shown in the article.

1 Like

I’m pretty sure there is a bug here somewhere. Hear me out.

When I setup my component as you suggest:

<AuthorizeView>
    <Authorized>
        <ProfileMenu />
    </Authorized>
    <NotAuthorized>
        <RadzenLabel>
            <a href="/login?redirectUri=/auth0">Log In</a>
        </RadzenLabel>
    </NotAuthorized>
</AuthorizeView>

The Auth0 login page fails - it says that I have incorrectly configured my Callback URL. I have configured mine to be: https://localhost:7203/auth0. But here is my Auth0 login screen:

Now, if I modify my Program.cs file to include the callback in the options:

// Add Authentication...
builder.Services.AddAuth0WebAppAuthentication(o => {
    o.CallbackPath = "/auth0";
    o.ClientId = SettingsUtil.Settings.CellaretAdminAuth0ClientId;
    o.Domain = SettingsUtil.Settings.Auth0Domain;
    o.Scope = "openid profile email";
});

I get an error upon successful login when Auth0 attempts to callback to my razor page:

So… In order to fix all of this, I have to do something odd. I have to add a Callback URL into my Auth0 application settings that doesn’t exist: https://localhost:7203/callback. Once this is configured on the Auth0 side, the application does load the /auht0 razor page as specified in the <AuthorizedView> element.

It would appear the bug is that when the login.cshtml razor page is invoked and the OnGet() method executes:

public async Task OnGet(string redirectUri)
{
    var authenticationProperties = new LoginAuthenticationPropertiesBuilder()
        .WithRedirectUri(redirectUri)
        .Build();

    await HttpContext.ChallengeAsync(Auth0Constants.AuthenticationScheme, authenticationProperties);
}

The redirectUri param is not properly sent to Auth0 in the request. Either way, it would seem bad practice to have to configure my Auth0 application in such a way that the Callback URL is a page that does not exist.

Am I missing something here or does this make sense?

Hey @cellaret,
What you think is a bug is actually the standard behavior of the ASP.NET Core authentication middleware that the Auth0 SDK relies on.

Basically, the value of the redirectUri parameter (and the corresponding redirectUri property) is NOT the redirect_uri parameter you find in the authorization request URL.

The former is the page to which you want your user to be redirected. It is handled internally in your application through the authentication middleware. Auth0 doesn’t know this URL

The latter is where Auth0 sends the ID token after the authentication. Auth0 needs to know this URL and it should be registered in the dashboard.
This URL is defined and fully handled by the authentication middleware.
As mentioned before, the default value is /signin-oidc. Our SDK only redefines it as /callback for consistency with the other SDKs.

In summary, you must register https://localhost:7203/callback in the Auth0 dashboard regardless of what page you want your authenticated user to land on.

I hope that this clarifies the internal behavior :slightly_smiling_face:

OK, still clicking along with an app that I have decided to do as a Blazor WASM app. Anyway also been off an on trying out Auth0 and find it pretty straight forward. I went through this entire example and it ran like a champ. But after some examples I tried on Amazon Amplify thought let’s try this there. I think my problem is with the Callback URI and the Logout URI. Has anyone done this?

Hey @MickCG,
Welcome to the Auth0 Community!
I’m glad to hear that the Blazor WASM sample project worked well.

I’m not familiar with Amazon Amplify, but I can try to help you anyway. Can you tell me specifically what the problem is? Are you getting an error? What error message?

Mostly in Amazon I have to put a Login URI and a Logout URI I think that is where my trouble is because I think on the verify its giving a 401 error. I do with the provided URI to test it on the web get to the index page but then the Login seems to go south. I am spending some time looking at their Amazon examples of blazor, seem to me I found one.

After I wrote my last post I went back into the app and realized I don’t think I’m actually getting to the logon screen from Auth0. Seems to me it should be the same info for that as the local version which woks???

Not sure about the problems you are experiencing. I would suggest checking the following:

  • Make sure that you are using the actual AWS Amplify base URL for the callback and logout URLs in the Auth0 dashboard. I mean, when you run your app locally, you use https://localhost:7290 as the base URL (for example, https://localhost:7290/callback). When you run your app in AWS Amplify, you need to register something like https://xxxxxxxxxxxxxx.amplifyapp.com/callback.

  • Since your Blazor WASM app is a SPA, make sure that all the URL requests are redirected to the app. As I said, I’m not familiar with AWS Amplify, but I found that you should create a redirect, specifically a redirect for SPA.

Let me know if these tips are helpful.

That got me a lot further. But when I hit the login button I get the following error:
image
and it sits completing login needless to say.

Honestly, I’m not sure I can help you. I have little context for the problem and no experience with AWS Amplify.
If everything works well locally, I think this is a specific deployment platform problem. At first glance, it could be a missing redirect to the SPA. In this case, it is not a Blazor problem and even less an Auth0 problem. It’s a general SPA hosting problem that you can solve by configuring redirection properly. But I can only make assumptions

Thanks for your response, I sort of was leaning that way too, good to see a confirmation from someone with more experience, thanks again!

1 Like

@Ditchford and anyone else interested in, I wrote a blog post about the logout problem in Blazor Server

Hello @andrea.chiarelli I followed the code but not sure why the app is being redirected to Account/Login. It is getting the redirect error below.

No web page was found for the web address: https://localhost:7231/Account/Login?ReturnUrl=%2F

Hi @mela,
Welcome to the Auth0 Community!

From the error you shared, it seems that your application is not configured properly.
Account/Login is the default login path used by ASP.NET Core Identity. Are you using the Auth0 ASP.NET Core Authentication SDK as suggested in the article?
Have you tried the sample project attached to the article and compared its code with your code?
Alternatively, please share your code.

this sample code is working using my app auth0 credentials. Still trying to figure out how to translate this code to Net 8 Blazor.

Wait @mela, the article and its sample project are for .NET 7.0.
.NET 8 changes the Blazor hosting model. You can move seamlessly from Server to WASM at the component level. So, the approach used in this article may not work.
Currently, there are no official guidelines on how to deal with external OIDC providers (I’m still exploring this).
See this thread on this topic.