

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 自訂身分驗證和授權
<a name="custom-authentication"></a>

 AWS IoT Core 可讓您定義自訂授權方，以便管理自己的用戶端身分驗證和授權。當您需要使用 AWS IoT Core 非原生支援的身分驗證機制時，這會很有用。(如需原生支援機制的詳細資訊，請參閱 [用戶端身分驗證](client-authentication.md))。  

 例如，如果您要將 欄位中的現有裝置遷移至 ， AWS IoT Core 而這些裝置使用自訂承載字符或 MQTT 使用者名稱和密碼進行身分驗證， 則可以將其遷移至 ， AWS IoT Core 而不必為其佈建新身分。您可以搭配 AWS IoT Core 支援的任何通訊協定使用自訂身分驗證。如需 AWS IoT Core 支援的通訊協定的詳細資訊，請參閱 [裝置通訊協定](protocols.md)。

**Topics**
+ [

# 了解自訂身分驗證工作流程
](custom-authorizer.md)
+ [

# 建立和管理自訂授權方 (CLI)
](config-custom-auth.md)
+ [

# 使用 X.509 用戶端憑證進行自訂身分驗證
](custom-auth-509cert.md)
+ [

# AWS IoT Core 使用自訂身分驗證連線至
](custom-auth.md)
+ [

# 疑難排解您的授權方
](custom-auth-troubleshooting.md)

# 了解自訂身分驗證工作流程
<a name="custom-authorizer"></a>

