カスタムオーソライザーを使用してAWS API Gatewayエンドポイントをセキュリティ保護する

AWS Lambda関数(カスタムオーソライザーを含む)を作成・構成してAPIエンドポイントを保護し、認可フローを実装します。これにより、ユーザーはAuth0からAPIへのアクセス取得に必要なアクセストークンを取得できるようになります。

詳細は、AWS API Gatewayにログインして、「AWS Lambdaの概要」をご覧ください。

API GatewayはLambda関数の前にサービスレイヤーを追加することで、セキュリティを拡張し、入力・出力メッセージの変換を管理し、スロットリングや監査などの機能を提供して、Lambdaの機能を拡張します。サーバーレスアプローチにより、スケールアウトやフォールトトレランスなどの懸念事項がコードを実行するコンピュートサービスの責任となるため、運用上の課題が簡素化されます。

カスタムオーソライザーは以下を行います。

  • APIへのアクセス要求のauthorizationヘッダーを介してアクセストークンが渡されたことを確認する。

  • JWKSエンドポイントを介して取得した公開鍵を使用して、アクセストークンのRS256署名を検証する。

  • アクセストークンに必要な発行者issとオーディエンスaudクレームがあることを確認する。

以下の手順でカスタムオーソライザーを使用します。

  1. Auth0 APIを作成する

  2. AWS API Gateway APIをインポートして導入する

  3. カスタムオーソライザーを作成する

  4. カスタムオーソライザーを使用してAPIを保護する

  5. 導入をテストする

署名アルゴリズムの詳細については、「署名アルゴリズム」を参照してください。JWKSの使用に関する詳細は、「JSON Web Key Sets」をご覧ください。

API Gatewayのカスタムオーソライザーの仕組み

Amazonによると、API Gatewayのカスタムオーソライザーは、「OAuthSAMLなどのベアラートークン認証戦略を使用してAPIへのアクセスを制御するために提供するLambda関数」です。

誰か(または何らかのプログラム)がAPIを呼び出そうとするたびに、API GatewayはそのAPI用に構成されたカスタムオーソライザーがあるかどうかを確認します。

APIのカスタムオーソライザーがある場合は、API Gatewayがカスタムオーソライザーを呼び出し、受け取った要求ヘッダーから抽出した認可トークンを提供します。

JWT検証を含むさまざまなタイプの認可戦略を実装して、要求を認可するIAMポリシーを返すことができます。返されたポリシーが無効か、アクセス許可が拒否された場合は、API呼び出しは失敗です。

ポリシーが有効な場合は、APIが返されたポリシーをキャッシュし、それを受信トークンと関連付けて、現在および後続の要求に使用します。ポリシーがキャッシュされる時間は構成できます。デフォルト値は300秒で、キャッシュの最大の長さは3600秒です(この値は0に設定してキャッシュを無効化することも可能です)。

詳細は、AmazonのDeveloper Guideにある「What is Amazon API Gateway?(Amazon API Gatewayとは?)」を参照してください。JWT検証の詳しい情報は、当社の「JSON Web Token」をお読みください。

前提条件

AWSアカウントにサインアップする必要があります。これにより、API GatewayとLambdaを含む、AWS機能へのアクセスが付与されます。新規メンバーは全員、12か月無料プランでAWSへのアクセスを得ることができます。

Auth0 APIを作成する

正常に認可されたアプリケーションによって使用されるAPIを構成します。

  1. [Auth0 Dashboard]>[Applications(アプリケーション)]>[APIs(API)]に移動して、[Create API(APIの作成)]を選択します。

  2. 以下のフィールドに値を入力して、[Create(作成)]を選択します。

    フィールド 説明
    Name(名前) APIのフレンドリー名。Auth0 APIのリストに表示される名前です。
    Identifier(識別子) APIの一意の識別子。この識別子をURL https://your-api-gatewayのような形式にすることをお勧めします。
    JSON Web Token Profile(JSON Webトークンのプロファイル) OAuth2.0のトークンプロファイルまたはダイアレクト(アクセストークン用)。詳細については、「アクセストークンのプロファイル」をお読みください
    署名アルゴリズム 発行されたアクセストークンを署名するために、Auth0で使用したいアルゴリズム。詳細については、「署名アルゴリズム」を参照してください。

