Toan Le

How to implement Firebase Authentication with React and Net Core

2023-04-05

Prerequisites

  1. Create a new project in Firebase.
  2. Create a new .Net Core project.
  3. Create a new React app using create-react-app.

Step 1: Setup Firebase Auth in React

  1. Install Firebase and its Authentication package using npm:

    npm install firebase
  2. Create a Firebase configuration object with your project’s API keys and other credentials. This object will be used for initializing Firebase in your app.

    const firebaseConfig = {
    apiKey: "your-api-key",
    authDomain: "your-auth-domain",
    projectId: "your-project-id",
    storageBucket: "your-storage-bucket",
    messagingSenderId: "your-msid",
    appId: "your-app-id",
    measurementId: "your-mid"
    };
  3. Create a useAuth hook.

    import { initializeApp } from "firebase/app";
    import {
    GoogleAuthProvider,
    User,
    getAuth,
    onAuthStateChanged,
    signInWithEmailAndPassword,
    signInWithPopup,
    signOut,
    } from "firebase/auth";
    import React from "react";
    import { firebaseConfig } from "../common/FirebaseConfig";
    
    const app = initializeApp(firebaseConfig);
    const auth = getAuth(app);
    
    function useAuth() {
    const [currentUser, setCurrentUser] = React.useState<User | null>(null);
    const isAuthenticated = !!currentUser;
    
    const signOutUser = () => signOut(auth);
    const signInUser = (email: string, password: string) => {
    return signInWithEmailAndPassword(auth, email, password);
    };
    const signInWithGoogle = () => {
    return signInWithPopup(auth, new GoogleAuthProvider());
    };
    
    React.useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setCurrentUser(user);
    });
    
    return unsubscribe;
    }, []);
    
    return {
    currentUser,
    isAuthenticated,
    signInUser,
    signInWithGoogle,
    signOut: signOutUser,
    };
    }
    
    export default useAuth;
  4. Apply useAuth hook to login page.

    const promise = signInWithGoogle();
    promise
    .then((value) => {
    value.user.getIdToken().then((token) => {
          
    });
    })
    .catch((error) => {
    console.error(error);
    });

The header of request should contain bearer authorization when calling api

Authorization: `Bearer ${token}`

Step 2: Setup Authentication in .Net Core

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opt =>
{
    opt.Authority = builder.Configuration["Jwt:Firebase:ValidIssuer"];
    opt.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = builder.Configuration["Jwt:Firebase:ValidIssuer"],
        ValidAudience = builder.Configuration["Jwt:Firebase:ValidAudience"]
    };
});

Or you can stored and load public key from https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com instead.

Change {public_key} to use public key from Google.

RSACryptoServiceProvider rsa = new();
rsa.ImportParameters(
  new RSAParameters()
  {
      Modulus = WebEncoders.Base64UrlDecode("{public_key}"),
      Exponent = WebEncoders.Base64UrlDecode("AQAB")
  });

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opt =>
{
    opt.TokenValidationParameters = new TokenValidationParameters
    {
        RequireExpirationTime = true,
        RequireSignedTokens = true,
        ValidateAudience = true,
        ValidateIssuer = true,
        ValidateLifetime = true,
        ValidIssuer = builder.Configuration["Jwt:Firebase:ValidIssuer"],
        ValidAudience = builder.Configuration["Jwt:Firebase:ValidAudience"],
        IssuerSigningKey = new RsaSecurityKey(rsa)
    };
});

Change {your-project-id} to your Firebase project id in appsettings.json

  "Jwt": {
    "Firebase": {
      "ValidIssuer": "https://securetoken.google.com/{your-project-id}",
      "ValidAudience": "{your-project-id}"
    }
  }

Copyright (c) 2024