

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Configuration de l'autorisation et de l'authentification pour sécuriser votre GraphQL APIs
<a name="security-authz"></a>

AWS AppSync propose les types d'autorisation suivants pour sécuriser GraphQL APIs : clés API, Lambda, IAM, OpenID Connect et groupes d'utilisateurs Cognito. Chaque option propose une méthode de sécurité différente : 

1. **Autorisation par clé d'API** : contrôle la limitation en cas de non-authentification APIs, fournissant une option de sécurité simple. 

1. **Autorisation Lambda** : active une logique d'autorisation personnalisée, expliquant en détail les entrées et sorties des fonctions. 

1. **Autorisation IAM** : utilise le processus AWS de signature version 4 de la version 4 de la solution, permettant un contrôle d'accès précis grâce à des politiques IAM. 

1. **Autorisation OpenID Connect** : s'intègre aux services conformes à l'OIDC pour l'authentification des utilisateurs. 

1. Groupes **d'utilisateurs de Cognito** : implémente un contrôle d'accès basé sur les groupes à l'aide des fonctionnalités de gestion des utilisateurs de Cognito. 

## Types d'autorisation
<a name="authorization-types"></a>

Il existe cinq manières d'autoriser les applications à interagir avec votre API AWS AppSync GraphQL. Vous spécifiez le type d'autorisation que vous utilisez en spécifiant l'une des valeurs de type d'autorisation suivantes dans votre appel AWS AppSync d'API ou de CLI :
+   
** `API_KEY` **  
Pour utiliser des clés API.
+   
** `AWS_LAMBDA` **  
Pour utiliser une AWS Lambda fonction.
+   
** `AWS_IAM` **  
Pour utiliser les autorisations Gestion des identités et des accès AWS ([IAM](https://aws.amazon.com/iam/)).
+   
** `OPENID_CONNECT` **  
Pour utiliser votre fournisseur OpenID Connect.
+   
** `AMAZON_COGNITO_USER_POOLS` **  
Pour utiliser un groupe d'utilisateurs Amazon Cognito.

Ces types d'autorisation de base fonctionnent pour la plupart des développeurs. Pour des cas d'utilisation plus avancés, vous pouvez ajouter des modes d'autorisation supplémentaires via la console, la CLI et AWS CloudFormation. Pour les modes d'autorisation supplémentaires, AWS AppSync fournit un type d'autorisation qui prend les valeurs répertoriées ci-dessus (c'est-à-dire `API_KEY``AWS_LAMBDA`,`AWS_IAM`,`OPENID_CONNECT`, et`AMAZON_COGNITO_USER_POOLS`).

Lorsque vous spécifiez `API_KEY``AWS_LAMBDA`, ou `AWS_IAM` en tant que type d'autorisation principal ou par défaut, vous ne pouvez pas les spécifier à nouveau comme l'un des modes d'autorisation supplémentaires. De même, vous ne pouvez pas dupliquer `API_KEY` `AWS_LAMBDA` ou `AWS_IAM` utiliser les modes d'autorisation supplémentaires. Vous pouvez utiliser plusieurs groupes d'utilisateurs Amazon Cognito et fournisseurs OpenID Connect. Toutefois, vous ne pouvez pas utiliser de groupes d'utilisateurs Amazon Cognito ou de fournisseurs OpenID Connect dupliqués entre le mode d'autorisation par défaut et l'un des modes d'autorisation supplémentaires. Vous pouvez spécifier différents clients pour votre groupe d'utilisateurs Amazon Cognito ou votre fournisseur OpenID Connect à l'aide de l'expression régulière de configuration correspondante.

Lorsque vous enregistrez les modifications apportées à la configuration de votre API, AWS AppSync commence à propager les modifications. Jusqu'à ce que votre modification de configuration soit propagée, AWS AppSync continue de diffuser le contenu de la configuration précédente. Une fois votre modification de configuration propagée, commence AWS AppSync immédiatement à diffuser votre contenu en fonction de la nouvelle configuration. Lors AWS AppSync de la propagation de vos modifications pour une API, nous ne pouvons pas déterminer si l'API diffuse votre contenu en fonction de la configuration précédente ou de la nouvelle configuration.

## API\$1KEY autorisation
<a name="api-key-authorization"></a>

Les méthodes non authentifiées APIs nécessitent une régulation plus stricte que les méthodes authentifiées. APIs Pour contrôler les limitations des points de terminaison GraphQL non authentifiés, vous pouvez utiliser des clés API. Une clé API est une valeur codée en dur dans votre application, qui est générée par le service AWS AppSync quand vous créez un point de terminaison GraphQL non authentifié. Vous pouvez faire pivoter les clés d'API depuis la console, depuis la CLI ou depuis la [référence AWS AppSync d'API](https://docs.aws.amazon.com/appsync/latest/APIReference/).

------
#### [ Console ]

1. Connectez-vous à la [AppSync console AWS Management Console et ouvrez-la](https://console.aws.amazon.com/appsync/).

   1. Dans le **APIs tableau de bord**, choisissez votre API GraphQL.

   1. Dans la **barre latérale**, choisissez **Réglages.**

1. Sous **Mode d'autorisation par défaut**, choisissez la **clé API**.

1. Dans le tableau des **clés d'API**, choisissez **Ajouter une clé d'API**.

   Une nouvelle clé d'API sera générée dans le tableau.

   1. Pour supprimer une ancienne clé d'API, sélectionnez-la dans le tableau, puis choisissez **Supprimer**.

1. En bas de la page, sélectionnez **Save** (Enregistrer).

------
#### [ CLI ]

1. Si ce n'est pas déjà fait, configurez votre accès à la AWS CLI. Pour plus d'informations, consultez la section [Principes de base de la configuration](https://docs.aws.amazon.com//cli/latest/userguide/cli-configure-quickstart.html).

1. Créez un objet d'API GraphQL en exécutant la [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-graphql-api.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-graphql-api.html)commande.

   Vous devez saisir deux paramètres pour cette commande en particulier :

   1. Celui `api-id` de votre API GraphQL.

   1. La nouveauté `name` de votre API. Vous pouvez utiliser le même`name`.

   1. Le`authentication-type`, qui sera`API_KEY`.
**Note**  
Il existe d'autres paramètres tels `Region` que ceux qui doivent être configurés, mais ils seront généralement définis par défaut sur les valeurs de configuration de votre CLI.

   Un exemple de commande peut ressembler à ceci :

   ```
   aws appsync update-graphql-api --api-id abcdefghijklmnopqrstuvwxyz --name TestAPI --authentication-type API_KEY
   ```

   Une sortie sera renvoyée dans la CLI. Voici un exemple en JSON :

   ```
   {
       "graphqlApi": {
           "xrayEnabled": false,
           "name": "TestAPI",
           "authenticationType": "API_KEY",
           "tags": {},
           "apiId": "abcdefghijklmnopqrstuvwxyz",
           "uris": {
               "GRAPHQL": "https://s8i3kk3ufhe9034ujnv73r513e.appsync-api.us-west-2.amazonaws.com/graphql",
               "REALTIME": "wss://s8i3kk3ufhe9034ujnv73r513e.appsync-realtime-api.us-west-2.amazonaws.com/graphql"
           },
           "arn": "arn:aws:appsync:us-west-2:348581070237:apis/abcdefghijklmnopqrstuvwxyz"
       }
   }
   ```

------

Les clés API sont configurables pour une durée maximale de 365 jours et vous pouvez prolonger une date d'expiration existante de 365 jours maximum à partir de cette date. Les clés API sont recommandées pour le développement ou pour les cas d'utilisation où il est possible d'exposer une API publique en toute sécurité.

Sur le client, la clé API est spécifiée par l'en-tête `x-api-key`.

Par exemple, si votre `API_KEY` a pour valeur `'ABC123'`, vous pouvez envoyer une requête GraphQL via `curl` comme suit :

```
$ curl -XPOST -H "Content-Type:application/graphql" -H "x-api-key:ABC123" -d '{ "query": "query { movies { id } }" }' https://YOURAPPSYNCENDPOINT/graphql
```

## AWS\$1LAMBDA autorisation
<a name="aws-lambda-authorization"></a>

Vous pouvez implémenter votre propre logique d'autorisation d'API à l'aide d'une AWS Lambda fonction. Vous pouvez utiliser une fonction Lambda pour votre autorisateur principal ou secondaire, mais il ne peut y avoir qu'une seule fonction d'autorisation Lambda par API. Lorsque vous utilisez des fonctions Lambda pour l'autorisation, les règles suivantes s'appliquent :
+ Si les modes d'`AWS_IAM`autorisation `AWS_LAMBDA` et sont activés dans l'API, la signature SigV4 ne peut pas être utilisée comme jeton `AWS_LAMBDA` d'autorisation.
+ Si les modes `OPENID_CONNECT` d'autorisation `AWS_LAMBDA` et ou le mode d'autorisation sont activés sur l'`AMAZON_COGNITO_USER_POOLS`API, le jeton OIDC ne peut pas être utilisé comme jeton `AWS_LAMBDA` d'autorisation. Notez que le jeton OIDC peut être un schéma Bearer.
+ Une fonction Lambda ne doit pas renvoyer plus de 5 Mo de données contextuelles pour les résolveurs.

Par exemple, si votre jeton d'autorisation l'est`'ABC123'`, vous pouvez envoyer une requête GraphQL via curl comme suit : 

```
$ curl -XPOST -H "Content-Type:application/graphql" -H "Authorization:ABC123" -d '{ "query":
         "query { movies { id } }" }' https://YOURAPPSYNCENDPOINT/graphql
```

Les fonctions Lambda sont appelées avant chaque requête ou mutation. La valeur de retour peut être mise en cache en fonction de l'ID d'API et du jeton d'authentification. Lorsqu'une réponse d'autorisation Lambda est inférieure à 1 048 576 octets, elle met en cache la réponse pour les demandes suivantes. AWS AppSync Si la réponse de l'autorisateur Lambda est égale ou supérieure à 1 048 576 octets, AWS AppSync elle n'est pas mise en cache et appelle l'autorisateur Lambda pour chaque demande entrante. Pour optimiser les performances et minimiser les coûts d'appel Lambda, nous vous recommandons de limiter les réponses de l'autorisateur Lambda à 1 048 576 octets. Par défaut, la mise en cache n'est pas activée, mais elle peut être activée au niveau de l'API ou en définissant la `ttlOverride` valeur dans la valeur de retour d'une fonction. 

Une expression régulière qui valide les jetons d'autorisation avant l'appel de la fonction peut être spécifiée si vous le souhaitez. Ces expressions régulières sont utilisées pour valider qu'un jeton d'autorisation est au bon format avant que votre fonction ne soit appelée. Toute demande utilisant un jeton ne correspondant pas à cette expression régulière sera automatiquement refusée. 

Les fonctions Lambda utilisées pour l'autorisation nécessitent qu'une politique principale leur soit appliquée `appsync.amazonaws.com` pour permettre de les AWS AppSync appeler. Cette action est effectuée automatiquement dans la AWS AppSync console ; la AWS AppSync console ne supprime *pas* la politique. Pour plus d'informations sur l'attachement de politiques aux fonctions Lambda, consultez la section [Politiques basées sur les ressources](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html#permissions-resource-serviceinvoke) dans le Guide du développeur. AWS Lambda 

La fonction Lambda que vous spécifiez recevra un événement ayant la forme suivante :

```
{
    "authorizationToken": "ExampleAUTHtoken123123123",
    "requestContext": {
        "apiId": "aaaaaa123123123example123",
        "accountId": "111122223333",
        "requestId": "f4081827-1111-4444-5555-5cf4695f339f",
        "queryString": "mutation CreateEvent {...}\n\nquery MyQuery {...}\n",
        "operationName": "MyQuery",
        "variables": {}
    }
    "requestHeaders": {
        application request headers
    }
}
```

L'`event`objet contient les en-têtes envoyés dans la demande par le client d'application à AWS AppSync.

La fonction d'autorisation doit renvoyer au moins `isAuthorized` un booléen indiquant si la demande est autorisée. AWS AppSync reconnaît les clés suivantes renvoyées par les fonctions d'autorisation Lambda :

**Note**  
La valeur de « `operationName` in » `requestContext` pour une opération de WebSocket connexion est définie par AWS AppSync « `DeepDish:Connect` ».

### Liste des fonctions
<a name="aws-lambda-authorization-list"></a>

`isAuthorized`(booléen, obligatoire)  
Une valeur booléenne indiquant si la valeur in `authorizationToken` est autorisée à effectuer des appels à l'API GraphQL.  
Si cette valeur est vraie, l'exécution de l'API GraphQL continue. Si cette valeur est fausse, un `UnauthorizedException` est augmenté

`deniedFields`(liste de chaînes, facultatif)  
Une liste dont la liste est modifiée de force`null`, même si une valeur a été renvoyée par un résolveur.  
Chaque élément est soit un ARN de champ entièrement qualifié sous la forme de, `arn:aws:appsync:us-east-1:111122223333:apis/GraphQLApiId/types/TypeName/fields/FieldName` soit une forme abrégée de`TypeName.FieldName`. Le formulaire ARN complet doit être utilisé lorsque deux personnes APIs partagent un autorisateur de fonction Lambda et qu'il peut y avoir une ambiguïté entre les types et les champs communs entre les deux. APIs

`resolverContext`(Objet JSON, facultatif)  
Un objet JSON visible comme `$ctx.identity.resolverContext` dans les modèles de résolveur. Par exemple, si la structure suivante est renvoyée par un résolveur :  

```
{
  "isAuthorized":true
  "resolverContext": {
    "banana":"very yellow",
    "apple":"very green" 
  }
}
```
La valeur des modèles intégrés `ctx.identity.resolverContext.apple` au résolveur sera « `very green` ». L'`resolverContext`objet ne prend en charge que les paires clé-valeur. Les clés imbriquées ne sont pas prises en charge.  
La taille totale de cet objet JSON ne doit pas dépasser 5 Mo.

`ttlOverride`(entier, facultatif)  
Le nombre de secondes pendant lesquelles la réponse doit être mise en cache. Si aucune valeur n'est renvoyée, la valeur de l'API est utilisée. S'il s'agit de 0, la réponse n'est pas mise en cache.

Les autorisateurs Lambda ont un délai d'expiration standard de 10 secondes, mais ils peuvent expirer plus tôt en cas de pic de trafic. Nous vous recommandons de concevoir des fonctions à exécuter le plus rapidement possible (moins de 1 seconde) afin d'optimiser les performances de votre API.

Plusieurs AWS AppSync APIs peuvent partager une seule fonction Lambda d'authentification. L'utilisation d'un système d'autorisation entre comptes n'est pas autorisée.

Lorsque vous partagez une fonction d'autorisation entre plusieurs APIs, sachez que les noms de champs abrégés (`typename.fieldname`) peuvent masquer des champs par inadvertance. Pour lever l'ambiguïté d'un champ dans`deniedFields`, vous pouvez spécifier un ARN de champ non ambigu sous la forme de. `arn:aws:appsync:region:accountId:apis/GraphQLApiId/types/typeName/fields/fieldName` 

Pour ajouter une fonction Lambda comme mode d'autorisation par défaut dans : AWS AppSync

------
#### [ Console ]

1. Connectez-vous à la AWS AppSync console et accédez à l'API que vous souhaitez mettre à jour.

1. Accédez à la page des paramètres de votre API.

   Modifiez l'autorisation au niveau de l'API en. **AWS Lambda**

1. Choisissez l'ARN Région AWS et Lambda par rapport auxquels autoriser les appels d'API.
**Note**  
La politique principale appropriée sera ajoutée automatiquement, ce qui vous permettra AWS AppSync d'appeler votre fonction Lambda. 

1. Définissez éventuellement le TTL de réponse et l'expression régulière de validation du jeton.

------
#### [ AWS CLI ]

1. Associez la politique suivante à la fonction Lambda utilisée :

   ```
   aws lambda add-permission --function-name "my-function" --statement-id "appsync" --principal appsync.amazonaws.com --action lambda:InvokeFunction --output text 
   ```
**Important**  
Si vous souhaitez que la politique de la fonction soit limitée à une seule API GraphQL, vous pouvez exécuter cette commande :  

   ```
   aws lambda add-permission --function-name “my-function” --statement-id “appsync” --principal appsync.amazonaws.com --action lambda:InvokeFunction --source-arn “<my AppSync API ARN>” --output text
   ```

1. Mettez à jour votre AWS AppSync API pour utiliser l'ARN de la fonction Lambda donné comme autorisateur :

   ```
   aws appsync update-graphql-api --api-id example2f0ur2oid7acexample --name exampleAPI --authentication-type AWS_LAMBDA --lambda-authorizer-config authorizerUri="arn:aws:lambda:us-east-2:111122223333:function:my-function"
   ```
**Note**  
Vous pouvez également inclure d'autres options de configuration telles que l'expression régulière du jeton. 

------

L'exemple suivant décrit une fonction Lambda qui illustre les différents états d'authentification et de défaillance qu'une fonction Lambda peut avoir lorsqu'elle est utilisée comme mécanisme d'autorisation : AWS AppSync 

```
def handler(event, context):
  # This is the authorization token passed by the client
  token = event.get('authorizationToken')
  # If a lambda authorizer throws an exception, it will be treated as unauthorized. 
  if 'Fail' in token:
    raise Exception('Purposefully thrown exception in Lambda Authorizer.')

  if 'Authorized' in token and 'ReturnContext' in token:
    return {
      'isAuthorized': True,
      'resolverContext': {
        'key': 'value'
      }
    }

  # Authorized with no f
  if 'Authorized' in token:
    return {
      'isAuthorized': True
    }
  # Partial authorization
  if 'Partial' in token:
    return {
      'isAuthorized': True,
      'deniedFields':['user.favoriteColor']
    }
  if 'NeverCache' in token:
    return {
      'isAuthorized': True,
      'ttlOverride': 0
    }
  if 'Unauthorized' in token:
    return {
      'isAuthorized': False
    }
  # if nothing is returned, then the authorization fails. 
  return {}
```

### Contourner les limites d'autorisation des jetons SigV4 et OIDC
<a name="aws-lambda-authorization-create-new-auth-token"></a>

Les méthodes suivantes peuvent être utilisées pour contourner le problème de l'impossibilité d'utiliser votre signature SigV4 ou votre jeton OIDC comme jeton d'autorisation Lambda lorsque certains modes d'autorisation sont activés.

Si vous souhaitez utiliser la signature SigV4 comme jeton d'autorisation Lambda lorsque `AWS_IAM` les modes d'autorisation `AWS_LAMBDA` et sont activés AWS AppSync pour l'API, procédez comme suit :
+ Pour créer un nouveau jeton d'autorisation Lambda, ajoutez des and/or préfixes de suffixes aléatoires à la signature SigV4.
+ Pour récupérer la signature SigV4 d'origine, mettez à jour votre fonction Lambda en supprimant les suffixes de and/or préfixes aléatoires du jeton d'autorisation Lambda. Utilisez ensuite la signature SigV4 d'origine pour l'authentification.

Si vous souhaitez utiliser le jeton OIDC comme jeton d'autorisation Lambda lorsque `OPENID_CONNECT` le mode d'autorisation ou `AMAZON_COGNITO_USER_POOLS` les modes d'autorisation `AWS_LAMBDA` et sont activés AWS AppSync pour l'API, procédez comme suit :
+ Pour créer un nouveau jeton d'autorisation Lambda, ajoutez des and/or préfixes de suffixes aléatoires au jeton OIDC. Le jeton d'autorisation Lambda ne doit pas contenir de préfixe de schéma Bearer.
+ Pour récupérer le jeton OIDC d'origine, mettez à jour votre fonction Lambda en supprimant les suffixes de and/or préfixes aléatoires du jeton d'autorisation Lambda. Utilisez ensuite le jeton OIDC d'origine pour l'authentification.

## AWS\$1IAM autorisation
<a name="aws-iam-authorization"></a>

Ce type d'autorisation applique le [processus de AWS signature de la version 4 de la signature](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) sur l'API GraphQL. Vous pouvez associer les stratégies d'accès Identity and Access Management ([IAM](https://aws.amazon.com/iam/)) à ce type d'autorisation. Votre application peut tirer parti de cette association en utilisant une clé d'accès (composée d'un identifiant de clé d'accès et d'une clé d'accès secrète) ou en utilisant des informations d'identification temporaires de courte durée fournies par Amazon Cognito Federated Identities.

Si vous souhaitez un rôle pouvant effectuer toutes les opérations de données :

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
            "appsync:GraphQL"
         ],
         "Resource": [
            "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/*"
         ]
      }
   ]
}
```

------

Vous pouvez le trouver sur la page principale `YourGraphQLApiId` de liste des API de la AppSync console, directement sous le nom de votre API. Vous pouvez aussi récupérer cet élément via l'interface de ligne de commande : `aws appsync list-graphql-apis` 

Si vous souhaitez limiter l'accès à un nombre limité d'opérations GraphQL, vous pouvez le faire pour les champs racine `Query`, `Mutation` et `Subscription`.

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
            "appsync:GraphQL"
         ],
         "Resource": [
            "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Query/fields/<Field-1>",
            "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Query/fields/<Field-2>",
            "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Mutation/fields/<Field-1>",
            "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Subscription/fields/<Field-1>"
         ]
     }
   ]
}
```