新たに作成されたAPIの詳細を確認するには、[Settings(設定)]ビューをご覧ください。

Dashboard - APIの作成 - AWS API Gateway

APIを作成すると、APIと共に使用するM2Mアプリケーションも作成されます。このアプリケーションは、[Machine to Machine Application(M2Mアプリケーション)]ビューの[Authorized(認可済み)]に表示されます。クライアントIDをメモしてください。このチュートリアルのパート3で使用します。

AWS API Gateway APIをインポートして導入する

この手順では以下を行います。

  • APIをAPI Gatewayにインポートする

  • APIインポートをテストする

  • 任意のフロントエンドアプリケーションで使用できるようにAPIを導入する

  • API導入をテストする

Pets APIをインポートして構成する

  1. AWSアカウントにログインし、上部のナビゲーションバーにある[Services(サービス)]ドロップダウンから[API Gateway]コンソールに移動します。

  2. すでにAPIを作成している場合は、API Gatewayコンソールに移動して[Create API(APIの作成)]をクリックします。[Create new API(APIの新規作成)]フォームで[Example API(サンプルAPI)]を作成することもできます。初めてAPI GatewayでAPIを作成する場合は、以下の画面が表示されます。[Get Started(はじめる)]をクリックして続けます。

    AWS API Gateway - Get Started

    API Gatewayに歓迎するポップアップメッセージが表示されます。[OK]をクリックして続行します。

  3. [Create new API(APIの新規作成)]フォームでは、[Example API(サンプルAPI)]がデフォルトで選択されており、エディターに定義されたサンプルAPIがあります。本チュートリアルでは以後このAPIを使用するので、[Import(インポート)]をクリックしてAPI作成プロセスを開始します。

    AWS API Gateway - Example API

    インポートが終わったら、APIが作成され、提供されたデータが読み込まれたことを示すメッセージが表示されます。APIにはすでにメソッド(GETPOST)が関連付けられています。リソースツリーでメソッド名をクリックすると、メソッドの詳細表示やその構成の変更、メソッドの呼び出しテストが行えます。

    AWS API Gateway - Resources Tree

APIをテストする

APIをテストするには、/petsPOSTをクリックします。すると、[Method Execution(メソッドの実行)]画面が表示され、POSTメソッドの構造と動作の概要を確認できます。

  • [Method Request(メソッド要求)][Method Response(メソッド応答)]:APIとフロントエンドのインターフェイス

  • [Integration Request(統合要求)][Integration Response(統合応答)]:APIとバックエンドのインターフェイス

この領域を使用してAPIをテストできます。

  1. (ページ中程の[Client(クライアント)]にある)[Test(テスト)]をクリックします。/pets - POST - Method Testページにリダイレクトされます。ページの下までスクロールし、以下のスニペットを[Request Body(要求本文)]として入力します。

    {"type": "dog", "price": 249.99}

    Was this helpful?

    /
    要求本文は、データベースに追加したいペットの属性とそのペットの費用を示します。

    AWS API Gateway - Request Body
  2. [Test(テスト)]をクリックして続行します。ページの右側にテストの結果が表示されます。

    AWS API Gateway - Test Results

APIを導入する

先ほど完了したテストは、API Gatewayコンソールを用いて行われました。APIを別のアプリケーションと使用するには、APIをステージに導入する必要があります。

  1. [Actions(アクション)]メニューで[Deploy API(APIの導入)]を選択します。

  2. 以下の値を入力して、[Deploy(導入)]をクリックします。

    パラメーター
    Deployment stage(導入ステージ) [New Stage]を選択
    Stage name(ステージ名) ステージの名前を指定します
    Stage description(ステージの説明) ステージの説明を入力します
    Deployment description(デプロイメントの説明) APIデプロイメントの説明を入力します

