Swift から AWS Cognito User Pools を使ってみた


Cognito に新機能 User Pools が追加されたので、Swift から使ってみました。

やったことは下記の通りです。

* Cognito User Pools の設定
* Swift 側の初期設定
* Sign-up実装
* ログイン実装

※[クラスメソッドさんのブログ](http://dev.classmethod.jp/cloud/aws/cognito-user-pool/)にObjective-C版があったので、参考にさせていただきました。

## Cognito User Pools の設定
#### 「Manage your User Pools」を選択し、「Create a User Pool」を選択
![スクリーンショット 2016-04-26 23.18.05.png](https://qiita-image-store.s3.amazonaws.com/0/52494/24fdb284-688b-58e1-d7d3-884e6cbb1a3f.png "スクリーンショット 2016-04-26 23.18.05.png")


#### 「Pool name」に任意の名前を入力し、「Step through settings」を選択
![スクリーンショット 2016-04-26 23.20.31.png](https://qiita-image-store.s3.amazonaws.com/0/52494/5a2c84dc-9ba9-cac7-0525-4adf1693a162.png "スクリーンショット 2016-04-26 23.20.31.png")

#### ユーザごとに取得する属性を選択
私は、email と name を選びました。

![スクリーンショット 2016-04-26 23.22.35.png](https://qiita-image-store.s3.amazonaws.com/0/52494/c1d7cf3b-fb15-00f4-367c-a8be36f84561.png "スクリーンショット 2016-04-26 23.22.35.png")

#### パスワードポリシーを決定

![スクリーンショット 2016-04-26 23.25.12.png](https://qiita-image-store.s3.amazonaws.com/0/52494/8f74089a-35af-e304-99a5-7a76c58daecf.png "スクリーンショット 2016-04-26 23.25.12.png")

#### 他要素認証とメールやSMSのVerifyをするか

私の場合は、メールアドレスを取得しているので、メールののVeryfyのみオンにしました。

![スクリーンショット 2016-04-26 23.26.18.png](https://qiita-image-store.s3.amazonaws.com/0/52494/7562fb32-5122-6d84-fc9d-2cb07a4dfa1c.png "スクリーンショット 2016-04-26 23.26.18.png")

#### アプリを登録

Swift から使用するには、アプリを登録する必要があります。
「Add an app」を選択し、適当なアプリ名を入れてください

![スクリーンショット 2016-04-26 23.29.57.png](https://qiita-image-store.s3.amazonaws.com/0/52494/c3d2a1f3-1062-4863-e568-780f393438b8.png "スクリーンショット 2016-04-26 23.29.57.png")

#### トリガーからのLambda起動

ログイン時やユーザ作成時などにLambdaを起動できます。
ログをDynamoに挿入したりできて便利そうですが、今回は利用しないのでそのまま「Next step」を押してください。
最後に「Create pool」を選択してください。

## Swift 側の初期設定

#### Pod インストール

Cognito 関連のライブラリをインストールする必要があります。

```:Podfile
platform :ios, '8.0'

pod 'AWSCore'
pod 'AWSCognitoIdentityProvider'
```

```
vi Podfile
pod install
```

#### Bridging-Header の追加

下記のファイルを作成し、

```:CognitoUserpoolSample-Bridging-Header.h
#import <AWSCore/AWSCore.h>
#import <AWSCognitoIdentityProvider.h>
```

Build Settings > Swift Conpiler - Code Generation > Objective-C Bridging Header に上のファイルを指定する。

"$(SRCROOT)/$(PROJECT)/CognitoUSerpoolSample-Bridging-Header.h"

## Sign-up実装

まず、Appdelegate.swift で Pool の初期化を行います。

```swift:AppDelegate.swift
let configuration: AWSServiceConfiguration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: nil)
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration

let userPoolConfigration: AWSCognitoIdentityUserPoolConfiguration =
    AWSCognitoIdentityUserPoolConfiguration(clientId: "***1", clientSecret: "***2", poolId: "***3")
    
// 名前をつけておくことで、このプールのインスタンスを取得することができます
AWSCognitoIdentityUserPool.registerCognitoIdentityUserPoolWithUserPoolConfiguration(userPoolConfigration, forKey: "AmazonCognitoIdentityProvider")
```

ClientId と clientSecret は Apps タブから、

![スクリーンショット 2016-04-26 23.47.22.png](https://qiita-image-store.s3.amazonaws.com/0/52494/6ae23a27-fe7d-cd0d-af2c-f2131e9eb947.png "スクリーンショット 2016-04-26 23.47.22.png")

poolId は Pool details から確認できます。

![スクリーンショット 2016-04-26 23.44.48.png](https://qiita-image-store.s3.amazonaws.com/0/52494/3df9733e-4f16-24ec-7515-938e353a0381.png "スクリーンショット 2016-04-26 23.44.48.png")


ユーザ作成部分は、下記のように実装しています。
エラーハンドリングなどはちゃんとできていないです。

```swift:
var pool: AWSCognitoIdentityUserPool?

override func viewDidLoad() {
    super.viewDidLoad()
    
    pool = AWSCognitoIdentityUserPool(forKey: "AmazonCognitoIdentityProvider")
}

@IBAction func pushed(sender: AnyObject) {
    let email: AWSCognitoIdentityUserAttributeType = AWSCognitoIdentityUserAttributeType()
    email.name = "email"
    email.value = self.mail.text!
    
    pool!.signUp(self.name.text!, password: self.password.text!, userAttributes: [email], validationData: nil).continueWithBlock({ task in
        if((task.error) != nil) {
            print(task.error?.code)
        } else {
            print("OK")
        }
        return nil
    })
}
```

## ログイン実装

```
@IBAction func login(sender: AnyObject) {
    let user: AWSCognitoIdentityUser = pool!.getUser(self.userName.text!)
    
    user.getSession(self.userName.text!, password: self.password.text!, validationData: nil, scopes: nil).continueWithBlock({task in
        if((task.error) != nil) {
            print(task.error)
        } else {
            print("OK")
        }
        return nil
    })
}
```
ログインの前に、ユーザのVerifyをしないとエラーになります。
Verify部分は作っていないので、マネージドコンソールから有効化してしまいました。

## まとめ
User Pools 非常に便利ですね！
次はLambda連携部分を触ってみたいと思います。