------

Par exemple, supposons que vous ayez le schéma suivant et que vous souhaitiez limiter l'accès à l'obtention de tous les billets de blog :

```
schema {
   query: Query
   mutation: Mutation
}

type Query {
   posts:[Post!]!
}

type Mutation {
   addPost(id:ID!, title:String!):Post!
}
```

La politique IAM correspondante pour un rôle (que vous pourriez associer à un pool d'identités Amazon Cognito, par exemple) se présente comme suit :

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
            "appsync:GraphQL"
            ],
            "Resource": [
                "arn:aws:appsync:us-west-2:123456789012:apis/YourGraphQLApiId/types/Query/fields/posts"
            ]
        }
    ]
}
```

------

## OPENID\$1CONNECT autorisation
<a name="openid-connect-authorization"></a>

Ce type d'autorisation applique les jetons [OpenID](https://openid.net/specs/openid-connect-core-1_0.html) connect (OIDC) fournis par un service conforme à l'OIDC. Votre application peut tirer parti des utilisateurs et des privilèges définis par votre fournisseur OIDC pour le contrôle des accès.

La seule valeur de configuration obligatoire que vous fournissez à AWS AppSync est une URL d'auteur (par exemple, `https://auth.example.com`). Cette URL doit être adressable via HTTPS. AWS AppSync [s'ajoute `/.well-known/openid-configuration` à l'URL de l'émetteur et localise la configuration OpenID conformément à la spécification OpenID Connect `https://auth.example.com/.well-known/openid-configuration` Discovery.](https://openid.net/specs/openid-connect-discovery-1_0.html) Il s'attend à récupérer un document JSON [RFC5785](https://tools.ietf.org/html/rfc5785)conforme à cette URL. Ce document JSON doit contenir une `jwks_uri` clé pointant vers le document JSON Web Key Set (JWKS) contenant les clés de signature. AWS AppSync nécessite que le JWKS contienne les champs JSON de et`kty`. `kid`