導入をテストする

APIが正常に導入されたら、[Test Stage Editor(テストステージエディター)]にリダイレクトされます。この時点で、APIが正しく導入されているかをテストすることができます。

  1. [Test Stage Editor(テストステージエディター)]画面の上部には、Invoke URL(呼び出しURL)の青いバナーが表示されます。これは、APIのGETエンドポイントを呼び出すために使用するURLです。リンクをクリックしてブラウザーでGET / method要求を送信します。これにより、以下のような成功応答が返されるはずです。

    AWS API Gateway - Deploy Test Response
  2. [Stages(ステージ)]ページで、[Test(テスト)]のツリーを展開します。/pets/{petId}GETをクリックします。

    AWS API Gateway - Get Pet ID
  3. 画面上部の青いバナーにInvoke URL(呼び出しURL)が表示されます。その末尾部分の{petID}は、パス変数を表します。この変数を1に置き換え、ブラウザーを使って新しいURLに移動します。以下のJSONペイロードのHTTP 200要求を受信するはずです。

    {
      "id": 1,
      "type": "dog",
      "price": 249.99
    }

    Was this helpful?

    /

カスタムオーソライザーを作成する

以上の手順で、API Gatewayによって管理された完全に機能するAPIができたので、次に、適切な認可を得たユーザーだけがAPIのバックエンドにアクセスできるようにAPIを保護します。

API Gatewayのカスタム要求オーソライザーを使用して、OAuth 2.0やSAMLなどのベアラートークン認可戦略でAPIを認可します。各受信要求で以下が行われます。

  1. API Gatewayが、カスタムオーソライザーが適切に構成されていることを確認します。

  2. API Gatewayが、認可トークンを使用してカスタムオーソライザー(Lambda関数)を呼び出します。

  3. 認可トークンが有効な場合は、カスタムオーソライザーが適切なAWSのIDおよびアクセス管理(IAM)ポリシーを返します。

  4. API Gatewayが、手順3で返されたポリシーを使用して要求を認可します。

カスタムオーソライザーを準備する

Auth0発行トークンをサポートするサンプルのカスタムオーソライザーをダウンロードできます。その後、自身の環境でカスタムオーソライザーが動作するようにファイルをカスタマイズする必要があります。

  1. ダウンロードしたサンプルファイル入りのフォルダーを任意の場所で解凍し、コマンドラインを使用してフォルダーに移動します。

  2. サンプルフォルダー内でnpm installを実行し、導入に必要なNode.jsパッケージをインストールします。後の手順でAWSにアップロードするバンドルにこれらのファイルを含める必要があります。

  3. .envファイルを使ってローカル環境を構成します。cp .env.sample .envを使って.env.sampleファイルをコピー(すると同時に名前を.envに変更)できます。以下の項目を変更します。

    パラメーター
    TOKEN_ISSUER トークンの発行者。Auth0がトークン発行者の場合は、https://{yourDomain}/を使用する。末尾のスラッシュを必ず付けてください。
    JWKS_URI JWKSエンドポイントのURL。Auth0がトークン発行者の場合は、https://{yourDomain}/.well-known/jwks.jsonを使用する
    AUDIENCE 上の「Auth0 APIを作成する」セクションで作成したAPIのidentifierの値。
    たとえば、.envファイルのテキストは、完了すると以下のようになります。
    JWKS_URI=https://{yourDomain}/.well-known/jwks.json
    AUDIENCE=https://your-api-gateway
    TOKEN_ISSUER=https://{yourDomain}/

    Was this helpful?

    /

カスタムオーソライザーをローカルでテストする

