

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Configurazione dell'autorizzazione e dell'autenticazione per proteggere GraphQL APIs
<a name="security-authz"></a>

AWS AppSync offre i seguenti tipi di autorizzazione per proteggere GraphQL APIs: chiavi API, Lambda, IAM, OpenID Connect e Cognito User Pools. Ciascuna opzione offre un metodo di sicurezza diverso: 

1. **Autorizzazione tramite chiave API**: controlla la limitazione per i non autenticati APIs, fornendo una semplice opzione di sicurezza. 

1. **Autorizzazione Lambda**: abilita la logica di autorizzazione personalizzata, spiegando in dettaglio gli input e gli output delle funzioni. 

1. **Autorizzazione IAM**: utilizza il processo AWS di firma della versione 4 della firma, che consente un controllo granulare degli accessi tramite le policy IAM. 

1. **Autorizzazione OpenID Connect**: si integra con i servizi conformi a OIDC per l'autenticazione degli utenti. 

1. **Pool di utenti Cognito**: implementa il controllo degli accessi basato sul gruppo utilizzando le funzionalità di gestione degli utenti di Cognito. 

## Tipi di autorizzazione
<a name="authorization-types"></a>

Esistono cinque modi per autorizzare le applicazioni a interagire con l'API AWS AppSync GraphQL. È possibile specificare il tipo di autorizzazione da utilizzare specificando uno dei seguenti valori del tipo di autorizzazione nella chiamata AWS AppSync API o CLI:
+   
** `API_KEY` **  
Per usare chiavi API.
+   
** `AWS_LAMBDA` **  
Per usare una AWS Lambda funzione.
+   
** `AWS_IAM` **  
Per l'utilizzo delle autorizzazioni AWS Identity and Access Management ([IAM](https://aws.amazon.com/iam/)).
+   
** `OPENID_CONNECT` **  
Per usare il provider OpenID Connect.
+   
** `AMAZON_COGNITO_USER_POOLS` **  
Per l'utilizzo di un pool di utenti Amazon Cognito.

Questi tipi di autorizzazione di base funzionano per la maggior parte degli sviluppatori. Per casi d'uso più avanzati, puoi aggiungere modalità di autorizzazione aggiuntive tramite la console, la CLI e. AWS CloudFormation Per le modalità di autorizzazione aggiuntive, AWS AppSync fornisce un tipo di autorizzazione che accetta i valori sopra elencati (ovvero`API_KEY`,`AWS_LAMBDA`, `AWS_IAM``OPENID_CONNECT`, e`AMAZON_COGNITO_USER_POOLS`).

Quando si specifica `API_KEY``AWS_LAMBDA`, o `AWS_IAM` come tipo di autorizzazione principale o predefinito, non è possibile specificarli nuovamente come una delle modalità di autorizzazione aggiuntive. Allo stesso modo, non è possibile duplicare `API_KEY` `AWS_LAMBDA` o `AWS_IAM` inserire le modalità di autorizzazione aggiuntive. Puoi utilizzare più pool di utenti Amazon Cognito e provider OpenID Connect. Tuttavia, non puoi utilizzare pool di utenti Amazon Cognito o provider OpenID Connect duplicati tra la modalità di autorizzazione predefinita e nessuna delle modalità di autorizzazione aggiuntive. Puoi specificare diversi client per il tuo pool di utenti Amazon Cognito o il provider OpenID Connect utilizzando l'espressione regolare di configurazione corrispondente.

Quando salvi le modifiche alla configurazione dell'API, AWS AppSync inizia a propagare le modifiche. Fino a quando la modifica alla configurazione non viene propagata, AWS AppSync continua a fornire i contenuti della configurazione precedente. Dopo la propagazione della modifica alla configurazione, inizia AWS AppSync immediatamente a pubblicare i contenuti in base alla nuova configurazione. Durante AWS AppSync la propagazione delle modifiche per un'API, non possiamo determinare se l'API sta servendo i tuoi contenuti sulla base della configurazione precedente o della nuova configurazione.

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