AWS AppSync prend en charge un large éventail d'algorithmes de signature.


| Algorithmes de signature | 
| --- | 
| RS256 | 
| RS384 | 
| RS512 | 
| PS256 | 
| PS384 | 
| PS512 | 
| HS256 | 
| HS384 | 
| HS512 | 
| ES256 | 
| ES384 | 
| ES512 | 

Nous vous recommandons d'utiliser les algorithmes RSA. Les jetons émis par le fournisseur doivent inclure l'heure d'émission du jeton (`iat`) et peuvent inclure son heure d'authentification (`auth_time`). Vous pouvez fournir des valeurs de durée de vie (TTL) pour l'heure d'émission (`iatTTL`) et l'heure d'authentification (`authTTL`) dans votre configuration OpenID Connect afin de renforcer la validation. Si votre fournisseur autorise plusieurs applications, vous pouvez également fournir une expression régulière (`clientId`) qui est utilisée pour les autorisations par ID client. Lorsque le `clientId` est présent dans votre configuration OpenID Connect, AWS AppSync valide la réclamation en demandant qu'il corresponde `clientId` à la réclamation `aud` ou à la `azp` réclamation figurant dans le jeton.

Pour valider plusieurs clients, IDs utilisez l'opérateur de pipeline (« \$1 ») qui est un « ou » dans une expression régulière. Par exemple, si votre application OIDC possède quatre clients avec un client IDs tel que 0A1S2D, 1F4G9H, 1J6L4B, 6 MG, pour valider uniquement les trois premiers clients, vous devez placer 1F4G9H\$11J6L4B\$16 GS5 MG dans le champ ID client. IDs GS5

Si une API est configurée avec plusieurs types d'autorisation, AWS AppSync valide l'émetteur (iss claim) présent dans le jeton JWT à partir des en-têtes de demande en le comparant à l'URL de l'émetteur spécifiée dans la configuration de l'API. Toutefois, lorsqu'une API est configurée uniquement avec OPENID\$1CONNECT autorisation, cette étape de validation de l'URL de l'émetteur est AWS AppSync ignorée.

## AMAZON\$1COGNITO\$1USER\$1POOLS autorisation
<a name="amazon-cognito-user-pools-authorization"></a>

Ce type d'autorisation applique les jetons OIDC fournis par les groupes d'utilisateurs Amazon Cognito. Votre application peut exploiter les utilisateurs et les groupes de vos groupes d'utilisateurs et ceux d'un autre AWS compte et les associer à des champs GraphQL pour contrôler l'accès.

Lorsque vous utilisez les groupes d'utilisateurs Amazon Cognito, vous pouvez créer des groupes auxquels les utilisateurs appartiennent. Ces informations sont codées dans un jeton JWT que votre application envoie AWS AppSync dans un en-tête d'autorisation lors de l'envoi d'opérations GraphQL. Vous pouvez utiliser les directives GraphQL sur le schéma pour contrôler les groupes pouvant appeler des résolveurs sur un champ, ainsi que les résolveurs pouvant être appelés, ce qui permet à vos clients de bénéficier d'un accès plus contrôlé.

Supposons, par exemple, que vous ayez le schéma GraphQL suivant :

```
schema {
   query: Query
   mutation: Mutation
}

type Query {
   posts:[Post!]!
}

type Mutation {
   addPost(id:ID!, title:String!):Post!
}
...
```

Si vous avez deux groupes dans les groupes d'utilisateurs d'Amazon Cognito (les blogueurs et les lecteurs) et que vous souhaitez restreindre le nombre de lecteurs afin qu'ils ne puissent pas ajouter de nouvelles entrées, votre schéma doit ressembler à ceci :

```
schema {
   query: Query
   mutation: Mutation
}
```

```
type Query {
   posts:[Post!]!
   @aws_auth(cognito_groups: ["Bloggers", "Readers"])
}

type Mutation {
   addPost(id:ID!, title:String!):Post!
   @aws_auth(cognito_groups: ["Bloggers"])
}
...
```

