Sécuriser votre application avec des en-têtes signés

Cette page explique comment sécuriser votre application avec des en-têtes IAP signés. Une fois configuré, Identity-Aware Proxy (IAP) utilise des jetons Web JSON (JWT, JSON Web Token) pour s'assurer qu'une requête envoyée à votre application est autorisée. Cette démarche protège votre application contre les types de risques suivants :

  • Désactivation accidentelle du service IAP
  • Pare-feu mal configurés
  • Accès depuis le projet

Afin de sécuriser correctement votre application, vous devez vous servir d'en-têtes signés qui conviennent à tous les types d'application.

Si vous disposez d'une application d'environnement standard App Engine, vous pouvez également utiliser l'API Users.

Sachez que les vérifications d'état de Compute Engine et de GKE n'incluent pas les en-têtes JWT, et qu'IAP ne gère pas ces vérifications. Si votre vérification d'état renvoie des erreurs d'accès, assurez-vous que vous l'avez correctement configurée dans la console Google Cloud et que votre validation d'en-tête JWT autorise le chemin de la vérification d'état. Pour en savoir plus, consultez la section Créer une exception de vérification d'état.

Avant de commencer

Pour sécuriser votre application avec des en-têtes signés, vous avez besoin des éléments suivants :

Sécuriser votre application avec des en-têtes IAP

Pour sécuriser votre application avec le JWT IAP, validez l'en-tête, la charge utile et la signature de celui-ci. Le JWT se trouve dans l'en-tête de requête HTTP x-goog-iap-jwt-assertion. En contournant IAP, un pirate informatique peut falsifier les en-têtes d'identité IAP non signés : x-goog-authenticated-user-{email,id}. Le JWT IAP constitue une alternative plus sécurisée.

Les en-têtes signés offrent une sécurité secondaire dans le cas d'un éventuel contournement d'IAP. Sachez que lorsqu'il est activé, IAP retire les en-têtes x-goog-* fournis par le client quand la requête passe par l'infrastructure de diffusion du service.

Valider l'en-tête JWT

Assurez-vous que l'en-tête JWT respecte les contraintes suivantes :

Revendications d'en-tête JWT
alg Algorithme ES256
kid ID de clé Doit correspondre à l'une des clés publiques répertoriées dans le fichier de clé IAP, disponible dans deux formats différents : https://www.gstatic.com/iap/verify/public_key et https://www.gstatic.com/iap/verify/public_key-jwk

Assurez-vous que le JWT a été signé par la clé privée correspondant à la revendication kid du jeton. Pour ce faire, récupérez d'abord la clé publique à l'un des deux emplacements suivants :

  • https://www.gstatic.com/iap/verify/public_key. Cette URL contient un dictionnaire JSON qui mappe les revendications kid avec les valeurs de la clé publique.
  • https://www.gstatic.com/iap/verify/public_key-jwk. Cette URL contient les clés publiques IAP au format JWK.

Une fois la clé publique récupérée, validez la signature à l'aide d'une bibliothèque JWT.

Valider la charge utile JWT

Assurez-vous que la charge utile JWT respecte les contraintes suivantes :

Revendications de charge utile JWT
exp Date/Heure d'expiration Il doit s'agir d'une date future. Le temps est mesuré en secondes depuis l'époque UNIX. Prévoyez 30 secondes de décalage. La durée de vie maximale d'un jeton est de 10 minutes + 2 * le décalage.
iat Date/Heure d'émission Il doit s'agir d'une date antérieure. Le temps est mesuré en secondes depuis l'époque UNIX. Prévoyez 30 secondes de décalage.
aud Cible Doit être une chaîne comportant les valeurs suivantes :
  • App Engine : /projects/PROJECT_NUMBER/apps/PROJECT_ID
  • Compute Engine et GKE : /projects/PROJECT_NUMBER/global/backendServices/SERVICE_ID
iss Émetteur Doit être https://cloud.google.com/iap.
hd Domaine du compte Si un compte appartient à un domaine hébergé, la revendication hd est fournie afin de différencier le domaine auquel le compte est associé.
google Revendication Google Si un ou plusieurs niveaux d'accès s'appliquent à la requête, leur nom est stocké sous forme de tableau de chaînes dans l'objet JSON de la revendication google, sous la clé access_levels.

