0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

APIGatewayの認可にCognitoのトークンを使用し、JavaScriptから実行する

Last updated at Posted at 2023-03-02

はじめに

ログイン機能のあるWEBサービスで利用されるAPIで、APIに認可を設定しなかった場合、APIのURLさえわかれば、どのユーザでもAPIが実行できてしまいます。
そのため、ログインユーザのみ許可されるAPIを作成する場合、適切な認可を設計する必要があります。

今回はAWS Cognitoでログインしているユーザのみ、APIGatewayで作成されたAPIが許可される設定をご紹介します。

※Cognitoは構築されている前提です。Cognitoの構築については以下の記事をご覧ください。
https://qiita.com/haruya_hamasaki/items/b4257ec4498185fa38a1
https://qiita.com/haruya_hamasaki/items/92d5972e46768a902104

API Gateway の設定

構築に使用するSAMテンプレートの例です。

template.yaml
MyMovieAPIGateway:
    Type: AWS::Serverless::Api
    Properties:
      AccessLogSetting:
        DestinationArn: !GetAtt ApigwLogDeliveryStream.Arn
        Format: '{ "requestId":"$context.requestId", "ip": "$context.identity.sourceIp", "caller":"$context.identity.caller", "user":"$context.identity.user","requestTime":"$context.requestTime", "httpMethod":"$context.httpMethod","resourcePath":"$context.resourcePath", "status":"$context.status","protocol":"$context.protocol", "responseLength":"$context.responseLength" }\n'
      StageName: api
      ApiKeySourceType: HEADER
      EndpointConfiguration:
        Type: REGIONAL
      DefinitionBody:
        swagger: "2.0"
        info:
          description: "get userid"
          version: "1.0"
          title: "mymovie"
        basePath: "/api"
        schemes:
        - "https"
        paths:
          /movie:
            delete:
              consumes:
              - "application/json"
              produces:
              - "application/json"
              parameters:
              - name: "user_id"
                in: "query"
                required: false
                type: "string"
              - name: "title"
                in: "query"
                required: false
                type: "string"
              responses:
                "200":
                  description: "200 response"
                  schema:
                    $ref: "#/definitions/Empty"
                "400":
                  description: "400 response"
                "500":
                  description: "500 response"
              security:
              - MyMovie: []
              - api_key: []
              x-amazon-apigateway-integration:
                httpMethod: "POST"
                uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DelMovFunction.Arn}/invocations"
                responses:
                  default:
                    statusCode: "200"
                  ".*\"statusCode\": 500,.*":
                    statusCode: "500"
                  ".*\"statusCode\": 400,.*":
                    statusCode: "400"
                requestTemplates:
                  application/json: "{\n  \"user_id\": \"$input.params('user_id')\",\n  \"\
                    title\": \"$input.params('title')\"\n}"
                passthroughBehavior: "when_no_templates"
                contentHandling: "CONVERT_TO_TEXT"
                type: "aws"
        securityDefinitions:
          api_key:
            type: "apiKey"
            name: "x-api-key"
            in: "header"
          MyMovie:
            type: "apiKey"
            name: "Authorization"
            in: "header"
            x-amazon-apigateway-authtype: "cognito_user_pools"
            x-amazon-apigateway-authorizer:
              providerARNs:
              - !GetAtt MyMovieUserPool.Arn
              type: "cognito_user_pools"

上記だと余計な記載があり過ぎるので、認可の部分を抜粋します。

以下で、MyMovieと命名したオーソライザーを定義。

          MyMovie:
            type: "apiKey"
            name: "Authorization"
            in: "header"
            x-amazon-apigateway-authtype: "cognito_user_pools"
            x-amazon-apigateway-authorizer:
              providerARNs:
              - !GetAtt MyMovieUserPool.Arn
              type: "cognito_user_pools"

以下で、オーソライザーを認可に設定しています。

              security:
              - MyMovie: []

この設定で、APIのリクエストヘッダーにCognitoから付与されたトークンがないと、APIの実行が許可されない設定となりました。

JavaScript 

今回はAPIをJavaScriptから実行します。
まず、ログインしているCognito UserPoolを指定し、情報を変数に格納します。

// ユーザープールの設定
var user_pool_id = "{USER_POOL_ID}"
var client_id = "{CLIENT_ID}"
const poolData = {
  UserPoolId : user_pool_id,
  ClientId : client_id
};
const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
const cognitoUser = userPool.getCurrentUser();

ログインユーザ情報から、トークンを抜き出します。

cognitoUser.getSession(function(err, session) {
    id_token = session["idToken"]["jwtToken"]
});

ヘッダーにトークンを入れて、APIを実行します。
ログインユーザであれば、トークンが取得できているはずなので、APIが成功します。
逆にログインユーザ以外は失敗します。

fetch(`https://{DOMAIN}/api/movie?user_id=${user_id}&title=${title}`,{
  //ヘッダーにトークンを入れる
  headers: {
    Authorization: id_token
  },
  //HTTPメソッド
  method: "delete"
})
.then(response => {
  if (!response.ok) {
    //失敗時の処理
  } else {
    //成功時の処理
  }
})  
.catch(error => {
  //失敗時の処理
});

おまけ

本記事の機能は以下のサービスで利用されています。
気になった方は、お気軽にサービスも利用くださると大変嬉しいです。
GitHubには、今回紹介したコードが実際に使われている形であります。

観た映画を登録、管理できるサービス MyMovie

映画一覧.png

サービスURL : mymovie.jp
GitHub(アプリ) : github.com/hamasakiharuya/mymovie
GitHub(CloudFormation/SAM) : github.com/hamasakiharuya/sam-mymovie

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?