有効なJWTアクセストークンを取得する取得方法は複数あり、選択する方法はアプリケーションの種類、信頼レベル、または全体的なエンドユーザーのエクスペリエンスに応じます。詳細は、「アクセストークンを取得する」をお読みください。

  1. APIのテストトークンを取得するには、[Auth0 Dashboard]>[Applications(アプリケーション)]>[APIs(API)]に移動して、APIを選び、[Test(テスト)]を選択します。

  2. トークンを含むevent.jsonファイルをローカルに作成します。サンプルファイルをコピーできます(cp event.json.sample event.jsonを実行します)。ACCESS_TOKENを自身のJWTトークンに置き換え、methodArnをAPIのGETメソッドの適切なARN値に置き換えます。

methodArnを取得するには以下を行います。

  1. API Gatewayコンソールで[PetStore]APIを開きます。

  2. 左側のナビゲーションで[Resources(リソース)]を選択します。

  3. 中央の[Resources(リソース)]パネルでリソースツリーを展開します。/petsの下の[GET]を選択します。

  4. [Method Request(メソッド要求)]欄に[ARN]が表示されます。

  5. npm testを使用してテストを実行します。

lambda-localパッケージを使用して、トークンを用いてカスタムオーソライザーをテストします。テストに成功すると、以下のように表示されます。

Message
------
{
    "principalId": "C8npTEMVnBrILsBTI91MOh6dfuZbPVAU@clients",
    "policyDocument": {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": "execute-api:Invoke",
                "Effect": "Allow",
                "Resource": "arn:aws:execute-api:us-east-1:1234567890:apiId/stage/method/resourcePath"
            }
        ]
    },
    "context": {
        "scope": "FULL_LIST_OF_SCOPES"
    }
}

Was this helpful?

/

Effectの値がAllowの場合は、オーソライザーがAPI Gatewayへの呼び出しを許可していることを表します。

詳細は、NPMの「Lambda-local」を参照してください。

IAMロールを作成する

IAMロールにはLambda関数を呼び出すために必要なアクセス許可があります。カスタムオーソライザーに取りかかる前に、API Gatewayがアクセス要求を受け取るたびにカスタムオーソライザーを呼び出すことのできるIAMロールを作成する必要があります。

  1. AWSにログインし、[IAM Console(IAMコンソール)]に移動します。左側のナビゲーションで[Roles(ロール)]を選択します。

  2. [Create new role(ロールの新規作成)]を選択します。

  3. [AWS service(AWSサービス)][AWS Lambda]行を選び、[Next:Permissions(次へ:アクセス許可)]を選択します。

  4. [Attach permissions policy(アクセス許可ポリシーのアタッチ)]画面で、[AWSLambdaRole]を選択します。フィルターを使用してオプションのリストを絞り込むことができます。[Next:Tags(次へ:タグ)][Next:Review(次へ:確認)]の順に選択して続行します。

  5. [Review(確認)]画面で、Auth0Integrationなどの[Role name(ロール名)]を入力します。他のフィールドはそのままにします。[Create role(ロールの作成)]を選択します。

  6. AWSがロールを作成し終えたら、IAMの[Roles(ロール)]ページにリダイレクトされます。新しいロールを選択します。

  7. 先ほど作成したロールの[Summary(サマリー)]ページで[Trust relationships(信頼関係)]ビューを選択します。

  8. [Edit trust relationship(信頼関係の編集)]を選択して、[Policy Document(ポリシードキュメント)]フィールドに以下のJSONスニペットを入力します。

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

    Was this helpful?

    /

  9. [Update Trust Polic(信頼ポリシーの更新)]をクリックします。

  10. [Summary(サマリー)]ページにリダイレクトで戻されます。後で使用するために[Role ARN(ロールARN)]値をコピーしておきます。

    undefined

Lambda関数を作成してカスタムオーソライザーを導入する