I non autenticati APIs richiedono una limitazione più rigorosa di quelli autenticati. APIs Un modo per controllare il throttling per gli endpoint GraphQL non autenticati è l'uso di chiavi API. Un chiave API è un valore hardcoded nell'applicazione che viene generato dal servizio AWS AppSync quando crei un endpoint GraphQL non autenticato. Puoi ruotare le chiavi API dalla console, dalla CLI o [AWS AppSync dal](https://docs.aws.amazon.com/appsync/latest/APIReference/) riferimento API.

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

1. [Accedi Console di gestione AWS e apri la AppSync console.](https://console.aws.amazon.com/appsync/)

   1. Nella **APIs dashboard**, scegli la tua API GraphQL.

   1. **Nella **barra laterale**, scegli Impostazioni.**

1. In **Modalità di autorizzazione predefinita**, scegli la **chiave API**.

1. Nella tabella delle **chiavi API**, scegli **Aggiungi chiave API**.

   Nella tabella verrà generata una nuova chiave API.

   1. Per eliminare una vecchia chiave API, seleziona la chiave API nella tabella, quindi scegli **Elimina**.

1. Scegli **Save** (Salva) nella parte inferiore della pagina.

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

1. Se non l'hai già fatto, configura il tuo accesso alla AWS CLI. Per ulteriori informazioni, consulta Nozioni di [base sulla configurazione](https://docs.aws.amazon.com//cli/latest/userguide/cli-configure-quickstart.html).

1. Crea un oggetto API GraphQL eseguendo il [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)comando.

   Dovrai digitare due parametri per questo particolare comando:

   1. La `api-id` della tua API GraphQL.

   1. La novità `name` della tua API. Puoi usare lo stesso`name`.

   1. Il`authentication-type`, che sarà`API_KEY`.
**Nota**  
Esistono altri parametri come questi `Region` che devono essere configurati, ma di solito vengono utilizzati per impostazione predefinita i valori di configurazione CLI.

   Un comando di esempio può avere il seguente aspetto:

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

   Verrà restituito un output nella CLI. Ecco un esempio in 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"
       }
   }
   ```

------

Le chiavi API sono configurabili per un massimo di 365 giorni e puoi estendere una data di scadenza esistente per un massimo di altri 365 giorni dalla data di scadenza. Le chiavi API sono consigliate per scopi di sviluppo o casi d'uso in cui è sicuro esporre un'API pubblica.

Nel client la chiave API viene specificata dall'intestazione `x-api-key`.

Ad esempio, se `API_KEY` è `'ABC123'`, puoi inviare una query GraphQL tramite `curl` in questo modo:

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

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

È possibile implementare la propria logica di autorizzazione API utilizzando una AWS Lambda funzione. È possibile utilizzare una funzione Lambda per l'autorizzatore principale o secondario, ma può esserci una sola funzione di autorizzazione Lambda per API. Quando si utilizzano le funzioni Lambda per l'autorizzazione, si applica quanto segue:
+ Se l'API ha le modalità `AWS_LAMBDA` e l'`AWS_IAM`autorizzazione abilitate, la firma SigV4 non può essere utilizzata come token di autorizzazione. `AWS_LAMBDA`
+ Se l'API ha le modalità di `OPENID_CONNECT` autorizzazione `AWS_LAMBDA` e o la modalità di `AMAZON_COGNITO_USER_POOLS` autorizzazione abilitata, il token OIDC non può essere utilizzato come token di autorizzazione. `AWS_LAMBDA` Nota che il token OIDC può essere uno schema Bearer.
+ Una funzione Lambda non deve restituire più di 5 MB di dati contestuali per i resolver.

Ad esempio, se il token di autorizzazione è`'ABC123'`, puoi inviare una query GraphQL tramite curl come segue: 

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

Le funzioni Lambda vengono chiamate prima di ogni query o mutazione. Il valore restituito può essere memorizzato nella cache in base all'ID API e al token di autenticazione. Quando una risposta di autorizzazione Lambda è inferiore a 1.048.576 byte, AWS AppSync memorizza nella cache la risposta per le richieste successive. Se la risposta dell'autorizzazione Lambda è uguale o superiore a 1.048.576 byte, AWS AppSync non memorizza nella cache la risposta e richiama l'autorizzazione Lambda per ogni richiesta in arrivo. Per ottimizzare le prestazioni e ridurre al minimo i costi di chiamata Lambda, consigliamo di limitare le risposte dell'autorizzazione Lambda a 1.048.576 byte. Per impostazione predefinita, la memorizzazione nella cache non è attivata, ma può essere abilitata a livello di API o impostando il valore nel valore restituito da una funzione. `ttlOverride` 

Se lo si desidera, è possibile specificare un'espressione regolare che convalida i token di autorizzazione prima della chiamata della funzione. Queste espressioni regolari vengono utilizzate per verificare che un token di autorizzazione sia del formato corretto prima che la funzione venga chiamata. Qualsiasi richiesta che utilizza un token che non corrisponde a questa espressione regolare verrà rifiutata automaticamente. 

Le funzioni Lambda utilizzate per l'autorizzazione richiedono l'applicazione `appsync.amazonaws.com` di una politica principale per consentire di AWS AppSync chiamarle. Questa azione viene eseguita automaticamente nella AWS AppSync console; la AWS AppSync console *non* rimuove la policy. Per ulteriori informazioni sull'associazione di policy alle funzioni Lambda, [consulta Politiche basate sulle risorse](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html#permissions-resource-serviceinvoke) nella Developer Guide. AWS Lambda 

La funzione Lambda specificata riceverà un evento con la forma seguente:

```
{
    "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`oggetto contiene le intestazioni che sono state inviate nella richiesta dal client dell'applicazione a. AWS AppSync

La funzione di autorizzazione deve restituire almeno `isAuthorized` un valore booleano che indica se la richiesta è autorizzata. AWS AppSync riconosce le seguenti chiavi restituite dalle funzioni di autorizzazione Lambda:

**Nota**  
Il valore per l'operazione `operationName` in the `requestContext` for a WebSocket connect è impostato su "»`DeepDish:Connect`. AWS AppSync 

### Elenco delle funzioni
<a name="aws-lambda-authorization-list"></a>

`isAuthorized`(booleano, obbligatorio)  
Un valore booleano che indica se il valore in `authorizationToken` è autorizzato a effettuare chiamate all'API GraphQL.  
Se questo valore è vero, l'esecuzione dell'API GraphQL continua. Se questo valore è falso, `UnauthorizedException` viene generato un

`deniedFields`(elenco di stringhe, opzionale)  
Un elenco dei quali viene modificato forzatamente in`null`, anche se un valore è stato restituito da un resolver.  
Ogni articolo è un ARN di campo completamente qualificato sotto forma di `arn:aws:appsync:us-east-1:111122223333:apis/GraphQLApiId/types/TypeName/fields/FieldName` o in forma abbreviata di. `TypeName.FieldName` Il modulo ARN completo deve essere usato quando due APIs condividono un autorizzatore di funzione Lambda e potrebbe esserci ambiguità tra i tipi e i campi comuni tra i due. APIs

`resolverContext`(Oggetto JSON, opzionale)  
Un oggetto JSON visibile come `$ctx.identity.resolverContext` nei modelli di resolver. Ad esempio, se un resolver restituisce la seguente struttura:  

```
{
  "isAuthorized":true
  "resolverContext": {
    "banana":"very yellow",
    "apple":"very green" 
  }
}
```
Il valore dei modelli `ctx.identity.resolverContext.apple` di resolver sarà "». `very green` L'`resolverContext`oggetto supporta solo coppie chiave-valore. Le chiavi annidate non sono supportate.  
La dimensione totale di questo oggetto JSON non deve superare i 5 MB.

`ttlOverride`(numero intero, opzionale)  
Il numero di secondi per i quali la risposta deve essere memorizzata nella cache. Se non viene restituito alcun valore, viene utilizzato il valore dell'API. Se è 0, la risposta non viene memorizzata nella cache.

Le autorizzazioni Lambda hanno un timeout standard di 10 secondi, ma possono scadere prima in condizioni di traffico intenso. Ti consigliamo di progettare funzioni da eseguire nel minor tempo possibile (meno di 1 secondo) per scalare le prestazioni dell'API.

Più persone AWS AppSync APIs possono condividere una singola funzione Lambda di autenticazione. L'uso di un sistema di autorizzazione tra account non è consentito.

Quando condividete una funzione di autorizzazione tra più persone APIs, tenete presente che i nomi di campo in formato breve (`typename.fieldname`) possono inavvertitamente nascondere dei campi. Per disambiguare un campo in`deniedFields`, è possibile specificare un campo non ambiguo ARN sotto forma di. `arn:aws:appsync:region:accountId:apis/GraphQLApiId/types/typeName/fields/fieldName` 

Per aggiungere una funzione Lambda come modalità di autorizzazione predefinita in: AWS AppSync

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

1. Accedi alla AWS AppSync console e vai all'API che desideri aggiornare.

1. Vai alla pagina Impostazioni della tua API.

   Cambia l'autorizzazione a livello di API in. **AWS Lambda**

1. Scegli l'ARN Regione AWS e Lambda per autorizzare le chiamate API.
**Nota**  
La politica principale appropriata verrà aggiunta automaticamente, consentendo di AWS AppSync chiamare la funzione Lambda. 

1. Facoltativamente, imposta il TTL di risposta e l'espressione regolare di convalida del token.

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

1. Allega la seguente policy alla funzione Lambda in uso:

   ```
   aws lambda add-permission --function-name "my-function" --statement-id "appsync" --principal appsync.amazonaws.com --action lambda:InvokeFunction --output text 
   ```
**Importante**  
Se desideri che la politica della funzione sia bloccata su una singola API GraphQL, puoi eseguire questo comando:  

   ```
   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. Aggiorna la tua AWS AppSync API per utilizzare la funzione Lambda ARN specificata come autorizzatore:

   ```
   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"
   ```
**Nota**  
Puoi anche includere altre opzioni di configurazione come l'espressione regolare del token. 

------

L'esempio seguente descrive una funzione Lambda che dimostra i vari stati di autenticazione e di errore che una funzione Lambda può avere quando viene utilizzata come meccanismo di autorizzazione: 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 {}
```

### Eludere le limitazioni di autorizzazione dei token SigV4 e OIDC
<a name="aws-lambda-authorization-create-new-auth-token"></a>

I seguenti metodi possono essere utilizzati per aggirare il problema dell'impossibilità di utilizzare la firma SigV4 o il token OIDC come token di autorizzazione Lambda quando sono abilitate determinate modalità di autorizzazione.

Se desideri utilizzare la firma SigV4 come token di autorizzazione Lambda quando le modalità di autorizzazione `AWS_IAM` e le modalità di `AWS_LAMBDA` autorizzazione sono abilitate per l'API, AWS AppSync procedi come segue:
+ Per creare un nuovo token di autorizzazione Lambda, aggiungi and/or prefissi di suffissi casuali alla firma SigV4.
+ Per recuperare la firma SigV4 originale, aggiorna la funzione Lambda rimuovendo i and/or suffissi casuali dei prefissi dal token di autorizzazione Lambda. Quindi, usa la firma SigV4 originale per l'autenticazione.

Se desideri utilizzare il token OIDC come token di autorizzazione Lambda quando la modalità di autorizzazione o le modalità di `OPENID_CONNECT` `AWS_LAMBDA` autorizzazione `AMAZON_COGNITO_USER_POOLS` e sono abilitate per l'API, AWS AppSync procedi come segue:
+ Per creare un nuovo token di autorizzazione Lambda, aggiungi and/or prefissi di suffissi casuali al token OIDC. Il token di autorizzazione Lambda non deve contenere un prefisso dello schema Bearer.
+ Per recuperare il token OIDC originale, aggiorna la funzione Lambda rimuovendo i and/or suffissi dei prefissi casuali dal token di autorizzazione Lambda. Quindi, usa il token OIDC originale per l'autenticazione.

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

Questo tipo di autorizzazione applica il [processo di AWS firma della versione 4 della firma sull'API](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) GraphQL. È possibile associare policy d'accesso Identity and Access Management ([IAM](https://aws.amazon.com/iam/)) a questo tipo di autorizzazione. La tua applicazione può sfruttare questa associazione utilizzando una chiave di accesso (che consiste in un ID chiave di accesso e una chiave di accesso segreta) o utilizzando credenziali temporanee di breve durata fornite da Amazon Cognito Federated Identities.

Se vuoi usare un ruolo che abbia accesso per eseguire tutte le operazioni sui dati:

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

****  

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

------

Puoi trovarla `YourGraphQLApiId` dalla pagina principale dell'elenco delle API nella AppSync console, direttamente sotto il nome della tua API. In alternativa, puoi recuperarlo con l'interfaccia a riga di comando: `aws appsync list-graphql-apis` 

Se vuoi limitare l'accesso solo a determinate operazioni GraphQL, puoi farlo per i campi root `Query`, `Mutation` e `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>"
         ]
     }
   ]
}
```

------

Ad esempio, supponiamo la presenza dello schema seguente e di voler limitare l'accesso in modo da ottenere tutti i post:

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

type Query {
   posts:[Post!]!
}

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

La politica IAM corrispondente per un ruolo (che puoi collegare a un pool di identità di Amazon Cognito, ad esempio) sarebbe simile alla seguente:

------
#### [ 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 autorizzazione
<a name="openid-connect-authorization"></a>

Questo tipo di autorizzazione applica i token [OpenID](https://openid.net/specs/openid-connect-core-1_0.html) connect (OIDC) forniti da un servizio conforme a OIDC. La tua applicazione può usare gli utenti e i privilegi definiti dal provider OIDC per controllare l'accesso.

Un URL dell'emittente è l'unico valore di configurazione necessario da fornire ad AWS AppSync, ad esempio `https://auth.example.com`. Questo URL deve essere indirizzabile tramite HTTPS. AWS AppSync [aggiunge `/.well-known/openid-configuration` all'URL dell'emittente e individua la configurazione OpenID in base alla specifica OpenID Connect `https://auth.example.com/.well-known/openid-configuration` Discovery.](https://openid.net/specs/openid-connect-discovery-1_0.html) Si aspetta di recuperare un [RFC5785](https://tools.ietf.org/html/rfc5785)documento JSON conforme a questo URL. Questo documento JSON deve contenere una `jwks_uri` chiave che rimanda al documento JSON Web Key Set (JWKS) con le chiavi di firma. AWS AppSync richiede che JWKS contenga campi JSON di e. `kty` `kid`

