1
1

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 3 years have passed since last update.

AWS Cognitoでユーザー情報をAWS Lambda(Golang)から取得する方法

Last updated at Posted at 2021-05-11

目的

APIの処理をAPIを叩いてきたユーザー名によって変えたいということがありました。
そこで、Cognitoでオーソライズを行っているLambda関数にて、API Gatewayの認証情報をLambda(Golang)の中で取得する方法を調べました。

結論

以下のコードでユーザー名を取得できます。

func handler(ctx context.Context, apiGWEvent events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {

	ユーザー名取得
	diaryGetter := apiGWEvent.RequestContext.Authorizer["claims"].(map[string]interface{})["cognito:username"].(string)

    /// ...略
}

割と途中のコードとかが謎ですので、以下に解説を載せておきます。(これより単純に取得できる方法がありましたらご教授いただけると幸いです。)

解説

(前提として、LambdaのオーソライザーにCognitoのユーザープールが設定されていることを確認)

まず、events.APIGatewayProxyRequestにはどのようなhttpリクエストを受け取ったのかが格納されます。
ドキュメントを参照すると、

type APIGatewayProxyRequest struct {
    Resource                        string                        `json:"resource"` // The resource path defined in API Gateway
    Path                            string                        `json:"path"`     // The url path for the caller
    HTTPMethod                      string                        `json:"httpMethod"`
    Headers                         map[string]string             `json:"headers"`
    MultiValueHeaders               map[string][]string           `json:"multiValueHeaders"`
    QueryStringParameters           map[string]string             `json:"queryStringParameters"`
    MultiValueQueryStringParameters map[string][]string           `json:"multiValueQueryStringParameters"`
    PathParameters                  map[string]string             `json:"pathParameters"`
    StageVariables                  map[string]string             `json:"stageVariables"`
    RequestContext                  APIGatewayProxyRequestContext `json:"requestContext"`
    Body                            string                        `json:"body"`
    IsBase64Encoded                 bool                          `json:"isBase64Encoded,omitempty"`
}

となっております。
参考:GoDoc package aws/aws-lambda-go/events
参考:AWS Lambda+API Gateway+DynamoDBでCRUD APIを作るのをGolangでやってみた

こちらの、RequestContext構造体には、Authorizer情報がmap[string]interface{}型で入っています。
僕が作成したアプリのdev環境用のCognitoの情報を取得してみると、以下の様になっています。

map[claims:map[aud:tekitoutekitou auth_time:12345678 cognito:username:テスト太郎 event_id:tekitou-d37c-41c9-be67-tekitou exp:Tue May 11 14:18:46 UTC 2021 iat:Tue May 11 13:18:46 UTC 2021 iss:https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-tekitou sub:tekitou-c7e9-4649-ab16-tekitou token_use:id]]

こちらから、claimsキーの中の、cognito:usernameキーがユーザーネームであることがわかります。
最初この構造を見たとき、

diaryGetter := apiGWEvent.RequestContext.Authorizer["claims"]["cognito:username"]

みたいな感じでとれるんじゃないの?
と思ったのですが、これをやろうとすると、

invalid operation: cannot index apiGWEvent.RequestContext.Authorizer["claims"] (map index expression of type interface{})

となってしまいます。

interface型の知識が欠如しておりました。

どんな型の値でも受け取れるinterface{}ですが、interface{}型の引数で受け渡された値は、元の型の情報が欠落しています。
(元の型の値を操作するための関数等を実行できません)
引用:https://blog.y-yuki.net/entry/2017/05/08/000000

元の型の値を操作できないため、辞書型のキーを取り出すという動作ができないっぽいです。
なので、型アサーションをして、取り出す必要がありました。さらにこのdiaryGetterはstring型として扱いたいので、最後も型アサーションをする必要があったということです。

まず、

apiGWEvent.RequestContext.Authorizer["claims"]

を型アサーションでmap[string]interface{}型にして、mapのキーを取り出すという感じです。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?