Notez que vous pouvez omettre la `@aws_auth` directive si vous souhaitez utiliser par défaut une grant-or-deny stratégie d'accès spécifique. Vous pouvez spécifier la grant-or-deny stratégie dans la configuration du groupe d'utilisateurs lorsque vous créez votre API GraphQL via la console ou via la commande CLI suivante :

```
$ aws appsync --region us-west-2 create-graphql-api --authentication-type AMAZON_COGNITO_USER_POOLS  --name userpoolstest --user-pool-config '{ "userPoolId":"test", "defaultEffect":"ALLOW", "awsRegion":"us-west-2"}'
```

## Utilisation de modes d'autorisation supplémentaires
<a name="using-additional-authorization-modes"></a>

Lorsque vous ajoutez des modes d'autorisation supplémentaires, vous pouvez configurer directement le paramètre d'autorisation au niveau de l'API AWS AppSync GraphQL (c'est-à-dire le `authenticationType` champ que vous pouvez configurer directement sur l'`GraphqlApi`objet) et il agit comme paramètre par défaut sur le schéma. Cela signifie que tout type n'ayant pas de directive spécifique doit transmettre le paramètre d'autorisation au niveau de l'API.

Au niveau du schéma, vous pouvez spécifier des modes d'autorisation supplémentaires à l'aide de directives sur le schéma. Vous pouvez spécifier des modes d'autorisation sur des champs spécifiques du schéma. Par exemple, pour l'autorisation `API_KEY`, vous devez utiliser `@aws_api_key` sur les définitions/champs de type d'objet de schéma. Les directives suivantes sont prises en charge sur les champs de schéma et les définitions de types d'objet :
+  `@aws_api_key` : permet de spécifier que le champ a l'autorisation `API_KEY`.
+  `@aws_iam` : permet de spécifier que le champ a l'autorisation `AWS_IAM`.
+  `@aws_oidc` : permet de spécifier que le champ a l'autorisation `OPENID_CONNECT`.
+  `@aws_cognito_user_pools` : permet de spécifier que le champ a l'autorisation `AMAZON_COGNITO_USER_POOLS`.
+  `@aws_lambda` : permet de spécifier que le champ a l'autorisation `AWS_LAMBDA`.

Vous ne pouvez pas utiliser la directive `@aws_auth` avec des modes d'autorisation supplémentaires. `@aws_auth` fonctionne uniquement dans le contexte de l'autorisation `AMAZON_COGNITO_USER_POOLS` sans mode d'autorisation supplémentaire. Cependant, vous pouvez utiliser la directive `@aws_cognito_user_pools` à la place de la directive `@aws_auth`, en utilisant les mêmes arguments. La principale différence entre les deux est que vous pouvez spécifier `@aws_cognito_user_pools` sur n'importe quelle définition de champ et de type d'objet.

Pour comprendre comment fonctionnent les modes d'autorisation supplémentaires et comment ils peuvent être spécifiés sur un schéma, examinons le schéma suivant :

```
schema {
   query: Query
   mutation: Mutation
}

type Query {
   getPost(id: ID): Post
   getAllPosts(): [Post]
   @aws_api_key
}

type Mutation {
   addPost(
      id: ID!
      author: String!
      title: String!
      content: String!
      url: String!
   ): Post!
}

type Post @aws_api_key @aws_iam {
   id: ID!
   author: String
   title: String
   content: String
   url: String
   ups: Int!
   downs: Int!
   version: Int!
}
...
```

Pour ce schéma, supposons qu'il `AWS_IAM` s'agit du type d'autorisation par défaut sur l'API AWS AppSync GraphQL. Cela signifie que les champs qui n'ont pas de directive sont protégés à l'aide de `AWS_IAM`. Par exemple, c'est le cas pour le champ `getPost` sur le type `Query`. Les directives de schéma vous permettent d'utiliser plusieurs modes d'autorisation. Par exemple, vous pouvez avoir `API_KEY` configuré un mode d'autorisation supplémentaire sur l'API AWS AppSync GraphQL, et vous pouvez marquer un champ à l'aide de la `@aws_api_key` directive (par exemple, `getAllPosts` dans cet exemple). Les directives fonctionnent au niveau du champ. Vous devez donc également accorder à `API_KEY` l'accès au type `Post`. Vous pouvez le faire en marquant chaque champ du type `Post` avec une directive ou en marquant le type `Post` avec la directive `@aws_api_key`.

Pour limiter davantage l'accès aux champs du type `Post`, vous pouvez utiliser des directives sur les champs individuels du type `Post`, comme illustré ci-après.

Par exemple, vous pouvez ajouter un champ `restrictedContent` au type `Post` et limiter l'accès à celui-ci à l'aide de la directive `@aws_iam`. Les demandes `AWS_IAM` authentifiées pourront accéder à `restrictedContent`, mais les demandes `API_KEY` ne pourront pas y accéder.

```
type Post @aws_api_key @aws_iam{
   id: ID!
   author: String
   title: String
   content: String
   url: String
   ups: Int!
   downs: Int!
   version: Int!
   restrictedContent: String!
   @aws_iam
}
...
```

## Contrôle précis des accès
<a name="fine-grained-access-control"></a>