AWS AppSync supporta un'ampia gamma di algoritmi di firma.


| Algoritmi di firma | 
| --- | 
| RS256 | 
| RS384 | 
| RS512 | 
| PS256 | 
| PS384 | 
| PS512 | 
| HS256 | 
| HS384 | 
| HS512 | 
| ES256 | 
| ES384 | 
| ES512 | 

Si consiglia di utilizzare gli algoritmi RSA. I token emessi dal provider devono includere la data e l'ora di emissione del token (`iat`) e possono includere la data e l'ora in cui è stato autenticato (`auth_time`). Puoi specificare valori TTL per la data e l'ora di emissione (`iatTTL`) e di autenticazione (`authTTL`) nella configurazione OpenID Connect per un'ulteriore convalida. Se il provider autorizza più applicazioni, puoi anche immettere un'espressione regolare (`clientId`), usata per l'autorizzazione tramite ID client. Quando `clientId` è presente nella configurazione di OpenID Connect, AWS AppSync convalida l'affermazione richiedendo che corrisponda `clientId` all'`azp`affermazione `aud` o nel token.

Per convalidare più client, IDs usa l'operatore pipeline («\$1») che è un «o» nell'espressione regolare. Ad esempio, se l'applicazione OIDC ha quattro client con client IDs come 0A1S2D, 1F4G9H, 1J6L4B, 6 GS5 MG, per convalidare solo i primi tre client IDs, è necessario inserire GS5 1F4G9H\$11J6L4B\$16 MG nel campo ID client.