以上の手順で、自身の環境用にカスタムオーソライザーを構成し、動作することをテストしたので、次はこれをAWSに導入しましょう。

  1. npm run bundleを実行して、AWSにアップロードできるバンドルを作成します。これにより、AWS Lambdaが必要とするソース、構成、ノードモジュールを含むcustom-authorizer.zipバンドルが生成されます。

  2. Lambdaコンソールに移動して、[Create function(関数の作成)]をクリックします。

  3. [Select blueprint(ブループリントの選択)]ページで[Author from scratch(一から作成)]をクリックして空の関数を作成します。[Basic information(基本的な情報)]で以下のパラメーターの値を入力します。

    パラメーター
    Name(名前) Lambda関数の名前。例:jwtRsaCustomAuthorizer
    Description(説明) Lambda関数の説明(任意)
    Runtime(ランタイム) Node.js 10.xを選択

  4. [Create Function(関数の作成)]をクリックして続行します。

  5. 関数の[Configuration(設定)]ページで[Function Code(関数コード)]セクションまで下にスクロールします。

  6. [Code entry type(コード入力タイプ)][Upload a .ZIP file(.ZIPファイルのアップロード)]を選択します。

  7. [Upload(アップロード)]をクリックして、先ほど作成したcustom-authorizer.zipバンドルを選択します。

  8. 次に、以下の3つの[Environment variables(環境変数)]を作成します。この情報は.envファイルの情報と同じであることに注意してください。

    パラメーター
    TOKEN_ISSUER トークンの発行者。Auth0がトークン発行者の場合は、https://{yourDomain}/を使用する
    JWKS_URI JWKSエンドポイントのURL。Auth0がトークン発行者の場合は、https://{yourDomain}/.well-known/jwks.jsonを使用する
    AUDIENCE 手順1で作成したAPIのidentifierの値。

  9. [Execution role(実行ロール)]セクションで、[Use an existing role(既存ロールを使用)]を選択してから、以前[Existing role(既存ロール)]として作成したIAMロールを選びます。

  10. [Basic settings(基本設定)][Timeout(タイムアウト)][30]秒に設定します。

  11. [Save(保存)]をクリックします。

  12. 作成したLambda関数をテストするため、右上の[Test(テスト)]をクリックします。

  13. event.jsonファイルの内容を[Configure test event(テストイベントの設定)]フォームにコピーします。デフォルトの「Hello World」イベントテンプレートを使用できます。

  14. [Create(作成)]をクリックします。

  15. これを選択し、[Test(テスト)]をクリックして実行します。テストに成功したら、[Execution result: succeeded(実行結果:成功)]と表示されます。出力画面を展開すると、ローカルテストに成功したときと似たようなメッセージが表示されるはずです。

    undefined

API Gatewayのカスタムオーソライザーを構成する

  1. API Gatewayコンソールに戻り、先ほど作成したPetStore APIを開きます。

  2. 左側のナビゲーションから[Authorizers(オーソライザー)]を開き、[Create New Authorizer(オーソライザーの新規作成)]を選択してから、以下のパラメーターを設定し、[Create(作成)]をクリックします。

    パラメーター
    名前 jwt-rsa-custom-authorizer
    タイプ Lambdaを選択する
    Lambdaのリージョン 前に作成したLambda関数のリージョンを使用する
    Lambda関数 jwtRsaCustomAuthorizer
    Lambdaの実行ロール 上でコピーしたIAMロールARN
    Lambdaのイベントペイロード **[Token(トークン)]**を選択する
    トークンのソース Authorization
    トークンの検証 ^Bearer [-0-9a-zA-z\.]*$
    TTL(秒) 3600

  3. AWSがオーソライザーを作成し、ページが更新されたら、[Test(テスト)]をクリックし、先ほど使用したAuth0トークン(Bearer ey...)を入力することで、オーソライザーをテストします。テストに成功すると、以下のような応答が表示されます。

    undefined

