Accesso degli utenti con SAML

Questo documento mostra come utilizzare Identity Platform per eseguire l'accesso degli utenti con un provider SAML (Security Assertion Markup Language) 2.0.

Prima di iniziare

  1. Accedi al tuo Google Cloud account. Se non hai mai utilizzato Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per eseguire, testare e implementare i carichi di lavoro.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

  6. Abilita Identity Platform e aggiungi l'SDK client alla tua app. Per ulteriori informazioni e istruzioni, consulta la guida rapida Eseguire l'accesso di un utente con un'email utilizzando Identity Platform.

Configurare il provider

  1. Nella Google Cloud console, vai alla pagina Identity Platform > Provider di identità.
    Vai a Provider di identità

  2. Fai clic su Aggiungi un provider e seleziona SAML dall'elenco.

  3. Inserisci i seguenti dettagli:

    1. Il nome del provider. Può essere uguale all'ID provider o a un nome personalizzato. Se inserisci un nome personalizzato, fai clic su Modifica accanto a ID provider per specificare l'ID (che deve iniziare con saml).

    2. L'ID entità del provider.

    3. L'URL SSO SAML del provider.

    4. Il certificato utilizzato per la firma dei token sul provider. Assicurati di includere le stringhe di inizio e fine. Ad esempio:

      -----BEGIN CERTIFICATE-----
      MIICajCCAdOgAwIBAgIBADANBgkqhkiG9w0BAQ0FADBSMQswCQYDVQQGEwJ1czEL
      ...
      LEzc1JwEGQQVDYQCwsQMSBDAF0QAB0w9GikhqkgBNADABIgABIwAgOdACCjaCIIM
      -----END CERTIFICATE-----
      
  4. Nella sezione Fornitore di servizi, inserisci l'ID entità della tua app. In genere si tratta dell'URL dell'app. Nel provider di identità SAML, questo viene chiamato pubblico.

  5. Nel riquadro laterale Impostazioni progetto , fai clic su Aggiungi dominio e aggiungi il dominio della tua app. Ad esempio, se l' URL di accesso della tua app è https://example.com/login, aggiungi example.com.

  6. Per completare la configurazione, esegui una delle seguenti operazioni:

    • Copia l'URL di callback di autorizzazione predefinito dal campo Callback di autorizzazione (URL) e aggiungilo alla configurazione dell'app SAML.

      L'utilizzo dell'URL di callback di autorizzazione predefinito riduce la complessità della convalida della risposta SAML.

    • Aggiungi l'URL di callback di autorizzazione personalizzato alla configurazione dell'app SAML, ad esempio https://PROJECT-ID.firebaseapp.com/__/auth/handler.

  7. Nella sezione Configura l'applicazione, fai clic su Dettagli di configurazione. Copia lo snippet nel codice dell'app per inizializzare l'SDK client di Identity Platform.

  8. Fai clic su Salva.

Elementi obbligatori del provider

Identity Platform prevede gli elementi <saml:Subject> e <saml:NameID> nelle risposte del provider. Se non definisci i valori per questi elementi durante la configurazione del provider, l'asserzione SAML non riesce.

Richieste di firma

Puoi aumentare la sicurezza delle richieste di autenticazione firmandole.

Per firmare le richieste, devi prima abilitare le richieste firmate per il tuo provider di identità chiamando inboundSamlConfigs.patch() e impostando idp_config.sign_request su true:

REST

Prima di utilizzare i dati della richiesta, apporta le sostituzioni seguenti:

  • project-id: l'ID del Google Cloud progetto
  • provider-id: l'ID provider SAML

Metodo HTTP e URL:

PATCH https://identitytoolkit.googleapis.com/admin/v2/projects/project-id/inboundSamlConfigs/provider-id?updateMask=idpConfig.signRequest

Corpo JSON della richiesta:

{
  "idp_config": {
    "sign_request": true
  }
}

Per inviare la richiesta, espandi una di queste opzioni:

 

Devi utilizzare l'API REST per abilitare le richieste firmate; l'utilizzo della Google Cloud console o di Google Cloud CLI non è supportato.

La risposta è un InboundSamlConfig oggetto, che include un array di SpCertificate oggetti. Configura il valore del certificato X509 con il tuo provider di identità SAML in modo che possa convalidare la firma delle tue richieste.

Ruotare i certificati del fornitore di servizi

Quando utilizzi le richieste SAML firmate, Identity Platform utilizza un certificato del fornitore di servizi (SP). Per evitare interruzioni dell'autenticazione, monitora la data di scadenza dei certificati SP ed esegui la rotazione prima della scadenza.

  1. Per controllare la scadenza del certificato SP, estrai i timestamp di scadenza del certificato utilizzando jq:

    curl -s -X GET "https://identitytoolkit.googleapis.com/v2/projects/PROJECT_ID/inboundSamlConfigs" \
        -H "Authorization: Bearer $(gcloud auth print-access-token)" \
        -H "X-Goog-User-Project: PROJECT_ID" \
        -H "Content-Type: application/json" | \
        jq -r '.inboundSamlConfigs[].spConfig.spCertificates[]?.expiresAt'
    

    Sostituisci PROJECT_ID con l'ID progetto Google Cloud.

    Controlla il valore expiresAt in spConfig.spCertificates.

  2. Se il timestamp di scadenza (expiresAt) è entro 30 giorni o entro l' intervallo di tempo richiesto dalla tua organizzazione, contatta l' assistenza clienti Google Cloud e l'amministratore IdP per pianificare l'aggiornamento durante un periodo di inattività pianificato.

  3. Per ruotare il certificato e ricevere il nuovo certificato pubblico, contatta l'assistenza clienti Google Cloud.

  4. Per aggiornare la configurazione del certificato sul tuo IdP, condividi il nuovo certificato SP con l'amministratore IdP.

  5. Verifica se il Single Sign-On (SSO) funziona con la configurazione aggiornata.