Se un'API è configurata con più tipi di autorizzazione, AWS AppSync convalida l'emittente (iss claim) presente nel token JWT dalle intestazioni della richiesta confrontandolo con l'URL dell'emittente specificato nella configurazione dell'API. Tuttavia, quando un'API è configurata solo con OPENID\$1CONNECT autorizzazione, AWS AppSync salta questa fase di convalida dell'URL dell'emittente.

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

Questo tipo di autorizzazione applica i token OIDC forniti dai pool di utenti di Amazon Cognito. L'applicazione può sfruttare gli utenti e i gruppi presenti nei pool di utenti e nei pool di utenti di un altro AWS account e associarli ai campi GraphQL per controllare l'accesso.

Quando usi i pool di utenti di Amazon Cognito, puoi creare gruppi a cui appartengono gli utenti. Queste informazioni sono codificate in un token JWT a cui l'applicazione invia AWS AppSync in un'intestazione di autorizzazione durante l'invio di operazioni GraphQL. Puoi usare direttive GraphQL nello schema per controllare quali gruppi possono richiamare resolver specifici in un campo, per offrire un accesso più controllato ai tuoi clienti.

Ad esempio, supponiamo lo schema GraphQL seguente:

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

type Query {
   posts:[Post!]!
}

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

Se hai due gruppi nei pool di utenti di Amazon Cognito, blogger e lettori, e desideri limitare i lettori in modo che non possano aggiungere nuove voci, lo schema dovrebbe essere simile al seguente:

```
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"])
}
...
```

Tieni presente che puoi omettere la `@aws_auth` direttiva se desideri impostare di default una grant-or-deny strategia di accesso specifica. È possibile specificare la grant-or-deny strategia nella configurazione del pool di utenti quando si crea l'API GraphQL tramite la console o tramite il seguente comando CLI:

```
$ 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"}'
```

## Utilizzo di modalità di autorizzazione aggiuntive
<a name="using-additional-authorization-modes"></a>

Quando aggiungi modalità di autorizzazione aggiuntive, puoi configurare direttamente l'impostazione di autorizzazione a livello di API AWS AppSync GraphQL (ovvero, il `authenticationType` campo che puoi configurare direttamente sull'`GraphqlApi`oggetto) e funge da impostazione predefinita sullo schema. Ciò significa che qualsiasi tipo che non dispone di una direttiva specifica deve superare l'impostazione di autorizzazione a livello di API.

A livello di schema, puoi specificare ulteriori modalità di autorizzazione utilizzando le direttive sullo schema. Puoi specificare le modalità di autorizzazione su singoli campi nello schema. Ad esempio, per l’autorizzazione `API_KEY` puoi utilizzare `@aws_api_key` nelle definizioni/campi del tipo di oggetto dello schema. Le direttive seguenti sono supportate nei campi dello schema e nelle definizioni del tipo di oggetto:
+  `@aws_api_key` - Per specificare che il campo è autorizzato `API_KEY`.
+  `@aws_iam` - Per specificare che il campo è autorizzato `AWS_IAM`.
+  `@aws_oidc` - Per specificare che il campo è autorizzato `OPENID_CONNECT`.
+  `@aws_cognito_user_pools` - Per specificare che il campo è autorizzato `AMAZON_COGNITO_USER_POOLS`.
+  `@aws_lambda` - Per specificare che il campo è autorizzato `AWS_LAMBDA`.

Non puoi utilizzare la direttiva `@aws_auth` insieme a modalità di autorizzazione aggiuntive. `@aws_auth` funziona solo nel contesto dell'autorizzazione `AMAZON_COGNITO_USER_POOLS` senza modalità di autorizzazione aggiuntive. Tuttavia, puoi utilizzare la direttiva `@aws_cognito_user_pools` al posto della direttiva `@aws_auth`, utilizzando gli stessi argomenti. La differenza principale tra le due è che è possibile specificare `@aws_cognito_user_pools` in qualsiasi definizione di campo e tipo di oggetto.

Per comprendere come funzionano le modalità di autorizzazione aggiuntive e come possono essere specificate in uno schema, esaminiamo lo schema seguente:

```
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!
}
...
```

Per questo schema, supponiamo che `AWS_IAM` sia il tipo di autorizzazione predefinito sull'API AWS AppSync GraphQL. Ciò significa che i campi che non dispongono di una direttiva sono protetti utilizzando `AWS_IAM`. Ad esempio, questo è il caso del campo `getPost` sul tipo `Query`. Le direttive dello schema consentono di utilizzare più di una modalità di autorizzazione. Ad esempio, è possibile `API_KEY` configurarla come modalità di autorizzazione aggiuntiva sull'API AWS AppSync GraphQL e contrassegnare un campo utilizzando la `@aws_api_key` direttiva (ad esempio, `getAllPosts` in questo esempio). Le direttive funzionano a livello di campo, quindi è necessario concedere a `API_KEY` l'accesso anche al tipo `Post`. Puoi eseguire questa operazione contrassegnando ogni campo nel tipo `Post` con una direttiva oppure contrassegnando il tipo `Post` con la direttiva `@aws_api_key`.

Per limitare ulteriormente l'accesso ai campi nel tipo `Post`, puoi utilizzare le direttive sui singoli campi nel tipo `Post` come mostrato di seguito.

Ad esempio, puoi aggiungere un campo `restrictedContent` al tipo `Post` e limitare l'accesso utilizzando la direttiva `@aws_iam`. Le richieste autenticate `AWS_IAM` possono accedere a `restrictedContent`, mentre le richieste `API_KEY` non possono accedervi.

```
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
}
...
```

## Controllo granulare degli accessi
<a name="fine-grained-access-control"></a>