Les informations précédentes montrent comment limiter ou accorder l'accès à certains champs GraphQL. Si vous voulez définir des contrôles d'accès sur les données en fonction de certaines conditions (par exemple, en fonction de l'utilisateur effectuant l'appel et du fait qu'il est ou non propriétaire des données), vous pouvez utiliser des modèles de mappage dans vos résolveurs. Vous pouvez également utiliser une logique métier plus complexe, dont vous trouverez la description dans [Filtrage des informations](#aws-appsync-filtering-information).

Cette section explique comment définir les contrôles d'accès à vos données à l'aide d'un modèle de mappage du résolveur DynamoDB.

Avant de poursuivre, si vous n'êtes pas familiarisé avec les modèles de mappage dans AWS AppSync, vous pouvez consulter la référence du modèle de [mappage Resolver et la référence du modèle](resolver-mapping-template-reference.md#aws-appsync-resolver-mapping-template-reference) de [mappage Resolver pour DynamoDB](resolver-mapping-template-reference-dynamodb.md#aws-appsync-resolver-mapping-template-reference-dynamodb).

Dans l'exemple suivant utilisant DynamoDB, supposons que vous utilisiez le schéma de billet de blog précédent et que seuls les utilisateurs ayant créé un article soient autorisés à le modifier. Le processus d'évaluation devrait consister pour l'utilisateur à obtenir des informations d'identification dans son application, à l'aide de groupes d'utilisateurs Amazon Cognito, par exemple, puis à transmettre ces informations d'identification dans le cadre d'une opération GraphQL. Le modèle de mappage remplace alors une valeur des informations d'identification (comme le nom utilisateur) dans une instruction conditionnelle qui sera ensuite comparée à une valeur dans votre base de données.

![\[Diagram showing authentication flow from user login to database operation using Services AWS.\]](http://docs.aws.amazon.com/fr_fr/appsync/latest/devguide/images/FGAC.png)


Pour ajouter cette fonctionnalité, ajoutez un champ GraphQL `editPost` comme suit :

```
schema {
   query: Query
   mutation: Mutation
}

type Query {
   posts:[Post!]!
}

type Mutation {
   editPost(id:ID!, title:String, content:String):Post
   addPost(id:ID!, title:String!):Post!
}
...
```

Le modèle de mappage de résolveur pour `editPost` (illustré dans un exemple à la fin de cette section) doit effectuer une vérification logique par rapport à votre magasin de données afin que seul l'utilisateur ayant créé un billet puisse le modifier. Comme il s'agit d'une opération de modification, elle correspond à une opération `UpdateItem` dans DynamoDB. Vous pouvez effectuer une vérification conditionnelle avant d'exécuter cette action, en utilisant le contexte transmis pour la validation de l'identité de l'utilisateur. Ce dernier se trouve dans un objet `Identity` qui a les valeurs suivantes :

```
{
   "accountId" : "12321434323",
   "cognitoIdentityPoolId" : "",
   "cognitoIdentityId" : "",
   "sourceIP" : "",
   "caller" : "ThisistheprincipalARN",
   "username" : "username",
   "userArn" : "Sameasabove"
}
```

Pour utiliser cet objet dans un appel `UpdateItem` DynamoDB, vous devez enregistrer les informations d'identité utilisateur dans le tableau à des fins de comparaison. Tout d'abord, votre mutation `addPost` doit contenir le créateur. Ensuite, votre mutation `editPost` doit effectuer la vérification conditionnelle avant la mise à jour.

Voici un exemple de code de résolution `addPost` qui stocke l'identité de l'utilisateur sous forme de `Author` colonne :

```
import { util, Context } from '@aws-appsync/utils';
import { put } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const { id: postId, ...item } = ctx.args;
	return put({
		key: { postId },
		item: { ...item, Author: ctx.identity.username },
		condition: { postId: { attributeExists: false } },
	});
}

export const response = (ctx) => ctx.result;
```

Notez que l'attribut `Author` est renseigné à partir de l'objet `Identity`, qui provient de l'application.

Enfin, voici un exemple de code de résolution pour`editPost`, qui met à jour le contenu du billet de blog uniquement si la demande provient de l'utilisateur qui a créé le billet :

```
import { util, Context } from '@aws-appsync/utils';
import { put } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const { id, ...item } = ctx.args;
	return put({
		key: { id },
		item,
		condition: { author: { contains: ctx.identity.username } },
	});
}

export const response = (ctx) => ctx.result;
```

Cet exemple utilise un `PutItem` qui remplace toutes les valeurs plutôt que an`UpdateItem`, mais le même concept s'applique au bloc d'`condition`instructions.

## Filtrer les informations
<a name="aws-appsync-filtering-information"></a>

Il peut arriver que vous ne puissiez pas contrôler la réponse de votre source de données, mais que vous ne souhaitiez pas envoyer des informations inutiles aux clients sur la réussite d'une opération de lecture ou d'écriture sur la source de données. Dans ce cas, vous pouvez filtrer les informations à l'aide d'un modèle de mappage de réponse.

Supposons, par exemple, que vous ne disposiez pas d'un index approprié dans la table DynamoDB de votre billet de blog (tel qu'un index sur). `Author` Vous pouvez utiliser le résolveur suivant :

```
import { util, Context } from '@aws-appsync/utils';
import { get } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	return get({ key: { ctx.args.id } });
}

export function response(ctx) {
	if (ctx.result.author === ctx.identity.username) {
		return ctx.result;
	}
	return null;
}
```

Le gestionnaire de demandes récupère l'élément même si l'appelant n'est pas l'auteur de la publication. Pour éviter que cela ne renvoie toutes les données, le gestionnaire de réponses vérifie que l'appelant correspond à l'auteur de l'article. Si l'appelant ne correspond pas à ce contrôle, seule une réponse null est renvoyée.

## Accès à une source de données
<a name="data-source-access"></a>

AWS AppSync communique avec les sources de données à l'aide des rôles Identity and Access Management ([IAM](https://aws.amazon.com/iam/)) et des politiques d'accès. Si vous utilisez un rôle existant, une politique de confiance doit être ajoutée AWS AppSync pour pouvoir assumer le rôle. La relation d'approbation doit ressembler à ce qui suit :

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "appsync.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

------

Il est important de définir la stratégie d'accès en fonction du rôle, afin de n'avoir que les autorisations nécessaires pour agir sur l'ensemble minimal de ressources nécessaires. Lorsque vous utilisez la AppSync console pour créer une source de données et un rôle, cela se fait automatiquement pour vous. Cependant, lorsque vous utilisez un modèle d'exemple intégré de la console IAM pour créer un rôle en dehors de la console AWS AppSync, les permissions ne seront pas automatiquement limitées à une ressource et vous devez effectuer cette action avant de déplacer votre application en production.

# Cas d'utilisation du contrôle d'accès pour sécuriser les demandes et les réponses
<a name="security-authorization-use-cases"></a>

Dans la section [Sécurité](security-authz.md#aws-appsync-security), vous avez découvert les différents modes d'autorisation pour protéger votre API et avez bénéficié d'une présentation des mécanismes d'autorisation granulaire pour comprendre les concepts et le flux. Comme il vous AWS AppSync permet d'effectuer des opérations logiques complètes sur les données à l'aide de [modèles de mappage](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview) GraphQL Resolver, vous pouvez protéger les données en lecture ou en écriture de manière très flexible en combinant identité utilisateur, conditions et injection de données.

Si vous n'êtes pas habitué à modifier des AWS AppSync résolveurs, consultez le [guide de programmation](resolver-mapping-template-reference-programming-guide.md#aws-appsync-resolver-mapping-template-reference-programming-guide).

## Présentation de
<a name="overview"></a>

L'accès aux données d'un système se fait traditionnellement par le biais d'une [matrice de contrôle d'accès](https://en.wikipedia.org/wiki/Access_Control_Matrix) où l'intersection d'une ligne (ressource) et d'une colonne (utilisateur/rôle) correspond aux autorisations accordées.

AWS AppSync utilise les ressources de votre propre compte et intègre les informations d'identité (utilisateur/rôle) dans la requête et la réponse GraphQL sous forme d'[objet contextuel](resolver-context-reference.md#aws-appsync-resolver-mapping-template-context-reference), que vous pouvez utiliser dans le résolveur. Cela signifie que les autorisations peuvent être accordées de façon appropriée sur des opérations de lecture ou d'écriture en fonction de la logique du résolveur. Si cette logique se situe au niveau des ressources, par exemple, seuls certains utilisateurs ou groupes nommés peuvent accéder read/write à une ligne de base de données spécifique, ces « métadonnées d'autorisation » doivent être stockées. AWS AppSync ne stocke aucune donnée. Vous devez donc stocker ces métadonnées d'autorisation avec les ressources afin que les autorisations puissent être calculées. Les métadonnées d'autorisation sont généralement un attribut (colonne) d'une table DynamoDB, tel qu'un **propriétaire** ou une liste d'utilisateurs/groupes. Par exemple, il pourrait y avoir des attributs **Readers** et **Writers**.

Depuis un niveau élevé, cela signifie que si vous lisez un élément individuel à partir d'une source de données, vous devez effectuer une déclaration conditionnelle `#if () ... #end` dans le modèle de réponse après que le résolveur a lu à partir de la source de données. Le contrôle utilisera normalement les valeurs d'utilisateur ou de groupe dans `$context.identity` pour les contrôles d'appartenance par rapport aux métadonnées d'autorisation renvoyées par une opération de lecture. Pour plusieurs enregistrements, tels que les listes renvoyées à partir d'une table `Scan` ou `Query`, vous envoyez le contrôle de la condition à la source de données, comme partie intégrante de l'opération, à l'aide de valeurs d'utilisateur ou de groupe similaires.

De même, lors de l'écriture des données, vous appliquerez une instruction conditionnelle à l'action (comme un `PutItem` ou `UpdateItem` pour voir si l'utilisateur ou le groupe effectuant la mutation a l'autorisation). L'instruction conditionnelle utilisera à nouveau à plusieurs reprises une valeur dans `$context.identity` à titre de comparaison avec les métadonnées d'autorisation sur cette ressource. Pour les modèles de demande et de réponse, vous pouvez également utiliser des en-têtes personnalisés provenant des clients pour effectuer les contrôles de validation.

## Lecture de données
<a name="reading-data"></a>

Comme indiqué ci-dessus, les métadonnées d'autorisation pour effectuer un contrôle doivent être stockées avec une ressource ou transmises à la demande GraphQL (identité, en-tête, etc.). Pour illustrer cela, supposons que vous ayez la table DynamoDB ci-dessous :

![\[DynamoDB table with ID, Data, PeopleCanAccess, GroupsCanAccess, and Owner columns.\]](http://docs.aws.amazon.com/fr_fr/appsync/latest/devguide/images/auth.png)


La clé primaire est `id` et les données qui doivent être accessibles `Data`. Les autres colonnes sont des exemples de vérifications que vous pouvez effectuer pour obtenir une autorisation. `Owner`prendrait un `String` certain temps `PeopleCanAccess` et `GroupsCanAccess` serait `String Sets` tel que décrit dans la [référence du modèle de mappage Resolver pour DynamoDB](resolver-mapping-template-reference-dynamodb.md#aws-appsync-resolver-mapping-template-reference-dynamodb).

Dans la [présentation du modèle de mappage des résolveurs](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview), le diagramme montre comment le modèle de réponse contient non seulement l'objet de contexte, mais aussi les résultats de la source de données. Pour les requêtes GraphQL des objets individuels, vous pouvez utiliser le modèle de réponse pour vérifier si l'utilisateur est autorisé à voir les résultats ou à renvoyer un message d'erreur relatif à l'autorisation. Cet élément est parfois appelé « filtre d'autorisation ». Pour les requêtes GraphQL renvoyant des listes, à l'aide d'une requête (Query) ou d'une analyse (Scan), il est plus performant d'effectuer le contrôle sur le modèle de demande et de ne renvoyer les données que si une condition d'autorisation est remplie. L'implémentation se présente alors ainsi :

1. GetItem - contrôle d'autorisation pour les enregistrements individuels. Fait à l'aide d'instructions `#if() ... #end`.

1. Opérations Query/Scan – Le contrôle d'autorisation est une déclaration `"filter":{"expression":...}`. Les contrôles courants concernent l'égalité (`attribute = :input`) ou la vérification de la présence d'une valeur dans une liste (`contains(attribute, :input)`).

Dans \$12, l'attribut `attribute` des deux déclarations représente le nom de colonne de l'enregistrement dans une table, comme `Owner` dans notre exemple ci-dessus. Vous pouvez créer un alias à l'aide du signe `#` et utiliser `"expressionNames":{...}`, mais ce n'est pas obligatoire. L'élément `:input` est une référence à la valeur que vous comparez à l'attribut de base de données, que vous définissez dans `"expressionValues":{...}`. Voyez les exemples ci-dessous.

### Cas d'utilisation : le propriétaire sait lire
<a name="use-case-owner-can-read"></a>

À l'aide du tableau ci-dessus, si vous souhaitez uniquement renvoyer les données si `Owner == Nadia` dans le cas d'une opération de lecture (`GetItem`), votre modèle se présente comme suit :

```
#if($context.result["Owner"] == $context.identity.username)
    $utils.toJson($context.result)
#else
    $utils.unauthorized()
#end
```

Quelques remarques à mentionner ici seront réutilisées dans les sections restantes. Tout d'abord, le check utilise `$context.identity.username` le nom d'inscription convivial si les groupes d'utilisateurs Amazon Cognito sont utilisés et l'identité de l'utilisateur si IAM est utilisé (y compris les identités fédérées Amazon Cognito). Il existe d'autres valeurs à enregistrer pour un propriétaire, comme la valeur unique « identité Amazon Cognito », qui est utile lors de la fédération de connexions provenant de plusieurs sites. Vous devriez consulter les options disponibles dans la référence contextuelle du modèle de mappage du [résolveur](resolver-context-reference.md#aws-appsync-resolver-mapping-template-context-reference).

Deuxièmement, le contrôle conditionnel « else » répondant avec `$util.unauthorized()` est totalement facultatif, mais recommandé comme bonne pratique lors de la conception de votre API GraphQL.

### Cas d'utilisation : accès spécifique par code en dur
<a name="use-case-hardcode-specific-access"></a>

```
// This checks if the user is part of the Admin group and makes the call
#foreach($group in $context.identity.claims.get("cognito:groups"))
    #if($group == "Admin")
        #set($inCognitoGroup = true)
    #end
#end
#if($inCognitoGroup)
{
    "version" : "2017-02-28",
    "operation" : "UpdateItem",
    "key" : {
        "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
    },
    "attributeValues" : {
        "owner" : $util.dynamodb.toDynamoDBJson($context.identity.username)
        #foreach( $entry in $context.arguments.entrySet() )
            ,"${entry.key}" : $util.dynamodb.toDynamoDBJson($entry.value)
        #end
    }
}
#else
    $utils.unauthorized()
#end
```

### Cas d'utilisation : filtrage d'une liste de résultats
<a name="use-case-filtering-a-list-of-results"></a>

Dans l'exemple précédent, vous avez été en mesure de contrôler directement `$context.result` tandis qu'il renvoyait un seul élément ; cependant, certaines opérations telles qu'une analyse renvoient plusieurs éléments dans `$context.result.items` où vous devez exécuter le filtre d'autorisation de filtre et retourner uniquement les résultats que l'utilisateur est autorisé à afficher. Supposons que le `Owner` champ comporte cette fois l'identifiant Amazon Cognito IdentityID défini sur l'enregistrement. Vous pouvez ensuite utiliser le modèle de mappage des réponses suivant pour filtrer afin d'afficher uniquement les enregistrements appartenant à l'utilisateur :

```
#set($myResults = [])
#foreach($item in $context.result.items)
    ##For userpools use $context.identity.username instead
    #if($item.Owner == $context.identity.cognitoIdentityId)
        #set($added = $myResults.add($item))
    #end
#end
$utils.toJson($myResults)
```

### Cas d'utilisation : plusieurs personnes peuvent lire
<a name="use-case-multiple-people-can-read"></a>

Une autre option d'autorisation populaire consiste à autoriser un groupe de personnes à pouvoir lire les données. Dans l'exemple ci-dessous, `"filter":{"expression":...}` renvoie uniquement les valeurs d'une analyse de table si l'utilisateur exécutant la requête GraphQL est répertorié dans l'ensemble `PeopleCanAccess`.

```
{
    "version" : "2017-02-28",
    "operation" : "Scan",
    "limit": #if(${context.arguments.count}) $util.toJson($context.arguments.count) #else 20 #end,
    "nextToken": #if(${context.arguments.nextToken})  $util.toJson($context.arguments.nextToken) #else null #end,
    "filter":{
        "expression": "contains(#peopleCanAccess, :value)",
        "expressionNames": {
                "#peopleCanAccess": "peopleCanAccess"
        },
        "expressionValues": {
                ":value": $util.dynamodb.toDynamoDBJson($context.identity.username)
        }
    }
}
```

### Cas d'utilisation : le groupe peut lire
<a name="use-case-group-can-read"></a>

Comme pour le dernier scénario, il se peut que seules les personnes d'un ou de plusieurs groupes aient les droits pour lire certains éléments d'une base de données. L'utilisation de l'opération `"expression": "contains()"` est similaire ; cependant, le fait qu'un utilisateur puisse faire partie de ce qui doit être pris en compte dans l'appartenance à l'ensemble relève d'un OR logique de tous les groupes. Dans ce cas, nous créons une instruction `$expression` ci-dessous pour chaque groupe dont fait partie l'utilisateur, puis la transmettons au filtre :

```
#set($expression = "")
#set($expressionValues = {})
#foreach($group in $context.identity.claims.get("cognito:groups"))
    #set( $expression = "${expression} contains(groupsCanAccess, :var$foreach.count )" )
    #set( $val = {})
    #set( $test = $val.put("S", $group))
    #set( $values = $expressionValues.put(":var$foreach.count", $val))
    #if ( $foreach.hasNext )
    #set( $expression = "${expression} OR" )
    #end
#end
{
    "version" : "2017-02-28",
    "operation" : "Scan",
    "limit": #if(${context.arguments.count}) $util.toJson($context.arguments.count) #else 20 #end,
    "nextToken": #if(${context.arguments.nextToken})  $util.toJson($context.arguments.nextToken) #else null #end,
    "filter":{
        "expression": "$expression",
        "expressionValues": $utils.toJson($expressionValues)
    }
}
```

## Écrire des données
<a name="writing-data"></a>

L'écriture de données sur les mutations est toujours contrôlée sur le modèle de mappage de la demande. Dans le cas des sources de données DynamoDB, la clé consiste à utiliser un `"condition":{"expression"...}"` approprié, qui effectue la validation par rapport aux métadonnées d'autorisation de la table. Dans [Sécurité](security-authz.md#aws-appsync-security), nous avons fourni un exemple que vous pouvez utiliser pour vérifier le champ `Author` dans une table. Les cas d'utilisation de cette section explorent d'autres scénarios.

### Cas d'utilisation : propriétaires multiples
<a name="use-case-multiple-owners"></a>

À l'aide de l'exemple de schéma de table précédent, imaginons la liste `PeopleCanAccess`

```
{
    "version" : "2017-02-28",
    "operation" : "UpdateItem",
    "key" : {
        "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
    },
    "update" : {
        "expression" : "SET meta = :meta",
        "expressionValues": {
            ":meta" : $util.dynamodb.toDynamoDBJson($ctx.args.meta)
        }
    },
    "condition" : {
        "expression"       : "contains(Owner,:expectedOwner)",
        "expressionValues" : {
            ":expectedOwner" : $util.dynamodb.toDynamoDBJson($context.identity.username)
        }
    }
}
```

### Cas d'utilisation : le groupe peut créer un nouvel enregistrement
<a name="use-case-group-can-create-new-record"></a>

```
#set($expression = "")
#set($expressionValues = {})
#foreach($group in $context.identity.claims.get("cognito:groups"))
    #set( $expression = "${expression} contains(groupsCanAccess, :var$foreach.count )" )
    #set( $val = {})
    #set( $test = $val.put("S", $group))
    #set( $values = $expressionValues.put(":var$foreach.count", $val))
    #if ( $foreach.hasNext )
    #set( $expression = "${expression} OR" )
    #end
#end
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key" : {
        ## If your table's hash key is not named 'id', update it here. **
        "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
        ## If your table has a sort key, add it as an item here. **
    },
    "attributeValues" : {
        ## Add an item for each field you would like to store to Amazon DynamoDB. **
        "title" : $util.dynamodb.toDynamoDBJson($ctx.args.title),
        "content": $util.dynamodb.toDynamoDBJson($ctx.args.content),
        "owner": $util.dynamodb.toDynamoDBJson($context.identity.username)
    },
    "condition" : {
        "expression": $util.toJson("attribute_not_exists(id) AND $expression"),
        "expressionValues": $utils.toJson($expressionValues)
    }
}
```

### Cas d'utilisation : le groupe peut mettre à jour un enregistrement existant
<a name="use-case-group-can-update-existing-record"></a>

```
#set($expression = "")
#set($expressionValues = {})
#foreach($group in $context.identity.claims.get("cognito:groups"))
    #set( $expression = "${expression} contains(groupsCanAccess, :var$foreach.count )" )
    #set( $val = {})
    #set( $test = $val.put("S", $group))
    #set( $values = $expressionValues.put(":var$foreach.count", $val))
    #if ( $foreach.hasNext )
    #set( $expression = "${expression} OR" )
    #end
#end
{
    "version" : "2017-02-28",
    "operation" : "UpdateItem",
    "key" : {
        "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
    },
    "update":{
                "expression" : "SET title = :title, content = :content",
        "expressionValues": {
            ":title" : $util.dynamodb.toDynamoDBJson($ctx.args.title),
            ":content" : $util.dynamodb.toDynamoDBJson($ctx.args.content)
        }
    },
    "condition" : {
        "expression": $util.toJson($expression),
        "expressionValues": $utils.toJson($expressionValues)
    }
}
```

## Dossiers publics et privés
<a name="public-and-private-records"></a>

Avec les filtres conditionnels, vous pouvez également choisir de marquer les données comme privées, publiques ou booléennes. Elles peuvent ensuite être combinées dans le cadre d'un filtre d'autorisation à l'intérieur du modèle de réponse. L'utilisation de ce contrôle est un bon moyen de masquer les données temporairement sans tenter de contrôler l'appartenance au groupe.

Par exemple, imaginons que vous ayez ajouté un attribut sur chaque élément de votre table DynamoDB appelé `public` avec la valeur `yes` ou `no`. Le modèle de réponse suivant peut être utilisé sur un appel `GetItem` pour afficher les données uniquement si l'utilisateur se trouve dans un groupe qui a accès ET si ces données sont marquées comme publiques :

```
#set($permissions = $context.result.GroupsCanAccess)
#set($claimPermissions = $context.identity.claims.get("cognito:groups"))

#foreach($per in $permissions)
    #foreach($cgroups in $claimPermissions)
        #if($cgroups == $per)
            #set($hasPermission = true)
        #end
    #end
#end

#if($hasPermission && $context.result.public == 'yes')
    $utils.toJson($context.result)
#else
    $utils.unauthorized()
#end
```

Le code ci-dessus peut également utiliser un OR logique (`||`) pour autoriser les personnes à lire si elles sont autorisés à accéder à un enregistrement ou s'il est public :

```
#if($hasPermission || $context.result.public == 'yes')
    $utils.toJson($context.result)
#else
    $utils.unauthorized()
#end
```

En général, vous trouverez les opérateurs standard `==`, `!=`, `&&` et `||` utiles lors de l'exécution des contrôles d'autorisation.

## Données en temps réel
<a name="security-real-time-data"></a>

Vous pouvez appliquer les contrôles d'accès détaillé aux abonnements GraphQL au moment où un client effectue un abonnement, en utilisant les mêmes techniques que celles décrites plus haut dans la documentation. Vous attachez un résolveur au champ d'abonnement et pouvez alors interroger les données à partir d'une source de données et exécuter une logique conditionnelle dans le modèle de mappage de la demande ou de la réponse. Vous pouvez également renvoyer des données supplémentaires au client, telles que les résultats initiaux d'un abonnement, aussi longtemps que la structure des données correspond à celle du type retourné dans votre abonnement GraphQL.

### Cas d'utilisation : l'utilisateur ne peut s'abonner qu'à des conversations spécifiques
<a name="use-case-user-can-subscribe-to-specific-conversations-only"></a>

Un cas d'utilisation courant pour les données en temps réel avec les abonnements GraphQL consiste à créer une application de messagerie ou chat privé. Lors de la création d'une application de chat qui comporte plusieurs utilisateurs, les conversations peuvent se produire entre deux ou plusieurs personnes. Celles-ci peuvent être regroupées en « salles », qui sont privées ou publiques. À ce titre, vous souhaitez uniquement autoriser un utilisateur à s'abonner à une conversation (qui pourrait être en face à face ou au sein d'un groupe) pour laquelle l'accès lui a été accordé. À des fins de démonstration, l'exemple ci-dessous illustre un simple scénario d'un utilisateur envoyant un message privé à un autre utilisateur. La configuration comporte deux tables Amazon DynamoDB :
+ Table Messages : (clé primaire) `toUser`, (clé de tri) `id` 
+ Table Permissions : (clé primaire) `username` 

La table Messages stocke les messages réels envoyés via une mutation GraphQL. La table Permissions est contrôlée par l'abonnement GraphQL pour l'autorisation au moment de la connexion du client. L'exemple suivant suppose que vous utilisez le schéma GraphQL suivant :

```
input CreateUserPermissionsInput {
    user: String!
    isAuthorizedForSubscriptions: Boolean
}

type Message {
    id: ID
    toUser: String
    fromUser: String
    content: String
}

type MessageConnection {
    items: [Message]
    nextToken: String
}

type Mutation {
    sendMessage(toUser: String!, content: String!): Message
    createUserPermissions(input: CreateUserPermissionsInput!): UserPermissions
    updateUserPermissions(input: UpdateUserPermissionInput!): UserPermissions
}

type Query {
    getMyMessages(first: Int, after: String): MessageConnection
    getUserPermissions(user: String!): UserPermissions
}

type Subscription {
    newMessage(toUser: String!): Message
        @aws_subscribe(mutations: ["sendMessage"])
}

input UpdateUserPermissionInput {
    user: String!
    isAuthorizedForSubscriptions: Boolean
}

type UserPermissions {
    user: String
    isAuthorizedForSubscriptions: Boolean
}

schema {
    query: Query
    mutation: Mutation
    subscription: Subscription
}
```

Certaines des opérations standard, telles que`createUserPermissions()`, ne sont pas abordées ci-dessous pour illustrer les résolveurs d'abonnement, mais sont des implémentations standard des résolveurs DynamoDB. Au lieu de cela, nous allons nous concentrer sur les flux d'autorisation d'abonnement avec les résolveurs. Pour envoyer un message d'un utilisateur à un autre, attachez un résolveur au champ `sendMessage()` et sélectionnez la source de données de la table **Messages** avec le modèle de demande suivant :

```
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key" : {
        "toUser" : $util.dynamodb.toDynamoDBJson($ctx.args.toUser),
        "id" : $util.dynamodb.toDynamoDBJson($util.autoId())
    },
    "attributeValues" : {
        "fromUser" : $util.dynamodb.toDynamoDBJson($context.identity.username),
        "content" : $util.dynamodb.toDynamoDBJson($ctx.args.content),
    }
}
```

Dans cet exemple, nous utilisons `$context.identity.username`. Cela renvoie des informations utilisateur pour Gestion des identités et des accès AWS ou pour les utilisateurs d'Amazon Cognito. Le modèle de réponse est une simple transmission de `$util.toJson($ctx.result)`. Enregistrez et revenez à la page du schéma. Ensuite, attachez un résolveur pour l'abonnement `newMessage()`, à l'aide de la table **Permissions** comme source de données et du modèle de mappage de demande suivant :

```
{
    "version": "2018-05-29",
    "operation": "GetItem",
    "key": {
        "username": $util.dynamodb.toDynamoDBJson($ctx.identity.username),
    },
}
```

Ensuite, utilisez le modèle de mappage de réponse suivant pour exécuter vos contrôles d'autorisation à l'aide des données de la table **Permissions** :

```
#if(! ${context.result})
    $utils.unauthorized()
#elseif(${context.identity.username} != ${context.arguments.toUser})
    $utils.unauthorized()
#elseif(! ${context.result.isAuthorizedForSubscriptions})
    $utils.unauthorized()
#else
##User is authorized, but we return null to continue
    null
#end
```

Dans ce cas, vous effectuez trois contrôles d'autorisation. Le premier garantit qu'un résultat est retourné. Le second garantit que l'utilisateur ne s'abonne pas aux messages destinés à une autre personne. Le troisième garantit que l'utilisateur est autorisé à s'abonner à n'importe quel champ, en vérifiant qu'un attribut DynamoDB est stocké sous la forme `isAuthorizedForSubscriptions` d'un. `BOOL`

Pour tester les choses, vous pouvez vous connecter à la AWS AppSync console à l'aide des groupes d'utilisateurs Amazon Cognito et d'un utilisateur nommé « Nadia », puis exécuter l'abonnement GraphQL suivant :

```
subscription AuthorizedSubscription {
    newMessage(toUser: "Nadia") {
        id
        toUser
        fromUser
        content
    }
}
```

Si, dans la table **Permissions**, il y a un enregistrement pour l'attribut clé `username` de `Nadia` avec `isAuthorizedForSubscriptions` défini sur `true`, vous obtiendrez une réponse positive. Si vous essayez un autre `username` dans la requête `newMessage()` ci-dessus, une erreur est renvoyée.

# Utilisation AWS WAF pour protéger votre AWS AppSync APIs
<a name="WAF-Integration"></a>

AWS WAF est un pare-feu pour applications Web qui aide à protéger les applications Web APIs contre les attaques. Il vous permet de configurer un ensemble de règles, appelé liste de contrôle d'accès Web (ACL Web), qui autorise, bloque ou surveille (compte) les requêtes Web sur la base de règles et de conditions de sécurité Web personnalisables que vous définissez. Lorsque vous intégrez votre AWS AppSync API AWS WAF, vous gagnez en contrôle et en visibilité sur le trafic HTTP accepté par votre API. Pour en savoir plus AWS WAF, consultez la section [Comment AWS WAF fonctionne](https://docs.aws.amazon.com/waf/latest/developerguide/how-aws-waf-works.html) dans le guide du AWS WAF développeur. 

Vous pouvez l'utiliser AWS WAF pour protéger votre AppSync API contre les exploits Web courants, tels que l'injection SQL et les attaques par script intersite (XSS). Celles-ci peuvent affecter la disponibilité et les performances des API, compromettre la sécurité ou consommer des ressources excessives. Par exemple, vous pouvez créer des règles pour autoriser ou bloquer les demandes provenant de plages d'adresses IP spécifiées, les demandes provenant de blocs CIDR, les demandes provenant d'un pays ou d'une région spécifique, les demandes contenant du code SQL malveillant ou les demandes contenant des scripts malveillants.

Vous pouvez également créer des règles qui correspondent à une chaîne spécifiée ou un modèle d'expression régulière dans les en-têtes HTTP, la méthode, la chaîne de requête, l'URI et le corps de la demande (limité aux 8 premiers Ko). De plus, vous pouvez créer des règles pour bloquer les attaques émanant d'agents utilisateurs spécifiques, de robots malveillants et d'extracteurs de contenu. Par exemple, vous pouvez utiliser des règles basées sur le débit pour spécifier le nombre de requêtes web que chaque adresse IP du client est autorisée à envoyer au cours d’une période de 5 minutes mise à jour en continu.

Pour en savoir plus sur les types de règles pris en charge et sur les AWS WAF fonctionnalités supplémentaires, consultez le guide du [AWS WAF développeur et le guide](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html) de [référence des AWS WAF API](https://docs.aws.amazon.com/waf/latest/APIReference/API_Types_AWS_WAFV2.html).

**Important**  
AWS WAF est votre première ligne de défense contre les exploits Web. Lorsqu'elle AWS WAF est activée sur une API, AWS WAF les règles sont évaluées avant les autres fonctionnalités de contrôle d'accès, telles que l'autorisation par clé d'API, les politiques IAM, les jetons OIDC et les groupes d'utilisateurs Amazon Cognito. 

## Intégrer une AppSync API avec AWS WAF
<a name="integrate-API-with-WAF"></a>

Vous pouvez intégrer une API Appsync à AWS WAF l'aide du AWS Management Console, du AWS CLI AWS CloudFormation, ou de tout autre client compatible.

**Pour intégrer une AWS AppSync API à AWS WAF**

1. Créez une ACL AWS WAF Web. Pour connaître les étapes détaillées relatives à l'utilisation de la [AWS WAF console](https://console.aws.amazon.com/waf/), consultez [la section Création d'une ACL Web](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-creating.html).

1. Définissez les règles de l'ACL Web. Une ou plusieurs règles sont définies lors de la création de l'ACL Web. Pour plus d'informations sur la structure des règles, consultez la section [AWS WAF règles](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rules.html). Pour des exemples de règles utiles que vous pouvez définir pour votre AWS AppSync API, consultez[Création de règles pour une ACL Web](#Creating-web-acl-rules).

1. Associez l'ACL Web à une AWS AppSync API. Vous pouvez effectuer cette étape dans la [AWS WAF console](https://console.aws.amazon.com/wafv2/) ou dans la [AppSync console](https://console.aws.amazon.com/appsync/). 
   + Pour associer l'ACL Web à une AWS AppSync API dans la AWS WAF console, suivez les instructions relatives à l'[association ou à la dissociation d'une ACL Web à une AWS ressource](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-associating-aws-resource.html) dans le guide du AWS WAF développeur.
   + Pour associer l'ACL Web à une AWS AppSync API dans la AWS AppSync console

     1. Connectez-vous à la [AppSync console AWS Management Console et ouvrez-la](https://console.aws.amazon.com/appsync/).

     1. Choisissez l'API que vous souhaitez associer à une ACL Web.

     1. Dans le panneau de navigation, sélectionnez **Settings** (Paramètres).

     1. Dans la section **Pare-feu des applications Web**, activez **Activer AWS WAF**.

     1. Dans la liste déroulante **Web ACL**, choisissez le nom de l'ACL Web à associer à votre API.

     1. Choisissez **Enregistrer** pour associer l'ACL Web à votre API.

   

**Note**  
Après avoir créé une ACL Web dans la AWS WAF console, la disponibilité de la nouvelle ACL Web peut prendre quelques minutes. Si aucune ACL Web nouvellement créée ne s'affiche dans le menu du **pare-feu des applications Web**, attendez quelques minutes et recommencez les étapes pour associer l'ACL Web à votre API.

**Note**  
AWS WAF l'intégration ne prend en charge l'`Subscription registration message`événement que pour les points de terminaison en temps réel. AWS AppSync répondra par un message d'erreur au lieu d'un `start_ack` message pour tout message `Subscription registration message` bloqué par AWS WAF. 

Après avoir associé une ACL Web à une AWS AppSync API, vous allez gérer l'ACL Web à l'aide du AWS WAF APIs. Il n'est pas nécessaire de réassocier l'ACL Web à votre AWS AppSync API, sauf si vous souhaitez associer l' AWS AppSync API à une autre ACL Web.

## Création de règles pour une ACL Web
<a name="Creating-web-acl-rules"></a>

Les règles définissent comment inspecter les requêtes Web et ce qu'il faut faire lorsqu'une demande Web correspond aux critères d'inspection. Les règles n'existent pas AWS WAF en elles-mêmes. Vous pouvez accéder à une règle par son nom dans un groupe de règles ou dans l'ACL Web où elle est définie. Pour plus d'informations, consultez [AWS WAF les règles](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rules.html). Les exemples suivants montrent comment définir et associer des règles utiles pour protéger une AppSync API.

**Example règle ACL Web pour limiter la taille du corps de la demande**  
Voici un exemple de règle qui limite la taille du corps des demandes. Cela serait saisi dans l'**éditeur Rule JSON** lors de la création d'une ACL Web dans la AWS WAF console.  

```
{
    "Name": "BodySizeRule", 
    "Priority": 1, 
    "Action": {
        "Block": {}
    }, 
    "Statement": {
        "SizeConstraintStatement": {
            "ComparisonOperator": "GE",
            "FieldToMatch": {
                "Body": {}
            },
            "Size": 1024, 
            "TextTransformations": [
                {
                    "Priority": 0, 
                    "Type": "NONE"
                }
             ]
          }
       }, 
       "VisibilityConfig": {
           "CloudWatchMetricsEnabled": true, 
           "MetricName": "BodySizeRule", 
           "SampledRequestsEnabled": true
        }
}
```
Après avoir créé votre ACL Web à l'aide de l'exemple de règle précédent, vous devez l'associer à votre AppSync API. Au lieu d'utiliser le AWS Management Console, vous pouvez effectuer cette étape en AWS CLI exécutant la commande suivante.  

```
aws waf associate-web-acl --web-acl-id waf-web-acl-arn --resource-arn appsync-api-arn
```
La propagation des modifications peut prendre quelques minutes, mais après l'exécution de cette commande, les demandes dont le corps est supérieur à 1024 octets seront rejetées par AWS AppSync.  
Une fois que vous avez créé une nouvelle ACL Web dans la AWS WAF console, l'association de cette ACL à une API peut prendre quelques minutes. Si vous exécutez la commande CLI et qu'une `WAFUnavailableEntityException` erreur s'affiche, attendez quelques minutes et réessayez d'exécuter la commande.

**Example règle ACL Web pour limiter les demandes provenant d'une seule adresse IP**  
Voici un exemple de règle qui limite une AppSync API à 100 requêtes provenant d'une seule adresse IP. Cela serait saisi dans l'**éditeur JSON de règles** lors de la création d'une ACL Web avec une règle basée sur le taux dans la AWS WAF console.  

```
{
  "Name": "Throttle",
  "Priority": 0,
  "Action": {
    "Block": {}
  },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "Throttle"
  },
  "Statement": {
    "RateBasedStatement": {
      "Limit": 100,
      "AggregateKeyType": "IP"
    }
  }
}
```
Après avoir créé votre ACL Web à l'aide de l'exemple de règle précédent, vous devez l'associer à votre AppSync API. Vous pouvez effectuer cette étape en AWS CLI exécutant la commande suivante.  

```
aws waf associate-web-acl --web-acl-id waf-web-acl-arn --resource-arn appsync-api-arn
```

**Example règle ACL Web pour empêcher les requêtes d'introspection GraphQL \$1\$1schema vers une API**  
Voici un exemple de règle qui empêche les requêtes d'introspection GraphQL \$1\$1schema vers une API. Tout corps HTTP contenant la chaîne « \$1\$1schema » sera bloqué. Cela serait saisi dans l'**éditeur Rule JSON** lors de la création d'une ACL Web dans la AWS WAF console.  

```
{
  "Name": "BodyRule",
  "Priority": 5,
  "Action": {
    "Block": {}
  },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "BodyRule"
  },
  "Statement": {
    "ByteMatchStatement": {
      "FieldToMatch": {
        "Body": {}
      },
      "PositionalConstraint": "CONTAINS",
      "SearchString": "__schema",
      "TextTransformations": [
        {
          "Type": "NONE",
          "Priority": 0
        }
      ]
    }
  }
}
```
Après avoir créé votre ACL Web à l'aide de l'exemple de règle précédent, vous devez l'associer à votre AppSync API. Vous pouvez effectuer cette étape en AWS CLI exécutant la commande suivante.  

```
aws waf associate-web-acl --web-acl-id waf-web-acl-arn --resource-arn appsync-api-arn
```