Lorsque vous spécifiez une stratégie d'appareil et que l'organisation a accès aux données de l'appareil, DeviceId est également stocké dans l'objet JSON. Notez qu'une requête envoyée à une autre organisation n'est pas nécessairement autorisée à afficher les données de l'appareil.

Vous pouvez obtenir les valeurs de la chaîne aud mentionnée ci-dessus en accédant à console Google Cloud, ou utiliser l'outil de ligne de commande gcloud.

Pour obtenir les valeurs de la chaîne aud depuis la console Google Cloud, accédez aux paramètres Identity-Aware Proxy de votre projet, cliquez sur Plus à côté de la ressource de l'équilibreur de charge, puis sélectionnez Signed Header JWT Audience (Audience de jeton JWT avec en-tête signé). La boîte de dialogue Jeton JWT avec en-tête signé qui apparaît affiche la revendication aud pour la ressource sélectionnée.

menu à développer comportant l'option "Audience de jeton JWT avec en-tête signé"

Pour obtenir les valeurs de la chaîne aud à l'aide de l'outil de ligne de commande gcloud de la gcloud CLI, vous devez connaître l'ID du projet. Vous trouverez l'ID du projet dans la Console Google Cloud Informations sur le projet, puis exécutez les commandes spécifiées ci-dessous pour chaque valeur.

Numéro du projet

Pour obtenir votre numéro de projet à l'aide de l'outil de ligne de commande gcloud, exécutez la commande suivante :

gcloud projects describe PROJECT_ID

La commande renvoie un résultat semblable à celui-ci :

createTime: '2016-10-13T16:44:28.170Z'
lifecycleState: ACTIVE
name: project_name
parent:
  id: '433637338589'
  type: organization
projectId: PROJECT_ID
projectNumber: 'PROJECT_NUMBER'

ID du service

Pour obtenir votre ID de service à l'aide de l'outil de ligne de commande gcloud, exécutez la commande suivante :

gcloud compute backend-services describe SERVICE_NAME --project=PROJECT_ID --global

La commande renvoie un résultat semblable à celui-ci :

affinityCookieTtlSec: 0
backends:
- balancingMode: UTILIZATION
  capacityScaler: 1.0
  group: https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/instanceGroups/my-group
connectionDraining:
  drainingTimeoutSec: 0
creationTimestamp: '2017-04-03T14:01:35.687-07:00'
description: ''
enableCDN: false
fingerprint: zaOnO4k56Cw=
healthChecks:
- https://www.googleapis.com/compute/v1/projects/project_name/global/httpsHealthChecks/my-hc
id: 'SERVICE_ID'
kind: compute#backendService
loadBalancingScheme: EXTERNAL
name: my-service
port: 8443
portName: https
protocol: HTTPS
selfLink: https://www.googleapis.com/compute/v1/projects/project_name/global/backendServices/my-service
sessionAffinity: NONE
timeoutSec: 3610

Récupérer l'identité de l'utilisateur

Si toutes les vérifications ci-dessus réussissent, vous pouvez récupérer l'identité de l'utilisateur. La charge utile du jeton d'ID contient les informations utilisateur suivantes :

Identité de l'utilisateur de la charge utile du jeton d'ID
sub Objet Identifiant unique et stable pour l'utilisateur. Utilisez cette valeur à la place de l'en-tête x-goog-authenticated-user-id.
email Adresse e-mail de l'utilisateur Adresse e-mail de l'utilisateur.
  • Utilisez cette valeur à la place de l'en-tête x-goog-authenticated-user-email.
  • Contrairement à cet en-tête et à la revendication sub, cette valeur ne comporte pas de préfixe d'espace de noms.

Vous trouverez ci-dessous un exemple de code permettant de sécuriser une application avec des en-têtes IAP signés :

C#


using Google.Apis.Auth;
using Google.Apis.Auth.OAuth2;
using System;
using System.Threading;
using System.Threading.Tasks;