Le informazioni precedenti descrivono come limitare o concedere l'accesso a determinati campi GraphQL. Se vuoi impostare controlli degli accessi sui dati in base a determinate condizioni (ad esempio in base all'utente che effettua una chiamata e se è il proprietario dei dati), puoi usare i modelli di mappatura nei resolver. Puoi anche eseguire una logica di business più complessa, che descriveremo in [Applicazione di filtri alle informazioni](#aws-appsync-filtering-information).

Questa sezione mostra come impostare i controlli di accesso sui dati utilizzando un modello di mappatura del resolver DynamoDB.

Prima di procedere oltre, se non hai dimestichezza con i modelli di mappatura di Resolver AWS AppSync, puoi consultare il riferimento al modello di mappatura [Resolver e il riferimento al modello di mappatura](resolver-mapping-template-reference.md#aws-appsync-resolver-mapping-template-reference) [Resolver](resolver-mapping-template-reference-dynamodb.md#aws-appsync-resolver-mapping-template-reference-dynamodb) per DynamoDB.

Nell'esempio seguente che utilizza DynamoDB, supponiamo di utilizzare lo schema di post del blog precedente e che solo gli utenti che hanno creato un post siano autorizzati a modificarlo. Il processo di valutazione ha lo scopo di permettere all'utente di ottenere le credenziali nell'applicazione, ad esempio usando pool di utenti Amazon Cognito, e quindi passare queste credenziali come parte di un'operazione GraphQL. Il modello di mappatura sostituisce quindi un valore delle credenziali, ad esempio il nome utente, in un'istruzione condizionale, che viene quindi confrontata con un valore nel database.

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


Per aggiungere questa funzionalità, aggiungi un campo GraphQL `editPost` in questo modo:

```
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!
}
...
```

Il modello di mappatura dei resolver per `editPost` (mostrato in un esempio alla fine di questa sezione) deve eseguire un controllo logico sul datastore per permettere solo all'utente che ha creato un post di modificarlo. Poiché si tratta di un'operazione di modifica, corrisponde a un'operazione `UpdateItem` in DynamoDB. Puoi eseguire un controllo condizionale prima di eseguire questa operazione, usando il contesto passato per la convalida dell'identità dell'utente. Questo viene archiviato in un oggetto `Identity` che ha i valori seguenti:

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

Per utilizzare questo oggetto in una chiamata `UpdateItem` DynamoDB, è necessario memorizzare le informazioni sull'identità dell'utente nella tabella per il confronto. Prima di tutto, la mutazione `addPost` deve archiviare l'autore. In secondo luogo, la mutazione `editPost` deve eseguire il controllo condizionale prima dell'aggiornamento.

Ecco un esempio di codice del resolver `addPost` che memorizza l'identità dell'utente come colonna: `Author`

```
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;
```

Nota che l'attributo `Author` viene popolato dall'oggetto `Identity`, che proviene dall'applicazione.

Infine, ecco un esempio del codice resolver for`editPost`, che aggiorna il contenuto del post sul blog solo se la richiesta proviene dall'utente che ha creato il post:

```
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;
```

Questo esempio utilizza un `PutItem` che sovrascrive tutti i valori anziché uno`UpdateItem`, ma lo stesso concetto si applica al `condition` blocco di istruzioni.

## Filtraggio delle informazioni
<a name="aws-appsync-filtering-information"></a>

Esistono alcuni casi in cui non puoi controllare la risposta proveniente dall'origine dati, ma non vuoi inviare informazioni inutili ai client in un'operazione di scrittura o lettura riuscita nell'origine dati. In questi casi, puoi filtrare le informazioni usando un modello di mappatura della risposta.

Ad esempio, supponiamo di non avere un indice appropriato nella tabella DynamoDB del post sul blog (ad esempio un indice su). `Author` Puoi usare il seguente resolver:

```
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;
}
```

Il gestore della richiesta recupera l'elemento anche se il chiamante non è l'autore che ha creato il post. Per evitare che ciò restituisca tutti i dati, il gestore della risposta verifica che il chiamante corrisponda all'autore dell'elemento. Se il chiamante non corrisponde a questo controllo, viene restituita solo una risposta Null.

## Accesso origine dati
<a name="data-source-access"></a>

AWS AppSync comunica con le fonti di dati utilizzando i ruoli e le policy di accesso di Identity and Access Management ([IAM](https://aws.amazon.com/iam/)). Se si utilizza un ruolo esistente, è necessario aggiungere una politica di fiducia per AWS AppSync assumere il ruolo. La relazione di attendibilità apparirà come segue:

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

****  

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

------

È importante ridurre l'ambito della policy di accesso sul ruolo per avere solo le autorizzazioni per agire sul set minimo di risorse necessarie. Quando si utilizza la AppSync console per creare un'origine dati e creare un ruolo, questa operazione viene eseguita automaticamente. Tuttavia, quando si utilizza un modello di esempio integrato dalla console IAM per creare un ruolo al di fuori della console AWS AppSync, non sarà automaticamente ridotto l'ambito dei permessi su una risorsa; si consiglia di eseguire questa azione prima di spostare l'applicazione in produzione.

# Casi d'uso del controllo degli accessi per proteggere richieste e risposte
<a name="security-authorization-use-cases"></a>

Nella sezione [Sicurezza](security-authz.md#aws-appsync-security) sono stati illustrati i diversi metodi di autorizzazione per proteggere l'API ed è stato presentato il meccanismo di autorizzazione granulare per comprendere i concetti e il flusso. Poiché AWS AppSync consente di eseguire operazioni logiche complete sui dati tramite l'uso di [modelli GraphQL Resolver Mapping](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview), è possibile proteggere i dati in lettura o scrittura in modo molto flessibile utilizzando una combinazione di identità utente, condizionali e data injection.

[Se non hai dimestichezza con la modifica dei AWS AppSync Resolver, consulta la guida alla programmazione.](resolver-mapping-template-reference-programming-guide.md#aws-appsync-resolver-mapping-template-reference-programming-guide)

## Panoramica di
<a name="overview"></a>

La concessione dell'accesso ai dati in un sistema viene tradizionalmente effettuata tramite una [matrice di controllo degli accessi](https://en.wikipedia.org/wiki/Access_Control_Matrix) in cui l'intersezione di una riga (risorsa) e una colonna (utente/ruolo) rappresenta le autorizzazioni concesse.

AWS AppSync utilizza le risorse del proprio account e inserisce le informazioni sull'identità (utente/ruolo) nella richiesta e risposta GraphQL come [oggetto di contesto](resolver-context-reference.md#aws-appsync-resolver-mapping-template-context-reference), che può essere utilizzato nel resolver. Ciò significa che le autorizzazioni possono essere concesse in modo appropriato per le operazioni di lettura o scrittura in base alla logica del resolver. Se questa logica è a livello di risorsa, ad esempio solo determinati utenti o gruppi denominati possono accedere read/write a una riga specifica del database, è necessario archiviare tali «metadati di autorizzazione». AWS AppSync non memorizza alcun dato, quindi è necessario archiviare questi metadati di autorizzazione con le risorse in modo da poter calcolare le autorizzazioni. I metadati di autorizzazione sono in genere un attributo (colonna) in una tabella DynamoDB, ad esempio un **proprietario** o un elenco di utenti/gruppi. Potrebbero ad esempio esserci gli attributi **Readers** e **Writers**.

Da un punto di vista generale, ciò significa che se stai leggendo una singola voce da un'origine dati, esegui un'istruzione `#if () ... #end` condizionale nel modello di risposta dopo che il resolver ha letto dall'origine dati. Il controllo usa in genere i valori di utenti o gruppi in `$context.identity` per i controlli di appartenenza in base ai metadati di autorizzazione restituiti da un'operazione di lettura. Per più record, ad esempio gli elenchi restituiti da una tabella `Scan` o `Query`, puoi inviare il controllo della condizione come parte dell'operazione all'origine dati usando valori di utenti o gruppi simili.

Analogamente, quando scrivi dati applichi un'istruzione condizionale all'operazione (ad esempio `PutItem` o `UpdateItem`) per verificare se l'utente o il gruppo che esegue la mutazione dispone di autorizzazione. Molto spesso l'istruzione condizionale usa un valore in `$context.identity` per eseguire il confronto in base ai metadati di autorizzazione nella risorsa. Per entrambi i modelli di richiesta e di risposta è anche possibile usare intestazioni personalizzate provenienti dai client per eseguire i controlli di convalida.

## Lettura dei dati
<a name="reading-data"></a>

Come illustrato in precedenza, i metadati di autorizzazione per eseguire un controllo devono essere archiviati con una risorsa o passati nella richiesta GraphQL (identità, intestazione e così via). Per illustrare questo concetto, supponi di avere la tabella DynamoDB seguente:

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


La chiave primaria è `id` e i dati a cui accedere corrispondono a `Data`. Le altre colonne sono esempi di controlli che è possibile eseguire per l'autorizzazione. `Owner`richiederebbe un `String` po' di tempo `PeopleCanAccess` e `GroupsCanAccess` sarebbe `String Sets` come indicato nel [riferimento del modello di mappatura Resolver](resolver-mapping-template-reference-dynamodb.md#aws-appsync-resolver-mapping-template-reference-dynamodb) per DynamoDB.

Nella [panoramica sui modelli di mappatura dei resolver](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview) il diagramma mostra che il modello di risposta contiene non solo l'oggetto context, ma anche i risultati dall'origine dati. Per le query GraphQL di singole voci, è possibile usare il modello di risposta per controllare se l'utente è autorizzato a visualizzare i risultati oppure restituire un messaggio di errore di autorizzazione. In questo caso si parla talvolta di "filtro di autorizzazione". Per le query GraphQL che restituiscono elenchi, usando un elemento Scan o Query, è preferibile eseguire il controllo nel modello di richiesta e restituire i dati solo se la condizione di autorizzazione viene soddisfatta. L'implementazione è quindi la seguente:

1. GetItem - controllo delle autorizzazioni per i singoli record. Eseguito usando istruzioni `#if() ... #end`.

1. Operazioni Scan/Query: il controllo di autorizzazione è un'istruzione `"filter":{"expression":...}`. I controlli comuni riguardano l'uguaglianza (`attribute = :input`) o la verifica della presenza di un valore in un elenco (`contains(attribute, :input)`).

Nel punto 2 l'elemento `attribute` in entrambe le istruzioni rappresenta il nome di colonna del record in una tabella, come `Owner` nell'esempio precedente. Puoi impostare un alias con un segno `#` e usare `"expressionNames":{...}`, ma non è obbligatorio. L'elemento `:input` è un riferimento al valore che stai confrontando con l'attributo di database, che definirai in `"expressionValues":{...}`. Gli esempi sono disponibili di seguito.

### Caso d'uso: il proprietario può leggere
<a name="use-case-owner-can-read"></a>

Usando la tabella precedente, se desideri restituire i dati solo se `Owner == Nadia` per una singola operazione di lettura (`GetItem`), il modello sarà analogo al seguente:

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

Ci sono alcuni aspetti da sottolineare che valgono anche per le sezioni successive. Innanzitutto, il controllo utilizza `$context.identity.username` il nome di registrazione intuitivo dell'utente se vengono utilizzati i pool di utenti di Amazon Cognito e l'identità dell'utente se viene utilizzato IAM (incluse le identità federate di Amazon Cognito). Esistono altri valori da memorizzare per un proprietario, come il valore univoco «Amazon Cognito identity», utile per federare gli accessi da più sedi, e dovresti esaminare le opzioni disponibili nel [Resolver Mapping Template Context Reference](resolver-context-reference.md#aws-appsync-resolver-mapping-template-context-reference).

In secondo luogo, il controllo else condizionale che risponde con `$util.unauthorized()` è completamente facoltativo, ma consigliato come best practice nella progettazione dell'API GraphQL.

### Caso d'uso: accesso specifico per codice rigido
<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
```

### Caso d'uso: filtraggio di un elenco di risultati
<a name="use-case-filtering-a-list-of-results"></a>

Nell'esempio precedente è stato eseguito un controllo direttamente su `$context.result`, in quanto è stata restituita una singola voce, tuttavia alcune operazioni come una scansione restituiscono più voci in `$context.result.items`, quindi è necessario applicare il filtro di autorizzazione per restituire solo i risultati che l'utente può vedere. Supponiamo che questa volta `Owner` nel campo sia impostato l'IdentityID di Amazon Cognito nel record, quindi puoi utilizzare il seguente modello di mappatura delle risposte per filtrare in modo da mostrare solo i record di proprietà dell'utente:

```
#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)
```

### Caso d'uso: più persone possono leggere
<a name="use-case-multiple-people-can-read"></a>

Un'altra opzione di autorizzazione comune consiste nel permettere a un gruppo di persone di leggere i dati. Nell'esempio seguente `"filter":{"expression":...}` restituisce i valori di una scansione di tabella solo se l'utente che esegue la query GraphQL è incluso nel set `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)
        }
    }
}
```

### Caso d'uso: il gruppo può leggere
<a name="use-case-group-can-read"></a>

Analogamente all'ultimo caso d'uso, è possibile che solo le persone in uno o più gruppi abbiano i diritti per leggere determinate voci in un database. L'uso dell'operazione `"expression": "contains()"` è analogo, tuttavia nell'appartenenza a un set è necessario tenere conto dell'operatore logico OR che permette di includere tutti i gruppi di cui un utente potrebbe far parte. In questo caso, creiamo l'istruzione `$expression` seguente per ogni gruppo a cui appartiene l'utente e la passiamo al filtro:

```
#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)
    }
}
```

## Scrittura di dati
<a name="writing-data"></a>

La scrittura di dati nelle mutazioni è sempre controllata nel modello di mappatura della richiesta. Nel caso delle origini dati DynamoDB, la chiave consiste nell'usare un elemento `"condition":{"expression"...}"` appropriato che esegue la convalida in base ai metadati di autorizzazione nella tabella. In [Sicurezza](security-authz.md#aws-appsync-security), abbiamo fornito un esempio che è possibile utilizzare per controllare il campo `Author` in una tabella. In questa sezione vengono esaminati altri casi d'uso.

### Caso d'uso: più proprietari
<a name="use-case-multiple-owners"></a>

Usando il diagramma della tabella di esempio precedente, presupponi l'elenco `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)
        }
    }
}
```

### Caso d'uso: il gruppo può creare un nuovo record
<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)
    }
}
```

