【自動ログイン機能】機種変更でアカウントを引継ぐ方法

# はじめに
ふとこんなことを考えました。最近流行の「自動ログイン機能」を実装しているアプリを使っていて、もし機種変更をしたら、アカウントはどうやって引き継がれるんだろう？

![アプリのお引越し.png](https://qiita-image-store.s3.amazonaws.com/0/112032/7a360f40-64a2-b1d9-ec8f-1b7871a404a1.png)

自動ログインって、ユーザーにはログイン/ログアウトを意識させずに行うので、
機種変更したらアカウントの引継ぎってどうなるの？と思ったわけです。
そこで考えてみました！！！

ちょうど[ニフティクラウド mbile backend (以下mBaaS)](http://mb.cloud.nifty.com/about.htm)を使って「自動ログイン機能」自体の実装は出来ていたので、これを使って実現してみることにしました。

> __参考__
> 「自動ログイン機能」についてはこちらに記事があります▼
> [__[Qiita]サーバー開発を一切せずに自動ログイン機能を実現してみた__](http://qiita.com/natsumo/items/8edfb3b2b9d11d4a1931)

ちなみに、自分はサーバーエンジニアではないので、[mBaaS](http://mb.cloud.nifty.com/about.htm) をフル活用して、サーバー周りの開発一切なしで作っています◎（ついでに無料で）

## 機能はできたぞ！ただ…ロジックの説明が中々難しい…

この機能を実現したとき、説明するのにとても苦労しました；
__アカウントの移り変わり__ を言葉で伝えるのはもちろん、絵に描いて説明するのもなかなか苦をしました…そこでアカウント自体を図にしてみました。（ちゃんと伝わるといいなー。）

# 本編に進む前に<br>前提条件と事前知識についての話

## 自動ログイン機能について
「自動ログイン」機能は以下のような処理を行っています。

* __アプリ起動時に端末固有のUDID（ユニークデバイスID）を取得__し、それを__「userName（ユーザー名）/password（パスワード）」としてログイン__を行う
* acl（参照権限）設定を以下のようにする
 * __read__（読み込み）権限 → __public true__ （全員許可）
 * write（書き込み）権限 → user true （会員のみ許可）

例）端末固有のUDIDが「UUID_A」の場合
以下のようにmBaaS上にアカウントを作成し、アプリの裏側で処理をします。
![図0.png](https://qiita-image-store.s3.amazonaws.com/0/112032/9179dbd0-a14d-8f35-9b37-d97ed5c74996.png)

※__ユーザーからはアカウントの存在は見えません！__


> __参考__
> イメージが沸きにくい場合はサンプルを動かしてみましょう▼
> [__[Qiita]サーバー開発を一切せずに自動ログイン機能を実現してみた__](http://qiita.com/natsumo/items/8edfb3b2b9d11d4a1931)


## 前提条件
以下の前提条件の下、考えていきます。

* 前述の「[自動ログイン機能について](#自動ログイン機能について)」の自動ログインを使用します
 * ただし、起動時に引継ぎをするか、そのまま自動ログインをしてアプリを始めるのか、選択できるようにしておきます。
* 端末Aから端末Bへ機種変更した場合について考えます
* 端末AのUDIDを「UUID_A」、端末BのUDIDを「UUID_B」とします
* __端末Aで使用していたアカウントを、端末Bでも引き継いで利用します__

# 本編：「自動ログイン」アプリのアカウント引越し方法
次の３段階に分けて解説します。

* [《処理1》移行前：「引継ぎ認証を行うための情報を設定する」](#《処理1》移行前：「引継ぎ認証を行うための情報を設定する」)
* [《処理2》移行中：「引継ぎの認証と新しい端末の情報を会員情報に設定する」](#《処理2》移行中：「引継ぎの認証と新しい端末の情報を会員情報に設定する」)
* [《処理3》移行後：「新しい端末の情報で会員を検索してログインを行う」](#《処理3》移行後：「新しい端末の情報で会員を検索してログインを行う」)

その前にゴールをイメージしておきましょう！

## アカウント引継ぎイメージ（ゴール）
端末Aで使っていたアカウントを引き継いでそのまま使います。この方法では、まず__端末間の引継ぎ認証__を行い、__アカウント上に引継ぎ先のUUIDを登録する__しています。登録したUUIDを持って検索をし、__userNameを取得することで元のユーザーとしてログイン__できるため、引継ぎが実現できます。

![図7.png](https://qiita-image-store.s3.amazonaws.com/0/112032/e514977d-c85c-5758-6562-2c35e0e01262.png)

では詳細見てみましょう！

## 《処理1》移行前：「引継ぎ認証を行うための情報を設定する」
### ユーザー側の動作
* 引継ぎ元の端末Aでアプリを起動（自動ログイン）して、「メールアドレス」と「移行用の一時パスワード」を設定する

＜画面イメージ＞
![図5.png](https://qiita-image-store.s3.amazonaws.com/0/112032/c39da3be-31a4-381d-99cd-156155212665.png)

### アプリ側の処理
以下のようにしてアカウント移行時の認証のための情報を設定します。

* 端末Aで自動ログインした状態なので、UserNameが「UUID_A」のアカウントでログインされた状態にある
* ユーザーが登録した「メールアドレス」と「移行用の一時パスワード」を、それぞれアカウントの「mailAddress」「temporaryPass」フィールドに登録する
* ↑と同時に、アカウント移行中であることを認識するために「flag」フィールドに「true」を設定しておく

＜アカウントイメージ＞
![図1.png](https://qiita-image-store.s3.amazonaws.com/0/112032/54d3ddf5-9d98-c3c1-4235-7d64d3f68240.png)


## 《処理2》移行中：「引継ぎの認証と新しい端末の情報を会員情報に設定する」
### ユーザー側の動作
* 引継ぎ先の端末Bでアプリをダウンロードする
* ダウンロードしたアプリを起動してアカウントの引継ぎ処理として、「メールアドレス」と「移行用の一時パスワード」を入力する

＜画面イメージ＞
![図6.png](https://qiita-image-store.s3.amazonaws.com/0/112032/f0997491-3df8-3939-0d83-48a40720cbfa.png)

### アプリ側の処理
以下のように処理を行いアカウントの引継ぎを完了させます。

* 端末Bで入力された「mailAddress（メールアドレス）」と「temporaryPass（移行用の一時パスワード）」を元にmBaaS上のユーザーを検索します
 * このとき、引継ぎ設定の有無のチェックのために「flag = true」であることも条件として検索します。
* 検索してヒットしたユーザー（端末Aで使用していたもの）でログインを行います
 * 「password」は検索し開示することは出来ない仕様ですが、「userName」と同じもので設定しているのでログインすることができます
* ログイン後、端末のUDID（UUID_B）を取得し、「transferId」としてを設定します
 * ログインをすることで書き込みが有効になります
 * このとき、引継ぎ設定完了のため「flag = false」も設定します

これでUUID_AのアカウントにUUID_Bを紐付けることが出来ました！

＜アカウントイメージ＞
![図2.png](https://qiita-image-store.s3.amazonaws.com/0/112032/339386b7-87b6-0f56-adf7-84109ac0f89f.png)


## 《処理3》移行後：「新しい端末の情報で会員を検索してログインを行う」
### ユーザー側の動作
* 引継ぎ先の端末Bでアプリを起動し、利用開始します
 * 引継ぎ元の端末Aで使用していたアカウントの情報を引き継いでアプリを使用できます

### アプリ側の処理
以後、ログインはすべて次の処理を通して行うようになります。

* 端末のUDIDを取得し、それを元にmBaaS上のユーザーを検索します
* 検索してヒットしたユーザーのuserNameを取得し、ログインを行います 

＜アカウントイメージ＞
![図3.png](https://qiita-image-store.s3.amazonaws.com/0/112032/00249e24-3520-962f-b34b-1d1f0e3376f9.png)

# おわりに
mBaaSを使った実現方法としてはこんな感じでいかがでしょうか？
細かい部分はぜひサンプルアプリを作りましたので、ご利用ください！

|GitHub|動作環境|
|:----------------:|:----------------:|
|[__SwiftAdvanceLoginApp__](https://github.com/natsumo/SwiftAdvanceLoginApp/archive/master.zip)|Xcode ver. 8.2.1<br>mBaaS iOS SDK Ver. 2.3.4|

ただ、このやり方だとAPIリクエスト数の消費がどうしても抑えられなかったんです…
あとはセキュリティ的に大丈夫かな？と思ったり…
まだまだです…orz

もっと効率的で良い方法があれば、ぜひコメントをお待ちしています('▼'*ﾉｼ！！

# 参考
* mBaaSについては[__こちら__](http://mb.cloud.nifty.com/about.htm)
* 自動ログインについては[__こちら__](https://github.com/natsumo/SwiftAutoLoginApp)

ニフティクラウド mobile backend NCMB mBaaS nifty NiftyCloud