AWS日記⑤ (Cognito)

# はじめに
今回はCognitoを利用して簡易なアカウントページを作成します。
サインアップする際にはメールアドレス認証する方法をとります。

# 準備
Cognitoのユーザープールを作成します。
[Lambda , API Gatewayの準備をします。]
(https://qiita.com/tanaka_takurou/items/3f93295de6cff060ec09)

[参考資料]
[はじめてのAWS Cognito！！](https://qiita.com/katekichi/items/dbf279077db6a7b597fc)
[チュートリアル: ユーザープールの作成](https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/tutorial-create-user-pool.html)

# WEBページ・API作成
GO言語のAWS Lambda関数ハンドラー aws-lambda-go を使用してHTMLやJSONを返す処理を作成します。
また、Cognito を使用するため aws-sdk-go を利用します。

[参考資料]
[AWS SDK for Go API Reference](https://docs.aws.amazon.com/sdk-for-go/api/service/cognitoidentityprovider/)
[golangでCognito認証（ただしSecure Remote Password(SRP)プロトコルではない）](https://qiita.com/cobachan/items/9ec379bbcc28a9d3d08a)
[Amazon Cognitoで発生する例外(Exception)をまとめてみた](https://qiita.com/yukitaka13-1110/items/99197466c1ba88f0f8d3)
[AWS Cognitoを実践で使うときのハマりどころ](https://qiita.com/aki/items/e35e1bea8c27cfab5e9e)


##### サインアップするには SignUp を使う。

```golang:main.go
func signup(name string, pass string, mail string) error {
        svc := cognitoidentityprovider.New(session.New(), &aws.Config{
                Region: aws.String("ap-northeast-1"),
        })
        ua := &cognitoidentityprovider.AttributeType {
                Name: aws.String("email"),
                Value: aws.String(mail),
        }
        params := &cognitoidentityprovider.SignUpInput{
                Username: aws.String(name),
                Password: aws.String(pass),
                ClientId: aws.String(clientId),
                UserAttributes: []*cognitoidentityprovider.AttributeType{
                        ua,
                },
        }

        _, err := svc.SignUp(params)
        if err != nil {
                return err
        }
        return nil
}
```

##### サインアップを認証するには ConfirmSignUp を使う。

```golang:main.go
func confirmSignup(name string, confirmationCode string) error {
        svc := cognitoidentityprovider.New(session.New(), &aws.Config{
                Region: aws.String("ap-northeast-1"),
        })

        params := &cognitoidentityprovider.ConfirmSignUpInput{
                Username: aws.String(name),
                ConfirmationCode: aws.String(confirmationCode),
                ClientId: aws.String(clientId),
        }

        _, err := svc.ConfirmSignUp(params)
        if err != nil {
                return err
        }
        return nil
}
```

##### サインインするには InitiateAuth を使う。

```golang:main.go
func login(name string, pass string)(string, error) {
        svc := cognitoidentityprovider.New(session.New(), &aws.Config{
                Region: aws.String("ap-northeast-1"),
        })

        params := &cognitoidentityprovider.InitiateAuthInput{
                AuthFlow: aws.String("USER_PASSWORD_AUTH"),
                AuthParameters: map[string]*string{
                        "USERNAME": aws.String(name),
                        "PASSWORD": aws.String(pass),
                },
                ClientId: aws.String(clientId),
        }

        res, err := svc.InitiateAuth(params)
        if err != nil {
                return "", err
        }
        return aws.StringValue(res.AuthenticationResult.AccessToken), nil
}
```

##### ユーザー情報を取得するには GetUser を使う。

```golang:main.go
func getuser(token string)(string, error) {
        svc := cognitoidentityprovider.New(session.New(), &aws.Config{
                Region: aws.String("ap-northeast-1"),
        })

        params := &cognitoidentityprovider.GetUserInput{
                AccessToken: aws.String(token),
        }

        res, err := svc.GetUser(params)
        if err != nil {
                return "", err
        }
        return aws.StringValue(res.Username), nil
}
```


##### パスワードを変更するには ChangePassword を使う。

```golang:main.go
func changePass(token string, pass string, newPass string) error {
        svc := cognitoidentityprovider.New(session.New(), &aws.Config{
                Region: aws.String("ap-northeast-1"),
        })

        params := &cognitoidentityprovider.ChangePasswordInput{
                AccessToken:      aws.String(token),
                PreviousPassword: aws.String(pass),
                ProposedPassword: aws.String(newPass),
        }

        _, err := svc.ChangePassword(params)
        if err != nil {
                return err
        }
        return nil
}
```

##### サインアウトするには GlobalSignOut を使う。

```golang:main.go
func logout(token string) error {
        svc := cognitoidentityprovider.New(session.New(), &aws.Config{
                Region: aws.String("ap-northeast-1"),
        })
        o_params := &cognitoidentityprovider.GlobalSignOutInput{
                AccessToken: aws.String(token),
        }
        _, err := svc.GlobalSignOut(o_params)
        if err != nil {
                return err
        }
        return nil
}
```


今回は、ページ表示とAPIの API Gatewayを別々に作成し、APIのメソッドはPOSTに設定しました。
[作成したLambda 関数、テンプレート](https://github.com/tanaka-takurou/serverless-account-page-go)


# 終わりに
今回は、メールアドレスでサインアップする方法をとりました。
他にも様々な使い方があるので今後試していきたいと思います。
[AWS CognitoにGoogleとYahooとLINEアカウントを連携させる](https://qiita.com/poruruba/items/189945dc64edfe1f2464)