public class IAPTokenVerification
{
    /// <summary>
    /// Verifies a signed jwt token and returns its payload.
    /// </summary>
    /// <param name="signedJwt">The token to verify.</param>
    /// <param name="expectedAudience">The audience that the token should be meant for.
    /// Validation will fail if that's not the case.</param>
    /// <param name="cancellationToken">The cancellation token to propagate cancellation requests.</param>
    /// <returns>A task that when completed will have as its result the payload of the verified token.</returns>
    /// <exception cref="InvalidJwtException">If verification failed. The message of the exception will contain
    /// information as to why the token failed.</exception>
    public async Task<JsonWebSignature.Payload> VerifyTokenAsync(
        string signedJwt, string expectedAudience, CancellationToken cancellationToken = default)
    {
        SignedTokenVerificationOptions options = new SignedTokenVerificationOptions
        {
            // Use clock tolerance to account for possible clock differences
            // between the issuer and the verifier.
            IssuedAtClockTolerance = TimeSpan.FromMinutes(1),
            ExpiryClockTolerance = TimeSpan.FromMinutes(1),
            TrustedAudiences = { expectedAudience },
            TrustedIssuers = { "https://cloud.google.com/iap" },
            CertificatesUrl = GoogleAuthConsts.IapKeySetUrl,
        };

        return await JsonWebSignature.VerifySignedTokenAsync(signedJwt, options, cancellationToken: cancellationToken);
    }
}

Go

import (
	"context"
	"fmt"
	"io"

	"google.golang.org/api/idtoken"
)

// validateJWTFromAppEngine validates a JWT found in the
// "x-goog-iap-jwt-assertion" header.
func validateJWTFromAppEngine(w io.Writer, iapJWT, projectNumber, projectID string) error {
	// iapJWT := "YmFzZQ==.ZW5jb2RlZA==.and0" // req.Header.Get("X-Goog-IAP-JWT-Assertion")
	// projectNumber := "123456789"
	// projectID := "your-project-id"
	ctx := context.Background()
	aud := fmt.Sprintf("/projects/%s/apps/%s", projectNumber, projectID)

	payload, err := idtoken.Validate(ctx, iapJWT, aud)
	if err != nil {
		return fmt.Errorf("idtoken.Validate: %w", err)
	}

	// payload contains the JWT claims for further inspection or validation
	fmt.Fprintf(w, "payload: %v", payload)

	return nil
}

// validateJWTFromComputeEngine validates a JWT found in the
// "x-goog-iap-jwt-assertion" header.
func validateJWTFromComputeEngine(w io.Writer, iapJWT, projectNumber, backendServiceID string) error {
	// iapJWT := "YmFzZQ==.ZW5jb2RlZA==.and0" // req.Header.Get("X-Goog-IAP-JWT-Assertion")
	// projectNumber := "123456789"
	// backendServiceID := "backend-service-id"
	ctx := context.Background()
	aud := fmt.Sprintf("/projects/%s/global/backendServices/%s", projectNumber, backendServiceID)

	payload, err := idtoken.Validate(ctx, iapJWT, aud)
	if err != nil {
		return fmt.Errorf("idtoken.Validate: %w", err)
	}

	// payload contains the JWT claims for further inspection or validation
	fmt.Fprintf(w, "payload: %v", payload)

	return nil
}

Java


import com.google.api.client.http.HttpRequest;
import com.google.api.client.json.webtoken.JsonWebToken;
import com.google.auth.oauth2.TokenVerifier;

/** Verify IAP authorization JWT token in incoming request. */
public class VerifyIapRequestHeader {

  private static final String IAP_ISSUER_URL = "https://cloud.google.com/iap";

  // Verify jwt tokens addressed to IAP protected resources on App Engine.
  // The project *number* for your Google Cloud project via 'gcloud projects describe $PROJECT_ID'
  // The project *number* can also be retrieved from the Project Info card in Cloud Console.
  // projectId is The project *ID* for your Google Cloud Project.
  boolean verifyJwtForAppEngine(HttpRequest request, long projectNumber, String projectId)
      throws Exception {
    // Check for iap jwt header in incoming request
    String jwt = request.getHeaders().getFirstHeaderStringValue("x-goog-iap-jwt-assertion");
    if (jwt == null) {
      return false;
    }
    return verifyJwt(
        jwt,
        String.format("/projects/%s/apps/%s", Long.toUnsignedString(projectNumber), projectId));
  }

  boolean verifyJwtForComputeEngine(HttpRequest request, long projectNumber, long backendServiceId)
      throws Exception {
    // Check for iap jwt header in incoming request
    String jwtToken = request.getHeaders().getFirstHeaderStringValue("x-goog-iap-jwt-assertion");
    if (jwtToken == null) {
      return false;
    }
    return verifyJwt(
        jwtToken,
        String.format(
            "/projects/%s/global/backendServices/%s",
            Long.toUnsignedString(projectNumber), Long.toUnsignedString(backendServiceId)));
  }