### Caso d'uso: il gruppo può aggiornare il record esistente
<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)
    }
}
```

## Record pubblici e privati
<a name="public-and-private-records"></a>

Con i filtri condizionali, è anche possibile scegliere di contrassegnare i dati come privati, pubblici o con altri valori booleani. Questa impostazione può quindi essere integrata in un filtro di autorizzazione all'interno del modello di risposta. Usando questo controllo, è possibile nascondere temporaneamente i dati o rimuoverli dalla visualizzazione senza tentare di controllare l'appartenenza a un gruppo.

Supponi, ad esempio, di aggiungere un attributo in ogni voce della tabella DynamoDB chiamata `public` con un valore `yes` o `no`. Il modello di risposta seguente può essere usato in una chiamata `GetItem` per visualizzare i dati solo nel caso in cui l'utente si trova in un gruppo che ha accesso E se i dati sono contrassegnati come pubblici:

```
#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
```

Nel codice precedente è anche possibile usare un operatore OR logico (`||`) per permettere agli utenti la lettura se dispongono dell'autorizzazione per un record o se il record è pubblico:

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

In generale, gli operatori standard `==`, `!=`, `&&` e `||`, sono utili per i controlli di autorizzazione.

## Dati in tempo reale
<a name="security-real-time-data"></a>

È possibile applicare controlli di accesso granulari alle sottoscrizioni GraphQL nel momento in cui un client esegue una sottoscrizione, usando le stesse tecniche descritte in precedenza in questa documentazione. È possibile collegare un resolver al campo della sottoscrizione e quindi è possibile eseguire query sui dati di un'origine dati e applicare la logica condizionale nel modello di mappatura della richiesta o della risposta. Puoi anche restituire dati aggiuntivi al client, ad esempio i risultati iniziali di una sottoscrizione, a condizione che la struttura dei dati corrisponda a quella del tipo restituito nella sottoscrizione GraphQL.

### Caso d'uso: l'utente può iscriversi solo a conversazioni specifiche
<a name="use-case-user-can-subscribe-to-specific-conversations-only"></a>

Un caso d'uso comune per i dati in tempo reale con le sottoscrizioni GraphQL consiste nella creazione di un'applicazione di messaggistica o di chat privata. Quando crei un'applicazione di chat con più utenti, le conversazioni possono avvenire tra due persone o tra più persone. Gli utenti possono essere raggruppati in "stanze", private o pubbliche. In questo caso, è necessario autorizzare un utente a eseguire solo la sottoscrizione di una conversazione (con una sola persona o con un gruppo) per la quale gli è stato concesso l'accesso. A scopo illustrativo, nell'esempio seguente è rappresentato un caso d'uso semplice di un utente che invia un messaggio privato a un altro utente. La configurazione ha due tabelle Amazon DynamoDB:
+ Tabella Messages: (chiave primaria) `toUser`, (chiave di ordinamento) `id` 
+ Tabella Permissions: (chiave primaria) `username` 

La tabella Messages archivia i messaggi effettivi inviati tramite una mutazione GraphQL. La tabella Permissions viene controllata dalla sottoscrizione GraphQL per verificare le autorizzazioni al momento della connessione client. L'esempio seguente presuppone che si stia usando lo schema GraphQL illustrato di seguito:

```
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
}
```

Alcune delle operazioni standard, ad esempio, non sono illustrate di seguito per illustrare i resolver in abbonamento, ma sono implementazioni standard dei resolver DynamoDB. `createUserPermissions()` Vengono invece analizzati i flussi di autorizzazione della sottoscrizione con i resolver. Per inviare un messaggio da un utente a un altro, collega un resolver al campo `sendMessage()` e seleziona l'origine dati della tabella **Messages** con il modello di richiesta seguente:

```
{
    "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),
    }
}
```

In questo esempio viene utilizzato `$context.identity.username`. Ciò restituisce le informazioni sugli utenti AWS Identity and Access Management o per gli utenti di Amazon Cognito. Il modello di risposta è un passthrough semplice di `$util.toJson($ctx.result)`. Salva e torna alla pagina dello schema. Collega quindi un resolver alla sottoscrizione `newMessage()`, usando la tabella **Permissions** come origine dati e il modello di mappatura della richiesta seguente:

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

Usa quindi il modello di mappatura della risposta seguente per eseguire i controlli di autorizzazione con i dati della tabella **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
```

