

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Dukungan CWT untuk Fungsi CloudFront
<a name="cwt-support-cloudfront-functions"></a>

Bagian ini memberikan detail tentang dukungan untuk CBOR Web Tokens (CWT) di CloudFront Fungsi Anda, yang memungkinkan otentikasi dan otorisasi berbasis token yang aman di Lokasi Edge. CloudFront Dukungan ini disediakan sebagai modul, dapat diakses di CloudFront Fungsi Anda. 

Untuk menggunakan modul ini, buat CloudFront Function menggunakan JavaScript runtime 2.0 dan sertakan pernyataan berikut di baris pertama kode fungsi: 

```
import cf from 'cloudfront';
```

Metode yang terkait dengan modul ini dapat diakses melalui (di mana \$1 adalah wildcard yang mewakili berbagai fungsi yang ada dalam modul):

```
cf.cwt.*
```

Untuk informasi selengkapnya, lihat [JavaScript fitur runtime 2.0 untuk Fungsi CloudFront](functions-javascript-runtime-20.md).

Saat ini, modul hanya mendukung struktur MAC0 dengan algoritma HS256 (HMAC-SHA256) dengan batas 1KB untuk ukuran token maksimum.

## Struktur token
<a name="token-structure"></a>

Bagian ini mencakup struktur token yang diharapkan oleh modul CWT. Modul mengharapkan token ditandai dengan benar dan dapat diidentifikasi (misalnya COSE MAC0). Selain itu, untuk struktur token, modul mengikuti standar yang ditetapkan oleh [CBOR Object Signing and Encryption (COSE) [RFC](https://datatracker.ietf.org/doc/html/rfc8152) 8152].

```
( // CWT Tag (Tag value: 61) --- optional    
    ( // COSE MAC0 Structure Tag (Tag value: 17) --- required        
        [            
            protectedHeaders,            
            unprotectedHeaders,            
            payload,            
            tag,        
        ]    
    )
)
```

**Example : CWT menggunakan struktur COSE MAC0**  

```
61( // CWT tag     
    17( // COSE_MAC0 tag       
        [         
            { // Protected Headers           
                1: 4  // algorithm : HMAC-256-64         
            },         
            { // Unprotected Headers           
                4: h'53796d6d6574726963323536' // kid : Symmetric key id          
            },         
            { // Payload           
                1: "https://iss.example.com", // iss           
                2: "exampleUser", // sub           
                3: "https://aud.example.com", // aud           
                4: 1444064944, // exp           
                5: 1443944944, // nbf           
                6: 1443944944, // iat         
            },         
            h'093101ef6d789200' // tag       
        ]     
    )   
)
```
Tag CWT bersifat opsional saat menghasilkan token. Namun, tag struktur COSE diperlukan.

## metode validateToken ()
<a name="validatetoken-method"></a>

Fungsi menerjemahkan dan memvalidasi token CWT menggunakan kunci yang ditentukan. Jika validasi berhasil, ia mengembalikan token CWT yang diterjemahkan. Jika tidak, itu akan menimbulkan kesalahan. Harap dicatat bahwa fungsi ini tidak melakukan validasi pada set klaim.

### Permintaan
<a name="validatetoken-request"></a>

```
cf.cwt.validateToken(token, handlerContext{key})
```Parameter

**token (wajib)**  
Token yang dikodekan untuk validasi. Ini pasti JavaScript Buffer.

**HandlerContext (Diperlukan)**  
 JavaScript Objek yang menyimpan konteks untuk panggilan ValidateToken. Saat ini, hanya properti kunci yang didukung.

**kunci (Diperlukan)**  
Kunci rahasia untuk perhitungan intisari pesan. Dapat disediakan baik sebagai string atau JavaScript Buffer.

### Respons
<a name="validatetoken-response"></a>

Ketika `validateToken()` metode mengembalikan token berhasil divalidasi, respon dari fungsi adalah `CWTObject` dalam format berikut. Setelah diterjemahkan, semua kunci klaim direpresentasikan sebagai string.

```
CWTObject {    
    protectedHeaders,    
    unprotectedHeaders,    
    payload
}
```

### Contoh - Validasi token dengan anak dikirim sebagai bagian dari token
<a name="validatetoken-example"></a>

Contoh ini menunjukkan validasi token CWT, di mana anak diekstraksi dari header. Anak itu kemudian diteruskan ke CloudFront Fungsi KeyValueStore untuk mengambil kunci rahasia yang digunakan untuk memvalidasi token.

```
import cf from 'cloudfront'

const CwtClaims = {
   iss: 1,
   aud: 3,
   exp: 4
}

async function handler(event) {
    try {
        let request = event.request;
        let encodedToken = request.headers['x-cwt-token'].value;
        let kid = request.headers['x-cwt-kid'].value;
                
        // Retrieve the secret key from the kvs
        let secretKey = await cf.kvs().get(kid);
                 
        // Now you can use the secretKey to decode & validate the token.
        let tokenBuffer = Buffer.from(encodedToken, 'base64url');
                
        let handlerContext = {
           key: secretKey,
        }
                
        try {
            let cwtObj = cf.cwt.validateToken(tokenBuffer, handlerContext);
                        
            // Check if token is expired
            const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds
            if (cwtObj[CwtClaims.exp] && cwtObj[CwtClaims.exp] < currentTime) {
                return {
                    statusCode: 401,
                    statusDescription: 'Token expired'
                };
            }
        } catch (error) {
            return {
               statusCode: 401,
               statusDescription: 'Invalid token'
            };
         }
    } catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
     }
    return request;
}
```

## metode generateToken ()
<a name="generatetoken-method"></a>

Fungsi ini menghasilkan token CWT baru menggunakan pengaturan payload dan konteks yang disediakan.

### Permintaan
<a name="generatetoken-request"></a>

```
cf.cwt.generateToken(generatorContext, payload)
```Parameter

**GeneratorContext (Diperlukan)**  
Ini JavaScript Object yang digunakan sebagai konteks untuk menghasilkan token dan berisi pasangan nilai kunci berikut:    
**CWTTag (Opsional)**  
Nilai ini adalah boolean, yang jika `true` menentukan `cwtTag` harus ditambahkan.  
**CoseTag (Diperlukan)**  
Menentukan jenis tag COSE. Saat ini hanya mendukung`MAC0`.  
**kunci (Diperlukan)**  
Kunci rahasia untuk menghitung intisari pesan. Nilai ini dapat berupa string atau JavaScript `Buffer`.

**payload (Wajib)**  
Payload token untuk pengkodean. Muatan harus dalam `CWTObject` format.

### Respons
<a name="generatetoken-response"></a>

Mengembalikan JavaScript Buffer yang berisi token dikodekan.

**Example : Menghasilkan token CWT**  

```
import cf from 'cloudfront';

const CwtClaims = {
    iss: 1,
    sub: 2,
    exp: 4
};

const CatClaims = {
    catu: 401,
    catnip: 402,
    catm: 403,
    catr: 404
};

const Catu = {
    host: 1,
    path: 2,
    ext: 3
};

const CatuMatchTypes = {
    prefix_match: 1,
    suffix_match: 2,
    exact_match: 3
};

const Catr = {
    renewal_method: 1,
    next_renewal_time: 2,
    max_uses: 3
};

async function handler(event) {
    try {
        const response = {
            statusCode: 200,
            statusDescription: 'OK',
            headers: {}
        };
        
        const commonAccessToken = {
            protected: {
                1: "5",
            },
            unprotected: {},
            payload: {
                [CwtClaims.iss]: "cloudfront-documentation",
                [CwtClaims.sub]: "cwt-support-on-cloudfront-functions",
                [CwtClaims.exp]: 1740000000,
                [CatClaims.catu]: {
                    [Catu.host]: {
                        [CatuMatchTypes.suffix_match]: ".cloudfront.net"
                    },
                    [Catu.path]: {
                        [CatuMatchTypes.prefix_match]: "/media/live-stream/cf-4k/"
                    },
                    [Catu.ext]: {
                        [CatuMatchTypes.exact_match]: [
                            ".m3u8",
                            ".ts",
                            ".mpd"
                        ]
                    }
                },
                [CatClaims.catnip]: [
                    "[IP_ADDRESS]",
                    "[IP_ADDRESS]"
                ],
                [CatClaims.catm]: [
                    "GET",
                    "HEAD"
                ],
                [CatClaims.catr]: {
                    [Catr.renewal_method]: "header_renewal",
                    [Catr.next_renewal_time]: 1750000000,
                    [Catr.max_uses]: 5
                }
            }
        };
        
        if (!request.headers['x-cwt-kid']) {
            throw new Error('Missing x-cwt-kid header');
        }
        
        const kid = request.headers['x-cwt-kid'].value;
        const secretKey = await cf.kvs().get(kid);
        
        if (!secretKey) {
            throw new Error('Secret key not found for provided kid');
        }
        
        try {
            const genContext = {
                cwtTag: true,
                coseTag: "MAC0",
                key: secretKey
            };
            
            const tokenBuffer = cf.cwt.generateToken(commonAccessToken, genContext);
            response.headers['x-generated-cwt-token'] = { value: tokenBuffer.toString('base64url') };
                        
            return response;
        } catch (tokenError) {
            return {
                statusCode: 401,
                statusDescription: 'Could not generate the token'
            };
        }
    } catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
    }
}
```

**Example : Segarkan token berdasarkan beberapa logika**  

```
import cf from 'cloudfront'

const CwtClaims = {
   iss: 1,
   aud: 3,
   exp: 4
}

async function handler(event) {
    try {
        let request = event.request;
        let encodedToken = request.headers['x-cwt-token'].value;
        let kid = request.headers['x-cwt-kid'].value;
        let secretKey = await cf.kvs().get(kid); // Retrieve the secret key from the kvs
                
        // Now you can use the secretKey to decode & validate the token.
        let tokenBuffer = Buffer.from(encodedToken, 'base64url');
                
        let handlerContext = {
           key: secretKey,
        }
                
        try {
            let cwtJSON = cf.cwt.validateToken(tokenBuffer, handlerContext);
                        
            // Check if token is expired
            const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds
            if (cwtJSON[CwtClaims.exp] && cwtJSON[CwtClaims.exp] < currentTime) {
                // We can regnerate the token and add 8 hours to the expiry time
                cwtJSON[CwtClaims.exp] = Math.floor(Date.now() / 1000) + (8 * 60 * 60);
                                
                let genContext = {
                  coseTag: "MAC0",
                  key: secretKey
                }
                                
                let newTokenBuffer = cf.cwt.generateToken(cwtJSON, genContext);
                 request.headers['x-cwt-regenerated-token'] = newTokenBuffer.toString('base64url');
            }
        } catch (error) {
            return {
               statusCode: 401,
               statusDescription: 'Invalid token'
            };
         }
    }
    catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
     }
    return request;
}
```