自訂身分驗證可讓您定義如何使用[授權方資源](https://docs.aws.amazon.com/iot/latest/apireference/API_AuthorizerDescription.html)來驗證和授權用戶端。  每個授權方都包含客戶受管 Lambda 函數的參考、用於驗證裝置憑證的選用公有金鑰，以及其他組態資訊。 下圖說明 中自訂身分驗證的授權工作流程 AWS IoT Core。

![\[在 中自訂身分驗證的自訂授權工作流程 AWS IoT Core。\]](http://docs.aws.amazon.com/zh_tw/iot/latest/developerguide/images/custom-authentication.png)


## AWS IoT Core 自訂身分驗證和授權工作流程
<a name="custom-authentication-workflow"></a>

下方清單說明自訂身分驗證和授權工作流程中的每個步驟。

1. 裝置會使用其中一個支援的 來連線至客戶 AWS IoT Core 的資料端點[裝置通訊協定](protocols.md)。裝置會在請求的標頭欄位或查詢參數 （適用於 HTTP Publish 或 MQTT over WebSockets 通訊協定） 中，或在 MQTT CONNECT 訊息的使用者名稱和密碼欄位 （適用於 MQTT 和 MQTT over WebSockets 通訊協定） 中傳遞登入資料。

1. AWS IoT Core 會檢查兩個條件之一：
   + 傳入的請求指定授權方。
   + 接收請求 AWS IoT Core 的資料端點已為其設定預設授權方。

   如果 以下列其中一種方式 AWS IoT Core 尋找授權方， AWS IoT Core 會觸發與授權方相關聯的 Lambda 函數。

1.  （選用） 如果您已啟用權杖簽署，請在觸發 Lambda 函數之前，使用存放在授權方中的 公有金鑰 AWS IoT Core 驗證請求簽章。如果驗證失敗， AWS IoT Core 會停止請求，而不會叫用 Lambda 函數。  

1. Lambda 函數會接收請求中的憑證和連線中繼資料，並做出身分驗證決策。

1. Lambda 函數會傳回身分驗證決策的結果，以及指定連線中允許哪些動作 AWS IoT Core 的政策文件。Lambda 函數也會傳回資訊，指定透過叫用 Lambda 函數 AWS IoT Core 重新驗證請求中登入資料的頻率。

1. AWS IoT Core 根據從 Lambda 函數接收到的政策，評估連線上的活動。

1. 建立連線且最初調用您的自訂授權方 Lambda 後，閒置連線的下一個調用最多可延遲 5 分鐘，而不需要任何 MQTT 操作。之後，後續調用將遵循自訂授權方 Lambda 中的重新整理間隔。這種方法可以防止超出 Lambda 並行限制的過度調用 AWS 帳戶。

## 擴展考量
<a name="custom-authentication-scaling"></a>

 因為 Lambda 函數會為您的授權方處理身分驗證和授權，所以此函數會受制於 Lambda 定價和服務配額，例如並行執行速率。 如需 Lambda 定價的詳細資訊，請參閱[ Lambda 定價](https://aws.amazon.com/lambda/pricing/)。您可以調整 Lambda 函數回應中的 `refreshAfterInSeconds` 和 `disconnectAfterInSeconds` 參數，管理 Lambda 函數上的負載。如需 Lambda 函數回應內容的詳細資訊，請參閱 [定義您的 Lambda 函式](custom-auth-lambda.md)。

**注意**  
如果將簽署保持啟用狀態，您可以防止無法辨識的用戶端過度觸發 Lambda。在您的授權方中停用簽署之前，請考慮這一點。

**注意**  
自訂授權方的 Lambda 函數逾時限制為 5 秒。

# 建立和管理自訂授權方 (CLI)
<a name="config-custom-auth"></a>

AWS IoT Core 使用自訂授權方實作自訂身分驗證和授權機制。自訂授權方是一種 AWS IoT Core 資源，可讓您根據特定需求彈性定義和實作規則和政策。若要使用step-by-step說明建立自訂授權方，請參閱[教學課程：為 建立自訂授權方 AWS IoT Core](https://docs.aws.amazon.com//iot/latest/developerguide/custom-auth-tutorial.html)。

每個授權方都包含以下元件：
+  *名稱*：識別授權方的唯一使用者定義字串。
+  *Lambda 函數 ARN*：Lambda 函數的 Amazon 資源名稱 (ARN)，用於實作授權和身分驗證邏輯。  
+  *字符金鑰名稱*：用來從 HTTP 標頭、查詢參數或 MQTT CONNECT 使用者名稱擷取字符以執行簽章驗證的金鑰名稱。如果在您的授權方中啟用簽署，則此值為必要的。
+  *已停用簽署旗標 (選用)*：布林值，用來指定是否要停用憑證上的簽署需求。 這對於簽署憑證沒有意義的案例很有用，例如使用 MQTT 使用者名稱和密碼的身分驗證結構述。預設值為 `false`，因此預設會啟用簽署。
+  *字符簽署公有金鑰*： AWS IoT Core 用來驗證字符簽章的公有金鑰。其長度下限為 2,048 位元。如果在您的授權方中啟用簽署，則此值為必要的。  

Lambda 會依據 Lambda 函數執行的次數，以及在您函數中執行程式碼所需的時間，向您收費。如需 Lambda 定價的詳細資訊，請參閱 [Lambda 定價](https://aws.amazon.com/lambda/pricing/)。如需建立 Lambda 函數的詳細資訊，請參閱《[Lambda 開發人員指南](https://docs.aws.amazon.com/lambda/latest/dg/)》。

**注意**  
如果將簽署保持啟用狀態，您可以防止無法辨識的用戶端過度觸發 Lambda。在您的授權方中停用簽署之前，請考慮這一點。

**注意**  
自訂授權方的 Lambda 函數逾時限制為 5 秒。

**Topics**
+ [

# 定義您的 Lambda 函式
](custom-auth-lambda.md)
+ [

# 建立授權方
](custom-auth-create-authorizer.md)
+ [

# 授權 AWS IoT 叫用您的 Lambda 函數
](custom-auth-authorize.md)
+ [

# 測試您的授權方
](custom-auth-testing.md)
+ [

# 管理自訂授權方
](custom-auth-manage.md)

# 定義您的 Lambda 函式
<a name="custom-auth-lambda"></a>

 當 AWS IoT Core 叫用您的授權方時，它會觸發與授權方相關聯的 Lambda，其中包含下列 JSON 物件的事件。範例 JSON 物件包含所有可能的欄位。不包含與連線請求無關的任何欄位。

```
{
    "token" :"aToken",
    "signatureVerified": Boolean, // Indicates whether the device gateway has validated the signature.
    "protocols": ["tls", "http", "mqtt"], // Indicates which protocols to expect for the request.
    "protocolData": {
        "tls" : {
            "serverName": "serverName" // The server name indication (SNI) host_name string.
        },
        "http": {
            "headers": {
                "#{name}": "#{value}"
            },
            "queryString": "?#{name}=#{value}"
        },
        "mqtt": {
            "username": "myUserName",
            "password": "myPassword", // A base64-encoded string.
            "clientId": "myClientId" // Included in the event only when the device sends the value.
        }
    },
    "connectionMetadata": {
        "id": UUID // The connection ID. You can use this for logging.
    },
}
```

 Lambda 函數應該使用此資訊來驗證傳入連線，並決定連線中允許哪些動作。此函數應該傳送包含下列值的回應。
+  `isAuthenticated`：指出是否驗證請求的布林值。
+  `principalId`：英數字串，作為自訂授權請求所傳送之字符的識別符。該值必須為英數字串 (字元數量不低於 1 個且不超過 128 個)，且符合此規則表達式 (regex) 模式：`([a-zA-Z0-9]){1,128}`。不允許非英數字元的特殊字元與 `principalId`搭配使用 AWS IoT Core。如果允許 使用非英數特殊字元，請參閱 AWS 其他服務的文件`principalId`。
+  `policyDocuments`：JSON 格式 AWS IoT Core 政策文件的清單 如需建立 AWS IoT Core 政策的詳細資訊，請參閱[AWS IoT Core 政策](iot-policies.md)。政策文件的數目上限為 10 份政策文件。每份政策文件最多可包含 2,048 個字元。
+  `disconnectAfterInSeconds`：整數，用來指定連接至 AWS IoT Core 閘道的持續時間上限 (以秒為單位)。最小值為 300 秒，最大值為 86,400 秒。預設值為 86，400。
**注意**  
建立連線時，會設定 的值 `disconnectAfterInSeconds`（由 Lambda 函數傳回）。在後續政策重新整理 Lambda 調用期間，無法修改此值。
+  `refreshAfterInSeconds`：整數，用來指定政策重新整理的間隔。一旦超出此間隔， AWS IoT Core 便會叫用 Lambda 函數，以允許政策重新整理。最小值為 300 秒，最大值為 86,400 秒。

  下列 JSON 物件包含您的 Lambda 函數可以傳送的回應範例。

 **\$1 "isAuthenticated":true, //A Boolean that determines whether client can connect. "principalId": "xxxxxxxx",  //A string that identifies the connection in logs. "disconnectAfterInSeconds": 86400,  "refreshAfterInSeconds": 300,   "policyDocuments": [       \$1         "Version": "2012-10-17",         "Statement": [            \$1               "Action": "iot:Publish",               "Effect": "Allow",               "Resource": "arn:aws:iot:us-east-1:<your\$1aws\$1account\$1id>:topic/customauthtesting"             \$1          ]        \$1     ] \$1**

 `policyDocument` 值必須包含有效的 AWS IoT Core 政策文件。如需 AWS IoT Core 政策的詳細資訊，請參閱[AWS IoT Core 政策](iot-policies.md)。  在 MQTT over TLS 和 MQTT over WebSockets 連線中， 會在 `refreshAfterInSeconds` 欄位值中指定的間隔內 AWS IoT Core 快取此政策。如果採用 HTTP 連線，除非裝置使用的是 HTTP 持續連線 (也稱為 HTTP 保持連線或 HTTP 連線重複使用)，否則每個授權請求都會呼叫 Lambda 函數。您可以在設定授權方時選擇啟用快取。在此間隔期間， 會針對此快取政策 AWS IoT Core 授權已建立連線中的動作，而不會再次觸發您的 Lambda 函數。如果在自訂身分驗證期間發生失敗， 會 AWS IoT Core 終止連線。如果連線開啟的時間超過 `disconnectAfterInSeconds`參數中指定的值， AWS IoT Core 也會終止連線。

 下列 JavaScript 包含範例 Node.js Lambda 函數，其會在 MQTT Connect 訊息中尋找值為 的密碼，`test`並傳回政策，授予許可，以 AWS IoT Core 連接至名為 的用戶端，`myClientName`並發佈至包含相同用戶端名稱的主題。如果找不到預期的密碼，它會傳回拒絕這兩個動作的政策。

```
// A simple Lambda function for an authorizer. It demonstrates 
// how to parse an MQTT password and generate a response.

exports.handler = function(event, context, callback) { 
    var uname = event.protocolData.mqtt.username;
    var pwd = event.protocolData.mqtt.password;
    var buff = new Buffer(pwd, 'base64');
    var passwd = buff.toString('ascii');
    switch (passwd) { 
        case 'test': 
            callback(null, generateAuthResponse(passwd, 'Allow')); 
            break;
        default: 
            callback(null, generateAuthResponse(passwd, 'Deny'));  
    }
};

// Helper function to generate the authorization response.
var generateAuthResponse = function(token, effect) { 
    var authResponse = {}; 
    authResponse.isAuthenticated = true; 
    authResponse.principalId = 'TEST123'; 
    
    var policyDocument = {}; 
    policyDocument.Version = '2012-10-17';		 	 	 
    policyDocument.Statement = []; 
    var publishStatement = {}; 
    var connectStatement = {};
    connectStatement.Action = ["iot:Connect"];
    connectStatement.Effect = effect;
    connectStatement.Resource = ["arn:aws:iot:us-east-1:123456789012:client/myClientName"];
    publishStatement.Action = ["iot:Publish"]; 
    publishStatement.Effect = effect; 
    publishStatement.Resource = ["arn:aws:iot:us-east-1:123456789012:topic/telemetry/myClientName"]; 
    policyDocument.Statement[0] = connectStatement;
    policyDocument.Statement[1] = publishStatement; 
    authResponse.policyDocuments = [policyDocument]; 
    authResponse.disconnectAfterInSeconds = 3600; 
    authResponse.refreshAfterInSeconds = 300;
    
    return authResponse; 
}
```

 當上述 Lambda 函數在 MQTT Connect 訊息中收到 `test` 的預期密碼時，它會傳回下列 JSON。`password` 和 `principalId` 屬性的值會是 MQTT 連結訊息的值。

```
{
  "password": "password",
  "isAuthenticated": true,
  "principalId": "principalId",
  "policyDocuments": [
    {
      "Version": "2012-10-17",		 	 	 
      "Statement": [
        {
          "Action": "iot:Connect",
          "Effect": "Allow",
          "Resource": "*"
        },
        {
          "Action": "iot:Publish",
          "Effect": "Allow",
          "Resource": "arn:aws:iot:region:accountId:topic/telemetry/${iot:ClientId}"
        },
        {
          "Action": "iot:Subscribe",
          "Effect": "Allow",
          "Resource": "arn:aws:iot:region:accountId:topicfilter/telemetry/${iot:ClientId}"
        },
        {
          "Action": "iot:Receive",
          "Effect": "Allow",
          "Resource": "arn:aws:iot:region:accountId:topic/telemetry/${iot:ClientId}"
        }
      ]
    }
  ],
  "disconnectAfterInSeconds": 3600,
  "refreshAfterInSeconds": 300
}
```

# 建立授權方
<a name="custom-auth-create-authorizer"></a>

 您可以使用 [CreateAuthorizer API](https://docs.aws.amazon.com/iot/latest/apireference/API_CreateAuthorizer.html) 建立授權方。下列範例描述此命令。

```
aws iot create-authorizer
--authorizer-name MyAuthorizer
--authorizer-function-arn arn:aws:lambda:us-west-2:<account_id>:function:MyAuthorizerFunction  //The ARN of the Lambda function.
[--token-key-name MyAuthorizerToken //The key used to extract the token from headers.
[--token-signing-public-keys FirstKey=
 "-----BEGIN PUBLIC KEY-----
  [...insert your public key here...] 
  -----END PUBLIC KEY-----"
[--status ACTIVE]
[--tags <value>]
[--signing-disabled | --no-signing-disabled]
```

您可以使用 `signing-disabled` 參數，在每次叫用授權方時選擇退出簽章驗證。除非您必須停用簽署，否則強烈建議您不要這樣做。簽章驗證可保護您防範未知裝置過度叫用 Lambda 函數。在建立授權方之後，您無法更新授權方的 `signing-disabled` 狀態。若要變更此行為，您必須使用不同的 `signing-disabled` 參數值建立另一個自訂授權方。

如果您已停用簽署，`tokenKeyName` 和 `tokenSigningPublicKeys` 參數的值是選用值。如果啟用簽署，則它們是必要值。

建立 Lambda 函數和自訂授權方之後，您必須明確授予 AWS IoT Core 服務許可，才能代表您叫用函數。 您可以使用下列命令來執行此操作。

**注意**  
預設 IoT 端點可能不支援搭配 Lambda 函數使用自訂授權方。反之，您可以使用網域組態來定義新的端點，然後為自訂授權方指定該端點。

```
aws lambda add-permission --function-name <lambda_function_name>
--principal iot.amazonaws.com --source-arn <authorizer_arn>
--statement-id Id-123 --action "lambda:InvokeFunction"
```

# 授權 AWS IoT 叫用您的 Lambda 函數
<a name="custom-auth-authorize"></a>

在本節中，您將授予您剛建立的自訂授權方資源的許可，以執行 Lambda 函數。若要授與許可，您可以使用 [add-permission](https://docs.aws.amazon.com//cli/latest/reference/lambda/add-permission.html) CLI 命令。

**使用 將許可授予 Lambda 函數 AWS CLI**

1. 在插入您的值之後，輸入以下命令。請注意，`statement-id` 值必須是唯一的。`Id-1234` 將 取代為您擁有的確切值，否則您可能會發生錯誤`ResourceConflictException`。

   ```
   aws lambda add-permission  \
   --function-name "custom-auth-function" \
   --principal "iot.amazonaws.com" \
   --action "lambda:InvokeFunction" \
   --statement-id "Id-1234" \
   --source-arn authorizerArn
   ```

1. 如果命令成功，它會傳回許可陳述式，例如此範例。您可以繼續下一節來測試自訂授權方。

   ```
   {
       "Statement": "{\"Sid\":\"Id-1234\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"iot.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function\"}}}"
   }
   ```

   如果命令未成功，它會傳回錯誤，例如此範例。您必須先檢閱並更正錯誤，然後才能繼續進行。

   ```
   An error occurred (AccessDeniedException) when calling the AddPermission operation: User: arn:aws:iam::57EXAMPLE833:user/EXAMPLE-1 is not authorized to perform: lambda:AddPer
   mission on resource: arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function
   ```

# 測試您的授權方
<a name="custom-auth-testing"></a>

 您可以使用 [TestInvokeAuthorizer](https://docs.aws.amazon.com/iot/latest/apireference/API_TestInvokeAuthorizer.html) API 來測試授權方的叫用和傳回值。此 API 可讓您指定通訊協定中繼資料，並在您的授權方中測試簽章驗證。

下列標籤顯示如何使用 AWS CLI 來測試您的授權方。

------
#### [ Unix-like ]

```
aws iot test-invoke-authorizer --authorizer-name NAME_OF_AUTHORIZER \
--token TOKEN_VALUE --token-signature TOKEN_SIGNATURE
```

------
#### [ Windows CMD ]

```
aws iot test-invoke-authorizer --authorizer-name NAME_OF_AUTHORIZER ^
--token TOKEN_VALUE --token-signature TOKEN_SIGNATURE
```

------
#### [ Windows PowerShell ]

```
aws iot test-invoke-authorizer --authorizer-name NAME_OF_AUTHORIZER `
--token TOKEN_VALUE --token-signature TOKEN_SIGNATURE
```

------

`token-signature` 參數的值是簽署的字符。若要了解如何取得此值，請參閱 [簽署字符](custom-auth.md#custom-auth-token-signature)。

如果您的授權方取得使用者名稱和密碼，您可以使用 `--mqtt-context` 參數來傳遞此資訊。下列標籤顯示如何使用 `TestInvokeAuthorizer` API，將包含使用者名稱、密碼和用戶端名稱的 JSON 物件傳送給您的自訂授權方。

------
#### [ Unix-like ]

```
aws iot test-invoke-authorizer --authorizer-name NAME_OF_AUTHORIZER  \
--mqtt-context '{"username": "USER_NAME", "password": "dGVzdA==", "clientId":"CLIENT_NAME"}'
```

------
#### [ Windows CMD ]

```
aws iot test-invoke-authorizer --authorizer-name NAME_OF_AUTHORIZER  ^
--mqtt-context '{"username": "USER_NAME", "password": "dGVzdA==", "clientId":"CLIENT_NAME"}'
```

------
#### [ Windows PowerShell ]

```
aws iot test-invoke-authorizer --authorizer-name NAME_OF_AUTHORIZER  `
--mqtt-context '{"username": "USER_NAME", "password": "dGVzdA==", "clientId":"CLIENT_NAME"}'
```

------

密碼必須為 base64 編碼。下列範例顯示如何在類似 Unix 環境中編碼密碼。

```
echo -n PASSWORD | base64
```

# 管理自訂授權方
<a name="custom-auth-manage"></a>

 您可以使用下列 API 來管理授權方。
+ [ListAuthorizers](https://docs.aws.amazon.com/iot/latest/apireference/API_ListAuthorizers.html)：顯示您帳戶中的所有授權方。
+  [DescribeAuthorizer](https://docs.aws.amazon.com/iot/latest/apireference/API_DescribeAuthorizer.html)：顯示所指定授權方的屬性。這些值包括建立日期、上次修改日期和其他屬性。
+ [SetDefaultAuthorizer](https://docs.aws.amazon.com/iot/latest/apireference/API_SetDefaultAuthorizer.html)：指定 AWS IoT Core 資料端點的預設授權方。如果裝置未傳遞 AWS IoT Core 登入資料，且未指定授權方，則 AWS IoT Core 使用此授權方。如需使用 AWS IoT Core 登入資料的詳細資訊，請參閱 [用戶端身分驗證](client-authentication.md)。
+ [UpdateAuthorizer](https://docs.aws.amazon.com/iot/latest/apireference/API_UpdateAuthorizer.html)：變更所指定授權方的狀態、字符金鑰名稱或公有金鑰。
+  [DeleteAuthorizer](https://docs.aws.amazon.com/iot/latest/apireference/API_DeleteAuthorizer.html)：刪除指定的授權方。

**注意**  
 您無法更新授權方的簽署需求。這表示您無法在需要簽署的現有授權方中停用簽署。您也無法在不需要簽署的現有授權方中要求簽署。

# 使用 X.509 用戶端憑證進行自訂身分驗證
<a name="custom-auth-509cert"></a>

將裝置連線至 時 AWS IoT Core，您有多種身分[驗證類型](protocols.md#connection-protocol-auth-mode)可用。您可以使用 X.[509 用戶端憑證](https://docs.aws.amazon.com//iot/latest/developerguide/x509-client-certs.html)來驗證用戶端和裝置連線，或定義[自訂授權方](https://docs.aws.amazon.com//iot/latest/developerguide/custom-authentication.html)來管理自己的用戶端身分驗證和授權邏輯。本主題說明如何搭配 X.509 用戶端憑證使用自訂身分驗證。

如果您已經使用 X.509 憑證對裝置進行身分驗證，並想要執行額外的驗證和自訂授權，則使用自訂身分驗證搭配 X.509 憑證可能會有所幫助。例如，如果您在 X.509 用戶端憑證中存放裝置的資料，例如其序號，則在 AWS IoT Core 驗證 X.509 用戶端憑證之後，您可以使用自訂授權方，根據憑證的 CommonName 欄位中存放的資訊來識別特定裝置。將裝置連線至 時，搭配 X.509 憑證使用自訂身分驗證可增強裝置安全管理， AWS IoT Core 並提供管理身分驗證和授權邏輯的更多彈性。 AWS IoT Core 支援搭配 X.509 憑證的自訂身分驗證，其使用 X.509 憑證和自訂授權方身分驗證類型，同時適用於 [MQTT](https://docs.aws.amazon.com//iot/latest/developerguide/mqtt.html) 通訊協定和 [HTTPS](https://docs.aws.amazon.com//iot/latest/developerguide/http.html) 通訊協定。如需裝置端點支援的身分驗證類型和應用程式通訊協定 AWS IoT Core 的詳細資訊，請參閱[裝置通訊協定](https://docs.aws.amazon.com//iot/latest/developerguide/protocols.html)。

**注意**  
 AWS GovCloud (US) 區域不支援使用 X.509 用戶端憑證的自訂身分驗證。

**重要**  
您必須使用使用[網域組態](iot-custom-endpoints-configurable.md)建立的端點。此外，用戶端在連線至 時必須提供[伺服器名稱指示 (SNI)](https://www.rfc-editor.org/rfc/rfc3546#section-3.1) 延伸 AWS IoT Core。

**Topics**
+ [

## 步驟 1：向 註冊您的 X.509 用戶端憑證 AWS IoT Core
](#custom-auth-509cert-client)
+ [

## 步驟 2：建立 Lambda 函數
](#custom-auth-509cert-lambda)
+ [

## 步驟 3：建立自訂授權方
](#custom-auth-509cert-authorizer)
+ [

## 步驟 4：在網域組態中設定身分驗證類型和應用程式通訊協定
](#custom-auth-509cert-domainconfig)

## 步驟 1：向 註冊您的 X.509 用戶端憑證 AWS IoT Core
<a name="custom-auth-509cert-client"></a>

如果您尚未這麼做，請註冊並啟用 [X.509 用戶端憑證。](https://docs.aws.amazon.com//iot/latest/developerguide/x509-client-certs.html) AWS IoT Core否則，跳至下一步。

若要使用 註冊和啟用您的用戶端憑證 AWS IoT Core，請遵循下列步驟：

1. 如果您[直接使用 建立用戶端憑證 AWS IoT](https://docs.aws.amazon.com//iot/latest/developerguide/device-certs-create.html)。這些用戶端憑證會自動向 註冊 AWS IoT Core。

1. 如果您[建立自己的用戶端憑證](https://docs.aws.amazon.com//iot/latest/developerguide/device-certs-your-own.html)，請依照[這些指示向 註冊 AWS IoT Core](https://docs.aws.amazon.com//iot/latest/developerguide/register-device-cert.html)憑證。

1. 若要啟用您的用戶端憑證，請遵循[這些指示](https://docs.aws.amazon.com//iot/latest/developerguide/activate-or-deactivate-device-cert.html)。

## 步驟 2：建立 Lambda 函數
<a name="custom-auth-509cert-lambda"></a>

AWS IoT Core 使用自訂授權方來實作自訂身分驗證和授權機制。自訂授權方與 Lambda 函數相關聯，該函數會判斷裝置是否經過身分驗證，以及允許裝置執行哪些操作。當裝置連線到 時 AWS IoT Core， 會 AWS IoT Core 擷取授權方詳細資訊，包括授權方名稱和相關聯的 Lambda 函數，並叫用 Lambda 函數。Lambda 函數會收到事件，其中包含具有裝置 X.509 用戶端憑證資料的 JSON 物件。您的 Lambda 函數使用此事件 JSON 物件來評估身分驗證請求、決定要採取的動作，以及傳送回應。

### Lambda 函數事件範例
<a name="custom-auth-509cert-event"></a>

下列範例 JSON 物件包含可以包含的所有可能欄位。實際 JSON 物件只會包含與特定連線請求相關的欄位。

```
{
	"token": "aToken",
	"signatureVerified": true,
	"protocols": [
		"tls",
		"mqtt"
	],
	"protocolData": {
		"tls": {
			"serverName": "serverName",
			"x509CertificatePem": "x509CertificatePem",
			"principalId": "principalId"
		},
		"mqtt": {
			"clientId": "myClientId",
                     "username": "myUserName",
                     "password": "myPassword"
		}
	},
	"connectionMetadata": {
		"id": "UUID"
	}
}
```

`signatureVerified`  
布林值，指出在叫用授權方的 Lambda 函數之前，是否驗證授權方中設定的字符簽章。如果授權方設定為停用權杖簽署，則此欄位將為 false。

`protocols`  
包含請求預期通訊協定的陣列。

`protocolData`  
包含連線中所用通訊協定資訊的物件。它提供通訊協定特定的詳細資訊，可用於身分驗證、授權等。  
`tls` - 此物件會保留與 TLS (Transport Layer Security) 通訊協定相關的資訊。  
+ `serverName` - [伺服器名稱指示 (SNI)](https://www.rfc-editor.org/rfc/rfc3546#section-3.1) 主機名稱字串。 AWS IoT Core 要求裝置將 [SNI 延伸](https://www.rfc-editor.org/rfc/rfc3546#section-3.1)模組傳送至 Transport Layer Security (TLS) 通訊協定，並在 `host_name`欄位中提供完整的端點地址。
+ `x509CertificatePem` - PEM 格式的 X.509 憑證，用於 TLS 連線中的用戶端身分驗證。
+ `principalId` - TLS 連線中與用戶端相關聯的主體識別符。
`mqtt` - 此物件會保留 MQTT 通訊協定的相關資訊。  
+ `clientId` - 字串只需要包含在裝置傳送此值的事件中。
+ `username` - MQTT Connect 封包中提供的使用者名稱。
+ `password` - MQTT Connect 封包中提供的密碼。

`connectionMetadata`  
連線的中繼資料。  
`id` - 用於記錄和故障診斷的連線 ID。

**注意**  
在此事件中，JSON 物件 `x509CertificatePem`和 `principalId`是請求中的兩個新欄位。的值`principalId`與 的值相同`certificateId`。如需詳細資訊，請參閱[憑證](https://docs.aws.amazon.com//iot/latest/apireference/API_Certificate.html)。

### Lambda 函數回應範例
<a name="custom-auth-509cert-response"></a>

Lambda 函數應使用事件 JSON 物件中的資訊來驗證傳入連線，並決定連線中允許哪些動作。

下列 JSON 物件包含 Lambda 函數可以傳送的範例回應。

```
{
	"isAuthenticated": true,
	"principalId": "xxxxxxxx",
	"disconnectAfterInSeconds": 86400,
	"refreshAfterInSeconds": 300,
	"policyDocuments": [
		{
			"Version": "2012-10-17",		 	 	 
			"Statement": [
				{
					"Effect": "Allow",
					"Action": "iot:Publish",
					"Resource": "arn:aws:iot:us-east-1:123456789012:topic/customauthtesting"
				}
			]
		}
	]
}
```

在此範例中，此函數應該傳送包含下列值的回應。

`isAuthenticated`  
布林值，指出是否驗證請求。

`principalId`  
英數字串，可做為自訂授權請求所傳送字符的識別符。值必須是至少包含一個英數字串，且不超過 128 個字元。它會識別日誌中的連線。的值`principalId`必須與事件 JSON 物件`principalId`中的 值相同 （即 X.509 憑證的 certificateId)。

`policyDocuments`  
JSON 格式 AWS IoT Core 政策文件的清單。此值為選用，並支援[物件政策變數](https://docs.aws.amazon.com//iot/latest/developerguide/thing-policy-variables.html)和[憑證政策變數](https://docs.aws.amazon.com//iot/latest/developerguide/cert-policy-variables.html)。政策文件的數量上限為 10。每份政策文件最多可包含 2,048 個字元。如果您將多個政策連接到用戶端憑證和 Lambda 函數，則許可是所有政策的集合。如需建立 AWS IoT Core 政策的詳細資訊，請參閱 [政策](https://docs.aws.amazon.com//iot/latest/developerguide/iot-policies.html)。

`disconnectAfterInSeconds`  
整數，指定與 AWS IoT Core 閘道連線的最長持續時間 （以秒為單位）。最小值為 300 秒，最大值為 86，400 秒。 `disconnectAfterInSeconds`是連線的生命週期，不會在連續政策重新整理時重新整理。

`refreshAfterInSeconds`  
整數，指定政策重新整理之間的間隔。當此間隔通過時， 會 AWS IoT Core 叫用 Lambda 函數以允許政策重新整理。最小值為 300 秒，最大值為 86,400 秒。

### Lambda 函數範例
<a name="custom-auth-509cert-js-example"></a>

以下是 Node.js Lambda 函數的範例。函數會檢查用戶端的 X.509 憑證，並擷取相關資訊，例如序號、指紋和主體名稱。如果擷取的資訊符合預期值，則會授予用戶端連線的存取權。此機制可確保只有具有有效憑證的授權用戶端才能建立連線。

```
const crypto = require('crypto');

exports.handler = async (event) => {
    
    // Extract the certificate PEM from the event
    const certPem = event.protocolData.tls.x509CertificatePem;
    
    // Parse the certificate using Node's crypto module
    const cert = new crypto.X509Certificate(certPem);
    
    var effect = "Deny";
    // Allow permissions only for a particular certificate serial, fingerprint, and subject
    if (cert.serialNumber === "7F8D2E4B9C1A5036DE8F7C4B2A91E5D80463BC9A1257" // This is a random serial
       && cert.fingerprint === "F2:9A:C4:1D:B5:E7:08:3F:6B:D0:4E:92:A7:C1:5B:8D:16:0F:E3:7A" // This is a random fingerprint
       && cert.subject === "allow.example.com") {
      effect = "Allow";
    }
    
    return generateAuthResponse(event.protocolData.tls.principalId, effect);
};


// Helper function to generate the authorization response.
function generateAuthResponse(principalId, effect) {
    const authResponse = {
        isAuthenticated: true,
        principalId,
        disconnectAfterInSeconds: 3600,
        refreshAfterInSeconds: 300,
        policyDocuments: [
          {
            Version: "2012-10-17",		 	 	 
            Statement: [
              {
                Action: ["iot:Connect"],
                Effect: effect,
                Resource: [
                  "arn:aws:iot:us-east-1:123456789012:client/myClientName"
                ]
              },
              {
                Action: ["iot:Publish"],
                Effect: effect,
                Resource: [
                  "arn:aws:iot:us-east-1:123456789012:topic/telemetry/myClientName"
                ]
              },
              {
                Action: ["iot:Subscribe"],
                Effect: effect,
                Resource: [
                   "arn:aws:iot:us-east-1:123456789012:topicfilter/telemetry/myClientName"
                ]
              },
              {
                Action: ["iot:Receive"],
                Effect: effect,
                Resource: [
                   "arn:aws:iot:us-east-1:123456789012:topic/telemetry/myClientName"
                ]
              }
            ]
          }
        ]
      };

  return authResponse;
}
```

上述 Lambda 函數在收到具有預期序列、指紋和主體的憑證時，會傳回下列 JSON。的值`x509CertificatePem`將是 TLS 交握中提供的用戶端憑證。如需詳細資訊，請參閱[定義 Lambda 函數](https://docs.aws.amazon.com//iot/latest/developerguide/config-custom-auth.html#custom-auth-lambda)。

```
{
	"isAuthenticated": true,
	"principalId": "principalId in the event JSON object",
	"policyDocuments": [
		{
			"Version": "2012-10-17",		 	 	 
			"Statement": [
				{
					"Action": "iot:Connect",
					"Effect": "Allow",
					"Resource": "arn:aws:iot:us-east-1:123456789012:client/myClientName"
				},
				{
					"Action": "iot:Publish",
					"Effect": "Allow",
					"Resource": "arn:aws:iot:us-east-1:123456789012:topic/telemetry/myClientName"
				},
				{
					"Action": "iot:Subscribe",
					"Effect": "Allow",
					"Resource": "arn:aws:iot:us-east-1:123456789012:topicfilter/telemetry/myClientName"
				},
				{
					"Action": "iot:Receive",
					"Effect": "Allow",
					"Resource": "arn:aws:iot:us-east-1:123456789012:topic/telemetry/myClientName"
				}
			]
		}
	],
	"disconnectAfterInSeconds": 3600,
	"refreshAfterInSeconds": 300
}
```

## 步驟 3：建立自訂授權方
<a name="custom-auth-509cert-authorizer"></a>

[定義 Lambda 函數](#custom-auth-509cert-lambda)之後，請建立自訂授權方來管理您自己的用戶端身分驗證和授權邏輯。您可以遵循[步驟 3：建立客戶授權方資源及其授權](https://docs.aws.amazon.com//iot/latest/developerguide/custom-auth-tutorial.html#custom-auth-tutorial-authorizer)中的詳細說明。如需詳細資訊，請參閱[建立 授權方](https://docs.aws.amazon.com//iot/latest/developerguide/config-custom-auth.html)。

在建立自訂授權方的過程中，您必須授予 AWS IoT 許可，才能在 Lambda 函數建立之後叫用該函數。如需詳細說明，請參閱[授權 AWS IoT 叫用您的 Lambda 函數](custom-auth-authorize.md)。

## 步驟 4：在網域組態中設定身分驗證類型和應用程式通訊協定
<a name="custom-auth-509cert-domainconfig"></a>

若要使用自訂身分驗證搭配 X.509 用戶端憑證來驗證裝置，您必須在網域組態中設定身分驗證類型和應用程式通訊協定，而且必須傳送 SNI 延伸。的值`authenticationType`必須是 `CUSTOM_AUTH_X509`，而 的值`applicationProtocol`可以是 `SECURE_MQTT`或 `HTTPS`。

### 在網域組態 (CLI) 中設定身分驗證類型和應用程式通訊協定
<a name="custom-auth-509cert-cli"></a>

如果您沒有網域組態，請使用 [https://docs.aws.amazon.com//cli/latest/reference/iot/create-domain-configuration.html](https://docs.aws.amazon.com//cli/latest/reference/iot/create-domain-configuration.html)命令來建立組態。的值`authenticationType`必須是 `CUSTOM_AUTH_X509`，而 的值`applicationProtocol`可以是 `SECURE_MQTT`或 `HTTPS`。

```
aws iot create-domain-configuration \
    --domain-configuration-name domainConfigurationName \
    --authentication-type CUSTOM_AUTH_X509 \  
    --application-protocol SECURE_MQTT \ 
    --authorizer-config '{
        "defaultAuthorizerName": my-custom-authorizer
    }'
```

如果您已有網域組態，`applicationProtocol`請視需要使用[https://docs.aws.amazon.com//cli/latest/reference/iot/update-domain-configuration.html](https://docs.aws.amazon.com//cli/latest/reference/iot/update-domain-configuration.html)命令更新`authenticationType`和 。請注意，您無法變更預設端點 () 上的身分驗證類型或通訊協定`iot:Data-ATS`。

```
aws iot update-domain-configuration \
    --domain-configuration-name domainConfigurationName \
    --authentication-type CUSTOM_AUTH_X509 \  
    --application-protocol SECURE_MQTT \
    --authorizer-config '{
        "defaultAuthorizerName": my-custom-authorizer
    }'
```

`domain-configuration-name`  
網域組態的名稱。

`authentication-type`  
網域組態的身分驗證類型。如需詳細資訊，請參閱[選擇身分驗證類型](protocols.md#connection-protocol-auth-mode)。

`application-protocol`  
裝置用來與之通訊的應用程式通訊協定 AWS IoT Core。如需詳細資訊，請參閱[選擇應用程式通訊協定](protocols.md#protocol-selection)。

`--authorizer-config`  
在網域組態中指定授權方組態的物件。

`defaultAuthorizerName`  
網域組態的授權方名稱。

如需詳細資訊，請參閱 *AWS IoT API 參考*中的 [CreateDomainConfiguration](https://docs.aws.amazon.com//iot/latest/apireference/API_CreateDomainConfiguration.html) 和 [UpdateDomainConfiguration](https://docs.aws.amazon.com//iot/latest/apireference/API_UpdateDomainConfiguration.html)。如需網域組態的詳細資訊，請參閱[網域組態](https://docs.aws.amazon.com//iot/latest/developerguide/iot-custom-endpoints-configurable.html)。

# AWS IoT Core 使用自訂身分驗證連線至
<a name="custom-auth"></a>

 裝置可以使用 AWS IoT Core 自訂身分驗證搭配 AWS IoT Core 支援裝置傳訊的任何通訊協定來連線至 。如需受支援通訊協定的詳細資訊，請參閱 [裝置通訊協定](protocols.md)。  傳遞至授權方 Lambda 函數的連線資料取決於您使用的通訊協定。如需建立授權方 Lambda 函數的詳細資訊，請參閱 [定義您的 Lambda 函式](custom-auth-lambda.md)。以下各節說明如何使用每個支援的通訊協定來連線，以便進行身分驗證。

## HTTPS
<a name="custom-auth-http"></a>

 AWS IoT Core 使用 [HTTP Publish API](https://docs.aws.amazon.com/iot/latest/apireference/API_iotdata_Publish.html) 將資料傳送到 的裝置，可以透過請求標頭或查詢其 HTTP POST 請求中的參數來傳遞憑證。裝置可以指定要使用 `x-amz-customauthorizer-name` 標頭或查詢參數叫用的授權方。如果您已在授權方中啟用字符簽署，則必須在請求標頭或查詢參數中傳遞 `token-key-name` 和 `x-amz-customauthorizer-signature`。請注意，在瀏覽器中使用 JavaScript 時，`token-signature` 的值必須是 URL 編碼格式。

**注意**  
HTTPS 通訊協定的客戶授權方僅支援發佈操作。如需有關 HTTP 通訊協定的詳細資訊，請參閱 [裝置通訊協定](protocols.md)。

下列範例請求會顯示如何在請求標頭和查詢參數中傳遞這些參數。

```
//Passing credentials via headers
POST /topics/topic?qos=qos HTTP/1.1
Host: your-endpoint 
x-amz-customauthorizer-signature: token-signature
token-key-name: token-value 
x-amz-customauthorizer-name: authorizer-name

//Passing credentials via query parameters
POST /topics/topic?qos=qos&x-amz-customauthorizer-signature=token-signature&token-key-name=token-value HTTP/1.1
```

## MQTT
<a name="custom-auth-mqtt"></a>

 AWS IoT Core 使用 MQTT 連線連線至 的裝置可以透過 MQTT 訊息的 `username`和 `password` 欄位傳遞登入資料。此 `username` 值也可以選擇包含一個查詢字串，將其他值 (包括字符、簽章和授權方名稱) 傳遞給您的授權方。如果您想要使用字符型身分驗證結構描述，而不是 `username` 和 `password` 值，則可使用此查詢字串。  

**注意**  
 密碼欄位中的資料由 base64 編碼 AWS IoT Core。您的 Lambda 函數必須將其解碼。

 以下範例包含一個 `username` 字串，其中包含指定字符和簽章的額外參數。  

```
username?x-amz-customauthorizer-name=authorizer-name&x-amz-customauthorizer-signature=token-signature&token-key-name=token-value
```

若要叫用 授權方， AWS IoT Core 使用 MQTT 和自訂身分驗證連線至 的裝置必須在連接埠 443 上連線。他們也必須傳遞值為 的應用程式層通訊協定交涉 (ALPN) TLS 延伸，`mqtt`以及其 AWS IoT Core 資料端點主機名稱的伺服器名稱指示 (SNI) 延伸。為了避免潛在的錯誤，`x-amz-customauthorizer-signature` 的值必須進行 URL 編碼。我們也強烈建議您對 `x-amz-customauthorizer-name` 和 `token-key-name` 值進行 URL 編碼。如需這些值的詳細資訊，請參閱 [裝置通訊協定](protocols.md)。V2 [AWS IoT 裝置SDKs、行動SDKs和 AWS IoT 裝置用戶端](iot-sdks.md) 可以設定這些延伸模組。 

## MQTT over WebSockets
<a name="custom-auth-websockets"></a>

 AWS IoT Core 透過 WebSockets 使用 MQTT 連線至 的裝置可以透過下列兩種方式之一傳遞登入資料。
+ 透過 HTTP UPGRADE 請求中的請求標頭或查詢參數來建立 WebSockets 連線。
+ 透過 MQTT CONNECT 訊息中的 `username` 和 `password` 欄位。

 如果透過 MQTT CONNECT 訊息傳遞憑證，則需要 ALPN 和 SNI TLS 延伸。如需這些延伸的詳細資訊，請參閱 [MQTT](#custom-auth-mqtt)。下列範例顯示如何透過 HTTP Upgrade 請求傳遞憑證。

```
GET /mqtt HTTP/1.1
Host: your-endpoint 
Upgrade: WebSocket 
Connection: Upgrade 
x-amz-customauthorizer-signature: token-signature
token-key-name: token-value 
sec-WebSocket-Key: any random base64 value 
sec-websocket-protocol: mqtt 
sec-WebSocket-Version: websocket version
```

## 簽署字符
<a name="custom-auth-token-signature"></a>

您必須利用您在 `create-authorizer` 呼叫中所使用之公有/私有金鑰對中的私有金鑰簽署字符。下列範例顯示如何使用類似 UNIX 的命令和 JavaScript 來建立字符簽章。它們會使用 SHA-256 雜湊演算法來編碼簽章。

------
#### [ Command line ]

```
echo -n TOKEN_VALUE | openssl dgst -sha256 -sign PEM encoded RSA private key | openssl base64
```

------
#### [ JavaScript ]

```
const crypto = require('crypto')

const key = "PEM encoded RSA private key"

const k = crypto.createPrivateKey(key)
let sign = crypto.createSign('SHA256')
sign.write(t)
sign.end()
const s = sign.sign(k, 'base64')
```

------

# 疑難排解您的授權方
<a name="custom-auth-troubleshooting"></a>

 本主題逐步解說可能會在自訂身分驗證工作流程中產生問題的常見問題，以及解決這些問題的步驟。若要最有效地疑難排解問題，請啟用 的 CloudWatch 日誌， AWS IoT Core 並將日誌層級設定為 **DEBUG**。您可以在 AWS IoT Core 主控台中啟用 CloudWatch 日誌 ([https://console.aws.amazon.com/iot/](https://console.aws.amazon.com/iot/)：//)。如需針對 AWS IoT Core啟用和設定記錄的詳細資訊，請參閱 [設定 AWS IoT 記錄](configure-logging.md)。

**注意**  
如果您長期將日誌層級保留在 **DEBUG**，CloudWatch 可能會存放大量的記錄資料。這可能會增加您的 CloudWatch 費用。請考慮使用資源型記錄，以增加特定物件群組中僅限裝置的詳細資訊。如需資源型記錄的詳細資訊，請參閱 [設定 AWS IoT 記錄](configure-logging.md)。此外，當您完成疑難排解時，請將日誌層級降低到較不詳細的層級。

開始疑難排解之前，請檢閱 [了解自訂身分驗證工作流程](custom-authorizer.md)，以取得自訂身分驗證程序的高階檢視。這協助您了解可在哪裡尋找問題的來源。

本主題討論下列兩個可供您調查的領域。
+ 與您授權方 Lambda 函數相關的問題。
+ 與您裝置相關的問題。

## 檢查您的授權方 Lambda 函數中的問題
<a name="custom-auth-troubleshooting-lambda"></a>

執行下列步驟，以確定您裝置的連線嘗試正在叫用 Lambda 函數。

1. 確認哪個 Lambda 函數與您的授權方相關聯。

   若要執行此確認，您可以呼叫 [DescribeAuthorizer](https://docs.aws.amazon.com/iot/latest/apireference/API_DescribeAuthorizer.html) API，或在 AWS IoT Core 主控台的 **Secure** (安全) 區段中按一下所需的授權方。

1. 檢查 Lambda 函數的叫用指標。執行下列步驟來執行此動作。

   1. 開啟 AWS Lambda 主控台 ([https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)：//)，然後選取與您的授權方相關聯的 函數。

   1. 選擇 **Monitor** (監控) 標籤，並檢視與您問題相關之時間範圍的指標。

1. 如果您未看到叫用，請確認 AWS IoT Core 具有叫用 Lambda 函數的許可。如果您看到叫用，請跳到下一個步驟。執行下列步驟來驗證您的 Lambda 函數是否具有必要的許可。

   1. 在 AWS Lambda 主控台中為您的函數選擇**許可**索引標籤。

   1. 在頁面底部尋找 **Resource-based Policy** (資源型政策) 區段。如果您的 Lambda 函數具有必要的許可，政策看起來像下列範例。  
****  

      ```
      {
        "Version":"2012-10-17",		 	 	 
        "Id": "default",
        "Statement": [
          {
            "Sid": "Id123",
            "Effect": "Allow",
            "Principal": {
              "Service": "iot.amazonaws.com"
            },
            "Action": "lambda:InvokeFunction",
            "Resource": "arn:aws:lambda:us-east-1:111111111111:function:FunctionName",
            "Condition": {
              "ArnLike": {
                "AWS:SourceArn": "arn:aws:iot:us-east-1:111111111111:authorizer/AuthorizerName"
              },
              "StringEquals": {
                "AWS:SourceAccount": "111111111111"
              }
            }
          }
        ]
      }
      ```

   1. 此政策會將函數的`InvokeFunction`許可授予 AWS IoT Core 委託人。如果您沒有看到它，您必須使用 [AddPermission](https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html) API 來新增它。下列範例顯示如何使用 AWS CLI來做到這一點。

      ```
      aws lambda add-permission --function-name FunctionName --principal iot.amazonaws.com --source-arn AuthorizerARn --statement-id Id-123 --action "lambda:InvokeFunction"
      ```

1. 如果您看到叫用，請確認沒有錯誤。錯誤可能表示 Lambda 函數未正確處理 AWS IoT Core 傳送給它的連線事件。

   如需在 Lambda 函數中處理事件的相關資訊，請參閱 [定義您的 Lambda 函式](custom-auth-lambda.md)。您可以使用 AWS Lambda 主控台中的測試功能 ([https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)：//) 在函數中硬式編碼測試值，以確保函數正確處理事件。

1. 如果您看到叫用沒有錯誤，但您的裝置無法連接 (或發佈、訂閱和接收訊息)，問題可能是您 Lambda 函數傳回的政策未對您裝置正在嘗試採取的動作提供許可。執行下列步驟，以判斷函數傳回的政策是否發生任何錯誤。

   1. 使用 Amazon CloudWatch Logs Insights 查詢，來掃描短時間內的記錄以檢查是否發生失敗。下列範例查詢會依時間戳記排序事件並尋找失敗。

      ```
      display clientId, eventType, status, @timestamp | sort @timestamp desc | filter status = "Failure"    
      ```

   1. 更新您的 Lambda 函數以記錄其傳回的資料， AWS IoT Core 以及觸發函數的事件。您可以使用這些記錄來檢查函數建立的政策。

1. 如果您看到叫用沒有錯誤，但您的裝置無法連接 (或發佈、訂閱和接收訊息)，另一個原因可能是您 Lambda 函數超過逾時限制。自訂授權方的 Lambda 函數逾時限制為 5 秒。您可以在 CloudWatch 日誌或指標中查看函數持續時間。

## 調查裝置問題
<a name="custom-auth-troubleshooting-investigate"></a>

如果您發現叫用 Lambda 函數沒有問題，函數傳回的政策也沒有問題，請尋找裝置嘗試連線方面的問題。格式不正確的連線請求可能會導致 AWS IoT Core 不觸發您的授權方。在 TLS 和應用程式層可能會同時發生連線問題。

**可能的 TLS 層問題：**
+ 客戶必須在所有自訂身分驗證請求中傳遞主機名稱標頭 (HTTP、MQTT over WebSockets) 或伺服器名稱指示 TLS 延伸 (HTTP、MQTT over WebSockets、MQTT)。在這兩種情況下，傳遞的值必須符合您帳戶的其中一個 AWS IoT Core 資料端點。這些是當您執行下列 CLI 命令時傳回的端點。
  + `aws iot describe-endpoint --endpoint-type iot:Data-ATS`
  + `aws iot describe-endpoint --endpoint-type iot:Data` (適用於舊式 VeriSign 端點)
+ 使用自訂身分驗證進行 MQTT 連線的裝置也須傳遞應用程式層通訊協定交涉 (ALPN) TLS 延伸 (其值為 `mqtt`)。
+ 自訂身分驗證目前僅適用於連接埠 443。

**可能的應用程式層問題：**
+ 如果已啟用簽署 (在您的授權方中，`signingDisabled` 欄位是 false)，請尋找下列簽章問題。
  + 確定您是在 `x-amz-customauthorizer-signature` 標頭或在查詢字串參數中傳遞字符簽章。
  + 確定服務不是簽署字符以外的值。
  + 確定您在標頭或查詢參數中傳遞字符，而此標頭或查詢參數是您在授權方的 `token-key-name` 欄位中所指定的。
+ 確定您在 `x-amz-customauthorizer-name` 標頭或查詢字串參數中傳遞的授權方名稱是有效的，或者您已為您的帳戶定義預設授權方。