  private boolean verifyJwt(String jwtToken, String expectedAudience) {
    TokenVerifier tokenVerifier =
        TokenVerifier.newBuilder().setAudience(expectedAudience).setIssuer(IAP_ISSUER_URL).build();
    try {
      JsonWebToken jsonWebToken = tokenVerifier.verify(jwtToken);

      // Verify that the token contain subject and email claims
      JsonWebToken.Payload payload = jsonWebToken.getPayload();
      return payload.getSubject() != null && payload.get("email") != null;
    } catch (TokenVerifier.VerificationException e) {
      System.out.println(e.getMessage());
      return false;
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const iapJwt = 'SOME_ID_TOKEN'; // JWT from the "x-goog-iap-jwt-assertion" header

let expectedAudience = null;
if (projectNumber && projectId) {
  // Expected Audience for App Engine.
  expectedAudience = `/projects/${projectNumber}/apps/${projectId}`;
} else if (projectNumber && backendServiceId) {
  // Expected Audience for Compute Engine
  expectedAudience = `/projects/${projectNumber}/global/backendServices/${backendServiceId}`;
}

const oAuth2Client = new OAuth2Client();

async function verify() {
  // Verify the id_token, and access the claims.
  const response = await oAuth2Client.getIapPublicKeys();
  const ticket = await oAuth2Client.verifySignedJwtWithCertsAsync(
    iapJwt,
    response.pubkeys,
    expectedAudience,
    ['https://cloud.google.com/iap']
  );
  // Print out the info contained in the IAP ID token
  console.log(ticket);
}

verify().catch(console.error);

PHP

namespace Google\Cloud\Samples\Iap;

# Imports Google auth libraries for IAP validation
use Google\Auth\AccessToken;

/**
 * Validate a JWT passed to your App Engine app by Identity-Aware Proxy.
 *
 * @param string $iapJwt The contents of the X-Goog-IAP-JWT-Assertion header.
 * @param string $cloudProjectNumber The project *number* for your Google
 *     Cloud project. This is returned by 'gcloud projects describe $PROJECT_ID',
 *     or in the Project Info card in Cloud Console.
 * @param string $cloudProjectId Your Google Cloud Project ID.
 */
function validate_jwt_from_app_engine(
    string $iapJwt,
    string $cloudProjectNumber,
    string $cloudProjectId
): void {
    $expectedAudience = sprintf(
        '/projects/%s/apps/%s',
        $cloudProjectNumber,
        $cloudProjectId
    );
    validate_jwt($iapJwt, $expectedAudience);
}

/**
 * Validate a JWT passed to your Compute / Container Engine app by Identity-Aware Proxy.
 *
 * @param string $iapJwt The contents of the X-Goog-IAP-JWT-Assertion header.
 * @param string $cloudProjectNumber The project *number* for your Google
 *     Cloud project. This is returned by 'gcloud projects describe $PROJECT_ID',
 *     or in the Project Info card in Cloud Console.
 * @param string $backendServiceId The ID of the backend service used to access the
 *     application. See https://cloud.google.com/iap/docs/signed-headers-howto
 *     for details on how to get this value.
 */
function validate_jwt_from_compute_engine(
    string $iapJwt,
    string $cloudProjectNumber,
    string $backendServiceId
): void {
    $expectedAudience = sprintf(
        '/projects/%s/global/backendServices/%s',
        $cloudProjectNumber,
        $backendServiceId
    );
    validate_jwt($iapJwt, $expectedAudience);
}

/**
 * Validate a JWT passed to your app by Identity-Aware Proxy.
 *
 * @param string $iapJwt The contents of the X-Goog-IAP-JWT-Assertion header.
 * @param string $expectedAudience The expected audience of the JWT with the following formats:
 *     App Engine:     /projects/{PROJECT_NUMBER}/apps/{PROJECT_ID}
 *     Compute Engine: /projects/{PROJECT_NUMBER}/global/backendServices/{BACKEND_SERVICE_ID}
 */
function validate_jwt(string $iapJwt, string $expectedAudience): void
{
    // Validate the signature using the IAP cert URL.
    $token = new AccessToken();
    $jwt = $token->verify($iapJwt, [
        'certsLocation' => AccessToken::IAP_CERT_URL
    ]);

    if (!$jwt) {
        print('Failed to validate JWT: Invalid JWT');
        return;
    }

    // Validate token by checking issuer and audience fields.
    assert($jwt['iss'] == 'https://cloud.google.com/iap');
    assert($jwt['aud'] == $expectedAudience);

    print('Printing user identity information from ID token payload:');
    printf('sub: %s', $jwt['sub']);
    printf('email: %s', $jwt['email']);
}

Python

from google.auth.transport import requests
from google.oauth2 import id_token


def validate_iap_jwt(iap_jwt, expected_audience):
    """Validate an IAP JWT.

    Args:
      iap_jwt: The contents of the X-Goog-IAP-JWT-Assertion header.
      expected_audience: The Signed Header JWT audience. See
          https://cloud.google.com/iap/docs/signed-headers-howto
          for details on how to get this value.

    Returns:
      (user_id, user_email, error_str).
    """

    try:
        decoded_jwt = id_token.verify_token(
            iap_jwt,
            requests.Request(),
            audience=expected_audience,
            certs_url="https://www.gstatic.com/iap/verify/public_key",
        )
        return (decoded_jwt["sub"], decoded_jwt["email"], "")
    except Exception as e:
        return (None, None, f"**ERROR: JWT validation error {e}**")

Ruby

# iap_jwt = "The contents of the X-Goog-Iap-Jwt-Assertion header"
# project_number = "The project *number* for your Google Cloud project"
# project_id = "Your Google Cloud project ID"
# backend_service_id = "Your Compute Engine backend service ID"
require "googleauth"

audience = nil
if project_number && project_id
  # Expected audience for App Engine
  audience = "/projects/#{project_number}/apps/#{project_id}"
elsif project_number && backend_service_id
  # Expected audience for Compute Engine
  audience = "/projects/#{project_number}/global/backendServices/#{backend_service_id}"
end

# The client ID as the target audience for IAP
payload = Google::Auth::IDTokens.verify_iap iap_jwt, aud: audience

puts payload

if audience.nil?
  puts "Audience not verified! Supply a project_number and project_id to verify"
end

Tester le code de validation

Si vous accédez à votre application à l'aide des paramètres de requête secure_token_test, IAP inclut un JWT non valide. Utilisez-le pour vous assurer que la logique de validation des JWT gère tous les cas d'échec et pour connaître le comportement de votre application lorsqu'elle reçoit un JWT non valide.

Créer une exception de vérification d'état

Comme mentionné précédemment, les vérifications d'état de Compute Engine et de GKE n'utilisent pas les en-têtes JWT, et IAP ne gère pas ces vérifications. Vous devez configurer votre vérification d'état et votre application pour autoriser l'accès à ces vérifications.

Configurer la vérification d'état

Si vous n'avez pas encore défini de chemin pour votre vérification d'état, attribuez-lui un chemin non sensible à l'aide de la console Google Cloud. Veillez à ce qu'aucune autre ressource ne partage ce chemin.

  1. Accéder à la console Google Cloud Vérifications d'état.
    Accéder à la page "Vérifications d'état"
  2. Cliquez sur la vérification d'état que vous utilisez pour votre application, puis sur Modifier.
  3. Dans le champ Chemin de requête, ajoutez un nom de chemin non sensible. Cela permet de spécifier le chemin d'URL que Google Cloud utilise lors de l'envoi de requêtes de vérification d'état. En cas d'omission, la requête de vérification d'état est envoyée à /.
  4. Cliquez sur Save.

Configurer la validation JWT

Dans votre code qui appelle le processus de validation JWT, ajoutez une condition pour renvoyer un code 200 à votre chemin de vérification d'état. Exemple :

if HttpRequest.path_info = '/HEALTH_CHECK_REQUEST_PATH'
  return HttpResponse(status=200)
else
  VALIDATION_FUNCTION

Les JWT pour les identités externes

Si vous utilisez IAP avec des identités externes, IAP émet tout de même un JWT signé à chaque requête authentifiée, tout comme avec les identités Google. Il existe toutefois quelques différences.

Informations sur le fournisseur

Lorsque vous utilisez des identités externes, la charge utile JWT contient une revendication nommée gcip. Cette revendication contient des informations sur l'utilisateur, telles que son adresse e-mail et l'URL de sa photo, ainsi que tous les autres attributs propres au fournisseur.

Voici un exemple de JWT pour un utilisateur qui s'est connecté avec Facebook :

"gcip": '{
  "auth_time": 1553219869,
  "email": "[email protected]",
  "email_verified": false,
  "firebase": {
    "identities": {
      "email": [
        "[email protected]"
      ],
      "facebook.com": [
        "1234567890"
      ]
    },
    "sign_in_provider": "facebook.com",
  },
  "name": "Facebook User",
  "picture: "https://graph.facebook.com/1234567890/picture",
  "sub": "gZG0yELPypZElTmAT9I55prjHg63"
}',

Champs email et sub

Si un utilisateur a été authentifié par Identity Platform, les champs email et sub du JWT sont préfixés avec l'émetteur de jeton Identity Platform et l'ID de locataire utilisé (le cas échéant). Exemple :

"email": "securetoken.google.com/PROJECT-ID/TENANT-ID:[email protected]",
"sub": "securetoken.google.com/PROJECT-ID/TENANT-ID:gZG0yELPypZElTmAT9I55prjHg63"

Contrôler l'accès avec sign_in_attributes

IAM n'est pas compatible avec les identités externes, mais vous pouvez contrôler l'accès à l'aide de revendications intégrées dans le champ sign_in_attributes à la place. Prenons l'exemple d'un utilisateur qui s'est connecté avec un fournisseur SAML :

{
  "aud": "/projects/project_number/apps/my_project_id",
  "gcip": '{
    "auth_time": 1553219869,
    "email": "[email protected]",
    "email_verified": true,
    "firebase": {
      "identities": {
        "email": [
          "[email protected]"
        ],
        "saml.myProvider": [
          "[email protected]"
        ]
      },
      "sign_in_attributes": {
        "firstname": "John",
        "group": "test group",
        "role": "admin",
        "lastname": "Doe"
      },
      "sign_in_provider": "saml.myProvider",
      "tenant": "my_tenant_id"
    },
    "sub": "gZG0yELPypZElTmAT9I55prjHg63"
  }',
  "email": "securetoken.google.com/my_project_id/my_tenant_id:[email protected]",
  "exp": 1553220470,
  "iat": 1553219870,
  "iss": "https://cloud.google.com/iap",
  "sub": "securetoken.google.com/my_project_id/my_tenant_id:gZG0yELPypZElTmAT9I55prjHg63"
}

Vous pouvez ajouter à votre application une logique semblable au code ci-dessous pour restreindre l'accès aux utilisateurs disposant d'un rôle valide :

const gcipClaims = JSON.parse(decodedIapJwtClaims.gcip);
if (gcipClaims &&
    gcipClaims.firebase &&
    gcipClaims.firebase.sign_in_attributes &&
    gcipClaims.firebase.sign_in_attribute.role === 'admin') {
  // Allow access to admin restricted resource.
} else {
  // Block access.
}

Vous pouvez accéder à d'autres attributs utilisateur des fournisseurs SAML et OIDC Identity Platform à l'aide de la revendication imbriquée gcipClaims.gcip.firebase.sign_in_attributes.

Limites de taille des revendications IdP

Lorsqu'un utilisateur s'est connecté avec Identity Platform, les attributs utilisateur supplémentaires est propagée à la charge utile du jeton d'ID Identity Platform sans état, sont transmises de façon sécurisée à IAP. IAP puis émet son propre cookie opaque sans état contenant les mêmes déclarations. IAP générera l'en-tête JWT signé en fonction du cookie contenus.

Par conséquent, si une session est lancée avec un grand nombre de revendications, ne dépassent pas la taille maximale autorisée des cookies, qui est généralement d'environ 4 Ko dans la plupart des navigateurs. L'opération de connexion échoue.

Vous devez vous assurer que seules les revendications nécessaires sont propagées dans le fournisseur d'identité SAML ou OIDC. Vous pouvez aussi utiliser des fonctions de blocage pour filtrer qui ne sont pas requises pour le contrôle des autorisations.

const gcipCloudFunctions = require('gcip-cloud-functions');

const authFunctions = new gcipCloudFunctions.Auth().functions();

// This function runs before any sign-in operation.
exports.beforeSignIn = authFunctions.beforeSignInHandler((user, context) => {
  if (context.credential &&
      context.credential.providerId === 'saml.my-provider') {
    // Get the original claims.
    const claims = context.credential.claims;
    // Define this function to filter out the unnecessary claims.
    claims.groups = keepNeededClaims(claims.groups);
    // Return only the needed claims. The claims will be propagated to the token
    // payload.
    return {
      sessionClaims: claims,
    };
  }
});