In questo caso, esegui tre controlli di autorizzazione. Il primo garantisce che venga restituito un risultato. Il secondo garantisce che l'utente non esegua la sottoscrizione di messaggi destinati a un'altra persona. Il terzo assicura che l'utente sia autorizzato a sottoscrivere qualsiasi campo, controllando un attributo DynamoDB `isAuthorizedForSubscriptions` di stored as a. `BOOL`

Per testare le cose, puoi accedere alla AWS AppSync console utilizzando i pool di utenti di Amazon Cognito e un utente chiamato «Nadia», quindi eseguire il seguente abbonamento GraphQL:

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

Se nella tabella **Autorizzazioni** c'è un record per l'attributo chiave `username` corrispondente a `Nadia` con valore di `isAuthorizedForSubscriptions` impostato su `true`, l'operazione avrà esito positivo. Se provi a usare un valore di `username` diverso nella query `newMessage()` precedente, verrà restituito un errore.

# Utilizzato AWS WAF per proteggere il tuo AWS AppSync APIs
<a name="WAF-Integration"></a>

AWS WAF è un firewall per applicazioni Web che aiuta a proteggere le applicazioni Web e APIs dagli attacchi. Consente di configurare una serie di regole, denominate elenco di controllo degli accessi Web (Web ACL), che consentono, bloccano o monitorano (contano) le richieste Web in base a regole e condizioni di sicurezza Web personalizzabili definite dall'utente. Quando integri la tua AWS AppSync API con AWS WAF, ottieni maggiore controllo e visibilità sul traffico HTTP accettato dalla tua API. Per ulteriori informazioni AWS WAF, consulta [How AWS WAF Works](https://docs.aws.amazon.com/waf/latest/developerguide/how-aws-waf-works.html) nella AWS WAF Developer Guide. 

Puoi utilizzarla AWS WAF per proteggere la tua AppSync API da exploit web comuni, come attacchi SQL injection e cross-site scripting (XSS). Questi potrebbero influire sulla disponibilità e sulle prestazioni delle API, compromettere la sicurezza o consumare risorse eccessive. Ad esempio, puoi creare regole per consentire o bloccare richieste da intervalli di indirizzi IP specificati, richieste da blocchi CIDR, richieste provenienti da un paese o una regione specifici, richieste che contengono codice SQL dannoso o richieste contenenti script dannoso.

Puoi anche creare regole che corrispondono a una stringa specificata o un modello di espressione regolare in intestazioni HTTP, metodo, stringa di query, URI e il corpo della richiesta (entro i primi 8 KB). Inoltre, puoi creare regole per bloccare attacchi da utenti-agenti, bad bot e scraper di contenuti. Ad esempio, puoi usare le regole basate sulla frequenza per specificare il numero di richieste Web consentite da ogni IP client in un periodo di 5 minuti, costantemente aggiornato, finale.

