Blazor’s Authorization

Disclaimer: based on my observation, not readings.

Recently, I had to implement Firebase authentication for a Blazor WASM project. To my surprise, I discovered there’s no ready-made authentication library for Firebase on .NET. While I found the Fireba…


This content originally appeared on DEV Community and was authored by Ruxo Zheng

Disclaimer: based on my observation, not readings.

Recently, I had to implement Firebase authentication for a Blazor WASM project. To my surprise, I discovered there's no ready-made authentication library for Firebase on .NET. While I found the Firebase Admin library, it wasn't quite what I needed for client-side authentication. So, I ended up building my own solution for .NET.

Fortunately, I didn't have to start from scratch. Firebase provides a JavaScript SDK for authentication, which is quite straightforward to use and integrates well with Blazor WASM.

Blazor Authorization

Blazor handles authorization through a class derived from AuthenticationStateProvider. This class requires you to override a key method: GetAuthenticationStateAsync. You can find more details in the official documentation.

The GetAuthenticationStateAsync method is responsible for returning an instance of AuthenticationState, which encapsulates the current user as a ClaimsPrincipal. The ClaimsPrincipal contains a ClaimsIdentity, which the framework uses to determine whether the user is authenticated by checking the IsAuthenticated property.

By overriding GetAuthenticationStateAsync and returning the appropriate user state, you can manage the application's authentication flow as well as user permissions. Essentially, this means you have full control over how authentication is implemented and when users are considered authenticated or not.

Firebase Authentication Overview

Firebase offers comprehensive documentation for their authentication libraries, which can be found here (JavaScript SDK). Since I was working with Blazor WASM, it made sense to leverage browser modules. Luckily, Firebase also supports this approach, as mentioned in a note on this page.

Image description

Blazor integration

The idea is to use the JS SDK to provide the Firebase authentication, and once we get the authenticated JWT, just hands over to .NET Cookie authentication for storing as .NET cookie, or manually managing the token yourself.

JS interop script

First, we need a Javascript-side interop code to call Firebase authentication. It looks like this:

import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.14.1/firebase-app.js'
import { getAuth, GoogleAuthProvider, signInWithPopup } from 'https://www.gstatic.com/firebasejs/10.14.1/firebase-auth.js'

const signin = async (output, config) => {
    const app = initializeApp(config);
    const auth = getAuth(app);

    const provider = new GoogleAuthProvider();

    try {
        const result = await signInWithPopup(auth, provider);
        const credential = GoogleAuthProvider.credentialFromResult(result);
        const user = result.user;
        const info = {
            accessToken: credential.accessToken,
            idToken: user.accessToken
        }
        const encoded = await output.invokeMethodAsync("AfterSignIn", true, info, null)
        // you may use local storage or session storage, etc.
        document.cookie = `after-signin=${encoded}; path=/; Secure; SameSite=Strict`;
    } catch(error) {
        console.error(error);
        output.invokeMethodAsync("AfterSignIn", false, null, "permission-needed")
    }
};

window.firebase = { signin };

In order to use the SDK, you need Firebase configuration, which is passed to the function via config variable. You can find the configuration in Firebase's console, in the application section under your project's settings.

The output variable encapsulates .NET interop class with a method name AfterSignIn. It is an integration for the script and .NET Blazor code. My AfterSignIn method looks like this:

    [JSInvokable]
    public async Task<string?> AfterSignIn(bool success, SignInInfo? info, string? error) {
        // basically you may want to cache the result of login
        afterSignInInfo = success? new AfterSignInInfo(info) : null;
        // return serialized sign-in data as string for storing in the cookie
        return success? JsonSerializer.Serialize(info!) : null;
    }

and the code to invoke the signin function:

async Task Login(){
        var jsRef = DotNetObjectReference.Create(this);
        var fbConfig = Configuration["FirebaseConfig"];

        await js.InvokeVoidAsync("window.firebase.signin", jsRef, fbConfig);
        if (afterSignInInfo?.IsSuccess ?? false){
            var query = returnUrl is null ? string.Empty : $"?ReturnUrl={HttpUtility.UrlEncode(returnUrl)}";
            navManager.NavigateTo($"/login/success{query}");
        }
}

That's it

The JS code should be generalized enough to be used with any kind of Blazor project (Blazor Server, Blazor Hosted WASM, or just Blazor WASM).


This content originally appeared on DEV Community and was authored by Ruxo Zheng


Print Share Comment Cite Upload Translate Updates
APA

Ruxo Zheng | Sciencx (2024-11-07T03:48:52+00:00) Blazor’s Authorization. Retrieved from https://www.scien.cx/2024/11/07/blazors-authorization/

MLA
" » Blazor’s Authorization." Ruxo Zheng | Sciencx - Thursday November 7, 2024, https://www.scien.cx/2024/11/07/blazors-authorization/
HARVARD
Ruxo Zheng | Sciencx Thursday November 7, 2024 » Blazor’s Authorization., viewed ,<https://www.scien.cx/2024/11/07/blazors-authorization/>
VANCOUVER
Ruxo Zheng | Sciencx - » Blazor’s Authorization. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/11/07/blazors-authorization/
CHICAGO
" » Blazor’s Authorization." Ruxo Zheng | Sciencx - Accessed . https://www.scien.cx/2024/11/07/blazors-authorization/
IEEE
" » Blazor’s Authorization." Ruxo Zheng | Sciencx [Online]. Available: https://www.scien.cx/2024/11/07/blazors-authorization/. [Accessed: ]
rf:citation
» Blazor’s Authorization | Ruxo Zheng | Sciencx | https://www.scien.cx/2024/11/07/blazors-authorization/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.