How to Validate the Firebase User Token from ASP.NET (C#)

We have a client application that uses Firebase authentication services to handle user management, and ASP.NET web services for the business logic and data storage. Before accessing the data on the server, we need to validate that the user is correctly authenticated and has access to their relevant data.

Firebase generates an authentication token that is valid for a few minutes only. The token can be retrieved using Firebase’s getIdToken method. We need to send the token to the web services application and validate it there before accessing the database.

Server side code (C#):

// Add the FirebaseAdmin NuGet package before adding these using directives
using FirebaseAdmin;
using FirebaseAdmin.Auth;
using Google.Apis.Auth.OAuth2;

// Global Firebase App instance
FirebaseApp firebaseApp = FirebaseApp.Create(new AppOptions()
{
    // the credentials file can be downloaded from Firebase portal and added to the project
    Credential = GoogleCredential.FromFile("cert/credentials.json")
});

// Method for handling a GET request to the profiles table
// The user token Id is optional and received as part of the HTTP reuest
// e.g. https://cloud1.upwindtec.pt:7002/profiles/rBeQAwFltmSSQDmy?idToken=firebase_secret_token
async Task<IResult> GetProfiles([FromRoute] string? Id,
                                string? idToken,
                                DbContext db)
{
    if (!string.IsNullOrEmpty(idToken))
    {
        // If a token Id is provided, validate the user before accessing the table
        bool authenticated = false;
        try
        {
            FirebaseToken decodedToken = await FirebaseAuth.GetAuth(firebaseApp).VerifyIdTokenAsync(idToken);
            string uid = decodedToken.Uid;
            // If the user is requesting a specific profile, make sure it matches the user Id from the token
            if (uid != null && uid == Id)
            {
                authenticated = true;
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine($"Error validating idToken: {ex.Message}");
        }

        if (!authenticated)
        {
            return TypedResults.Unauthorized();
        }
    }
...

Client side code (Typescript)

  const db = getFirestore(await getAuth().currentUser!.getIdToken()); // add the firebase token Id to the HTTP request
  const profileSnapshot = await getDoc(doc(db, "profiles", userID));
  ...

  // adding the token to the request is done this way:
  let response: AxiosResponse = {} as AxiosResponse;
  // if we have an idToken, add it to the query parameters for authentication purposes
    if (this.idToken !== "") {
      if (!params) {
        params = new URLSearchParams();
      }
      params.append("idToken", this.idToken);
    }
    try {
      response = await axios({
        url: Url,
        method: method,
        params: params,
        data: data,
        baseURL: this.baseUrl,
    ...