[Per ulteriori informazioni sui tipi di regole supportate e sulle AWS WAF funzionalità aggiuntive, consulta la [AWS WAF Developer Guide e l'API Reference](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html).AWS WAF](https://docs.aws.amazon.com/waf/latest/APIReference/API_Types_AWS_WAFV2.html)

**Importante**  
AWS WAF è la tua prima linea di difesa contro gli exploit web. Quando AWS WAF è abilitata su un'API, AWS WAF le regole vengono valutate prima di altre funzionalità di controllo degli accessi, come l'autorizzazione delle chiavi API, le policy IAM, i token OIDC e i pool di utenti di Amazon Cognito. 

## Integra un'API con AppSync AWS WAF
<a name="integrate-API-with-WAF"></a>

Puoi integrare un'API Appsync AWS WAF utilizzando il Console di gestione AWS AWS CLI AWS CloudFormation, o qualsiasi altro client compatibile.

**Per integrare un' AWS AppSync API con AWS WAF**

1. Crea un ACL AWS WAF web. Per i passaggi dettagliati sull'utilizzo della [AWS WAF console](https://console.aws.amazon.com/waf/), consulta [Creazione di un ACL Web](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-creating.html).

1. Definisci le regole per l'ACL web. Una o più regole vengono definite nel processo di creazione dell'ACL Web. Per informazioni su come strutturare le regole, consulta [AWS WAF regole](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rules.html). Per esempi di regole utili che puoi definire per la tua AWS AppSync API, consulta[Creazione di regole per un ACL web](#Creating-web-acl-rules).

1. Associa l'ACL web a un' AWS AppSync API. È possibile eseguire questo passaggio nella [AWS WAF console](https://console.aws.amazon.com/wafv2/) o nella [AppSync console](https://console.aws.amazon.com/appsync/). 
   + Per associare l'ACL Web a un' AWS AppSync API nella AWS WAF console, segui le istruzioni per [associare o dissociare un ACL Web a una AWS risorsa nella Developer Guide](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-associating-aws-resource.html). AWS WAF 
   + Per associare l'ACL Web a un'API nella console AWS AppSync AWS AppSync 

     1. Accedi Console di gestione AWS e apri la [AppSync console](https://console.aws.amazon.com/appsync/).

     1. Scegli l'API che desideri associare a un ACL web.

     1. Nel pannello di navigazione scegli **Impostazioni**.

     1. Nella sezione **Web Application Firewall**, attiva **Abilita. AWS WAF**

     1. Nell'elenco a discesa **Web ACL**, scegli il nome dell'ACL Web da associare alla tua API.

     1. Scegli **Salva** per associare l'ACL web alla tua API.

   

**Nota**  
Dopo aver creato un ACL Web nella AWS WAF Console, possono essere necessari alcuni minuti prima che il nuovo ACL Web sia disponibile. Se non vedi un ACL web appena creato nel menu **Web Application Firewall**, attendi qualche minuto e riprova i passaggi per associare l'ACL web alla tua API.

**Nota**  
AWS WAF l'integrazione supporta l'`Subscription registration message`evento solo per gli endpoint in tempo reale. AWS AppSync risponderà con un messaggio di errore anziché con un `start_ack` messaggio per qualsiasi persona `Subscription registration message` bloccata da AWS WAF. 

Dopo aver associato un ACL Web a un' AWS AppSync API, gestirai l'ACL Web utilizzando. AWS WAF APIs Non è necessario associare nuovamente l'ACL Web all'API, a meno che non si desideri associare l' AWS AppSync AWS AppSync API a un ACL Web diverso.

## Creazione di regole per un ACL web
<a name="Creating-web-acl-rules"></a>

Le regole definiscono come esaminare le richieste Web e cosa fare quando una richiesta Web soddisfa i criteri di ispezione. Le regole non esistono di AWS WAF per sé. È possibile accedere a una regola per nome in un gruppo di regole o nell'ACL Web in cui è definita. Per ulteriori informazioni, consulta [AWS WAF le regole](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rules.html). Gli esempi seguenti mostrano come definire e associare regole utili per proteggere un' AppSync API.

**Example regola web ACL per limitare la dimensione del corpo della richiesta**  
Di seguito è riportato un esempio di regola che limita la dimensione del corpo delle richieste. Questo verrebbe inserito nell'**editor Rule JSON** durante la creazione di un ACL web nella 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
        }
}
```
Dopo aver creato l'ACL Web utilizzando la regola di esempio precedente, è necessario associarlo all'API. AppSync In alternativa all'utilizzo di Console di gestione AWS, è possibile eseguire questo passaggio AWS CLI eseguendo il comando seguente.  

```
aws waf associate-web-acl --web-acl-id waf-web-acl-arn --resource-arn appsync-api-arn
```
La propagazione delle modifiche può richiedere alcuni minuti, ma dopo aver eseguito questo comando, le richieste che contengono un corpo di dimensioni superiori a 1024 byte verranno rifiutate da. AWS AppSync  
Dopo aver creato un nuovo ACL Web nella AWS WAF Console, possono essere necessari alcuni minuti prima che l'ACL Web sia disponibile per l'associazione a un'API. Se esegui il comando CLI e ricevi un `WAFUnavailableEntityException` errore, attendi qualche minuto e riprova a eseguire il comando.

**Example regola web ACL per limitare le richieste provenienti da un singolo indirizzo IP**  
Di seguito è riportato un esempio di regola che limita un' AppSync API a 100 richieste da un singolo indirizzo IP. Questo verrebbe inserito nell'**editor Rule JSON** durante la creazione di un ACL Web con una regola basata sulla velocità nella Console. AWS WAF   

```
{
  "Name": "Throttle",
  "Priority": 0,
  "Action": {
    "Block": {}
  },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "Throttle"
  },
  "Statement": {
    "RateBasedStatement": {
      "Limit": 100,
      "AggregateKeyType": "IP"
    }
  }
}
```
Dopo aver creato l'ACL Web utilizzando la regola di esempio precedente, è necessario associarlo alla propria API. AppSync È possibile eseguire questo passaggio AWS CLI eseguendo il comando seguente.  

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

**Example regola web ACL per impedire le query di introspezione GraphQL \$1\$1schema su un'API**  
Di seguito è riportato un esempio di regola che impedisce le query di introspezione GraphQL \$1\$1schema su un'API. Qualsiasi corpo HTTP che include la stringa «\$1\$1schema» verrà bloccato. Questo verrebbe inserito nell'**editor Rule JSON** durante la creazione di un ACL web nella console. AWS WAF   

```
{
  "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
        }
      ]
    }
  }
}
```
Dopo aver creato l'ACL Web utilizzando la regola di esempio precedente, è necessario associarlo all'API. AppSync È possibile eseguire questo passaggio AWS CLI eseguendo il comando seguente.  

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