Eseguire l'accesso degli utenti

Quando esegui l'accesso di un utente, l'SDK client gestisce l'handshake di autenticazione, quindi restituisce i token ID contenenti gli attributi SAML nei relativi payload. Per eseguire l'accesso di un utente e ottenere gli attributi dal provider SAML:

  1. Crea un'istanza di SAMLAuthProvider con l'ID provider che hai configurato in la sezione precedente. L'ID provider deve iniziare con saml.

    Versione web 9

    import { SAMLAuthProvider } from "firebase/auth";
    
    const provider = new SAMLAuthProvider("saml.myProvider");

    Versione web 8

    const provider = new firebase.auth.SAMLAuthProvider('saml.myProvider');
  2. Avvia il flusso di accesso. Puoi scegliere di utilizzare una finestra di dialogo o un reindirizzamento.

    Versione web 9

    import { getAuth, signInWithPopup, SAMLAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    signInWithPopup(auth, provider)
      .then((result) => {
        // User is signed in.
        // Provider data available from the result.user.getIdToken()
        // or from result.user.providerData
      }).catch((error) => {
        // Handle Errors here.
        const errorCode = error.code;
        const errorMessage = error.message;
        // The email of the user's account used.
        const email = error.customData.email;
        // The AuthCredential type that was used.
        const credential = SAMLAuthProvider.credentialFromError(error);
        // Handle / display error.
        // ...
      });

    Versione web 8

    firebase.auth().signInWithPopup(provider)
      .then((result) => {
        // User is signed in.
        // Identity provider data available in result.additionalUserInfo.profile,
        // or from the user's ID token obtained from result.user.getIdToken()
        // as an object in the firebase.sign_in_attributes custom claim
        // This is also available from result.user.getIdTokenResult()
        // idTokenResult.claims.firebase.sign_in_attributes.
      })
      .catch((error) => {
        // Handle / display error.
        // ...
      });

    Reindirizzamento

    Per reindirizzare a una pagina di accesso, chiama signInWithRedirect():

    Versione web 9

    import { getAuth, signInWithRedirect } from "firebase/auth";
    
    const auth = getAuth();
    signInWithRedirect(auth, provider);

    Versione web 8

    firebase.auth().signInWithRedirect(provider);

    Quindi, chiama getRedirectResult() per ottenere i risultati quando l'utente torna alla tua app:

    Versione web 9

    import { getAuth, getRedirectResult, SAMLAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    getRedirectResult(auth)
      .then((result) => {
        // User is signed in.
        // Provider data available from the result.user.getIdToken()
        // or from result.user.providerData
      })
      .catch((error) => {
        // Handle Errors here.
        const errorCode = error.code;
        const errorMessage = error.message;
        // The email of the user's account used.
        const email = error.customData.email;
        // The AuthCredential type that was used.
        const credential = SAMLAuthProvider.credentialFromError(error);
        // Handle / display error.
        // ...
      });

    Versione web 8

    firebase.auth().getRedirectResult()
      .then((result) => {
        // User is signed in.
        // Provider data available in result.additionalUserInfo.profile,
        // or from the user's ID token obtained from result.user.getIdToken()
        // as an object in the firebase.sign_in_attributes custom claim
        // This is also available from result.user.getIdTokenResult()
        // idTokenResult.claims.firebase.sign_in_attributes.
      }).catch((error) => {
        // Handle / display error.
        // ...
      });
  3. Recupera gli attributi utente associati al provider SAML dal token ID utilizzando l'attestazione firebase.sign_in_attributes. Assicurati di verificare il token ID utilizzando l'SDK Admin quando lo invii al server.

    Il token ID include l'indirizzo email dell'utente solo se viene fornito nell'attributo NameID dell'asserzione SAML del provider di identità:

    <Subject>
      <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">test@email.com</NameID>
    </Subject>
    

    Questo valore viene inserito nel token ID emesso da Firebase e nell'oggetto UserInfo.

Sono supportati solo i flussi SAML avviati dal fornitore di servizi dall'SDK client.

Se un utente ha già eseguito l'accesso alla tua app utilizzando un metodo diverso (ad esempio email/password), puoi collegare il suo account esistente a il provider SAML utilizzando linkWithPopup() o linkWithRedirect().

Il seguente snippet di codice mostra come collegare l'Account Google di un utente al provider SAML:

Versione web 9

import { getAuth, linkWithPopup, GoogleAuthProvider } from "firebase/auth";
const provider = new GoogleAuthProvider();

const auth = getAuth();
linkWithPopup(auth.currentUser, provider).then((result) => {
  // Accounts successfully linked.
  const credential = GoogleAuthProvider.credentialFromResult(result);
  const user = result.user;
  // ...
}).catch((error) => {
  // Handle Errors here.
  // ...
});

Versione web 8

auth.currentUser.linkWithPopup(provider).then((result) => {
  // Accounts successfully linked.
  var credential = result.credential;
  var user = result.user;
  // ...
}).catch((error) => {
  // Handle Errors here.
  // ...
});

Passaggi successivi