Firebase Cloud Function beforeSignIn()?


25.07.2022, 14:49

##### ES FUNKTIONIERT #####

Für alle, die etwas Ähnliches vorhaben.

Folgende Google Cloud Function fügt benutzerdefinierte Werte zu dem User Objekt bzw. zu dem idToken des Users hinzu:

exports.beforeSignIn = functions.region('europe-west3').auth.user().beforeSignIn((user, context) => {
let customClaims = {
  isVerified: true,
  role: 'admin'
}
getAuth().setCustomUserClaims(user.uid, customClaims);
});

Im Client können diese Werte dann wie folgt ausgelesen werden:

import { auth } from "../firebase/";

let user = auth.currentUser
let idTokenResult = await user.getIdTokenResult(true);
console.log(idTokenResult.claims)

Ich hoffe, dass das ganze noch jemandem hilft.

1 Antwort

Wenn du die Identity Platform-Authentifizierung von Firebase nutzt, und hierbei auf keine anonyme oder benutzerdefinierte Authentifizierungsweise zurückgreifst, kannst du Blockierfunktionen verwenden.

Ein konkretes Beispiel, wie sich Nutzer bei Anmeldung blockieren lassen, zeigt bereits die Dokumentation. Die Anfrage deines Client SDK würde eine entsprechende Fehlerinformation im Response erhalten (passend wäre z.B. Statuscode 403), die du in deiner Vue-Anwendung weiterverarbeiten kannst.


TomKell 
Beitragsersteller
 25.07.2022, 13:56

Vielen Dank für die Antwort. Ich habe mich mit der ganzen Thematik nochmal weiter auseinander gesetzt und die theoretische Möglichkeit von customClaims gefunden.

Soweit ich es verstanden habe, kann ich im signin oder create Process eines Nutzers einschreiten und über das customClaims Attribut beliebige Werte speichern und später abfragen lassen.

Firebase Dokumentation Custom Claims

https://firebase.google.com/docs/auth/admin/custom-claims

const functions = require('firebase-functions');
const { initializeApp } = require('firebase-admin/app');
const { getAuth } = require('firebase-admin/auth');
const { getDatabase } = require('firebase-admin/database');

initializeApp();

// On sign up.
exports.processSignUp = functions.auth.user().onCreate(async (user) => {
  // Check if user meets role criteria.
  if (
    user.email &&
    user.email.endsWith('@admin.example.com') &&
    user.emailVerified
  ) {
    const customClaims = {
      admin: true,
      accessLevel: 9
    };

    try {
      // Set custom user claims on this newly created user.
      await getAuth().setCustomUserClaims(user.uid, customClaims);

      // Update real-time database to notify client to force refresh.
      const metadataRef = getDatabase().ref('metadata/' + user.uid);

      // Set the refresh time to the current UTC timestamp.
      // This will be captured on the client to force a token refresh.
      await  metadataRef.set({refreshTime: new Date().getTime()});
    } catch (error) {
      console.log(error);
    }
  }
});

Die Funktion habe ich so auch getestet. Leider ohne Erfolg. Sie wird ausgeführt, setzt jedoch keine claims.

Ich habe das ganze in zahlreichen Varianten getestet und auch diese super stark runtergebrochene Version funktioniert nicht.

exports.beforeSignIn = functions.region('europe-west3').auth.user().beforeSignIn(async (user, context) => {
  await getAuth().setCustomUserClaims(user.uid, { admin: false });
  console.log(user)
});

Die Variable customClaims gibt immer undefined zurück.

was mache ich da falsch?

0
TomKell 
Beitragsersteller
 25.07.2022, 14:08
@TomKell

Okay, habs grade selbst gemerkt.. da es ne asynchrone Funktion ist, kann er die Claims im log natürlich nicht sofort ausgeben.

Dennoch werden die customClaimes nicht im userObjekt an meinen Client weitergegeben. gibt es da eine Möglichkeit, die im Client auszulesen?

0