カスタムオーソライザーを使用してAPIを保護する

APIのエンドポイントを保護する方法については、Amazon API GatewayのDeveloper Guideにある、「Use API Gateway Lambda Authorizers(API Gateway Lambdaオーソライザーを使用する)」の記事を参照してください。

カスタムオーソライザーを使用するためにAPI Gatewayリソースを構成する

  1. AWSにログインし、[API Gateway Console(API Gatewayコンソール)]に移動します。

  2. 本チュートリアルの手順2で作成した[PetStore] APIを開きます。中央にある[Resource(リソース)]ツリーの/petsリソースで、[GET]メソッドを選択します。

    undefined
  3. [Method Request(メソッド要求)]を選択します。

  4. [Settings(設定)][Authorization(認可)]の右にある鉛筆手順3で作成したjwt-rsa-custom-authorizerカスタムオーソライザーを選択します。

  5. チェックマークアイコンをクリックして、選んだカスタムオーソライザーを保存します。[API Key Required(APIキーを必須にする)]フィールドがfalseになっていることを確認します。

APIを導入する

変更内容を公開するため、APIを導入します。

  1. [Actions(アクション)]メニューで[Deploy API(APIの導入)]を選択します。

  2. 以下の値を入力して、[Deploy(導入)]をクリックします。

    パラメーター
    Deployment stage(導入ステージ) [New Stage]を選択
    Stage name(ステージ名) ステージの名前を指定します
    Stage description(ステージの説明) ステージの説明を入力します
    Deployment description(デプロイメントの説明) APIデプロイメントの説明を入力します

成功したら、[Test Stage Editor(テストステージエディター)]にリダイレクトされます。導入をテストする際に必要になるので、上部の青いバナーに表示されているInvoke URL(呼び出しURL)をメモします。

導入をテストする

導入をテストするため、先ほどの手順でメモしたInvoke URL(呼び出しURL)GET呼び出しを行います。このテストに失敗した場合は、JWTアクセストークンを正しく取得していることを確認してください。

詳細は、「アクセストークンを取得する」でご覧ください。


curl --request GET \
  --url https://%7ByourInvokeUrl%7D/pets

Was this helpful?

/
var client = new RestClient("https://%7ByourInvokeUrl%7D/pets");
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);

Was this helpful?

/
package main

import (
	"fmt"
	"net/http"
	"io/ioutil"
)

func main() {

	url := "https://%7ByourInvokeUrl%7D/pets"

	req, _ := http.NewRequest("GET", url, nil)

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}

Was this helpful?

/
HttpResponse<String> response = Unirest.get("https://%7ByourInvokeUrl%7D/pets")
  .asString();

Was this helpful?

/
var axios = require("axios").default;

var options = {method: 'GET', url: 'https://%7ByourInvokeUrl%7D/pets'};

axios.request(options).then(function (response) {
  console.log(response.data);
}).catch(function (error) {
  console.error(error);
});

Was this helpful?

/
#import <Foundation/Foundation.h>

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://%7ByourInvokeUrl%7D/pets"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"GET"];

NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                if (error) {
                                                    NSLog(@"%@", error);
                                                } else {
                                                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                    NSLog(@"%@", httpResponse);
                                                }
                                            }];
[dataTask resume];

Was this helpful?

/
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://%7ByourInvokeUrl%7D/pets",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "GET",
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

Was this helpful?

/
import http.client

conn = http.client.HTTPSConnection("")

conn.request("GET", "%7ByourInvokeUrl%7D/pets")

res = conn.getresponse()
data = res.read()

print(data.decode("utf-8"))

Was this helpful?

/
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://%7ByourInvokeUrl%7D/pets")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body

Was this helpful?

/
import Foundation

let request = NSMutableURLRequest(url: NSURL(string: "https://%7ByourInvokeUrl%7D/pets")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()

Was this helpful?

/