vue.jsとfirebaseを使って、パスワードマネージャを作った話

今回は、いつものGASと違って、firebaseを利用してパスワードマネージャのアプリケーションを作成しました。

# きっかけ
きっかけは、自分が利用しているサービスのパスワードが同じパスワードで管理しているのに、こののままやったら危ないなー。と思ったのがきっかけです。  
1passwordやトレンドマイクロ等がパスワードマネージャのアプリを提供しているのですが、せっかくなら、firebaseの勉強を兼ねて作ってみようと思いました。 
完成している画面はこのようになっています。

白枠で塗りつぶしている部分は、アカウントIDを表示しています。  
<img width="336" alt="スクリーンショット 2019-12-03 16.20.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211927/beead865-edd6-739e-5706-3ea5bf088652.png">

#イメージフロー
下記のようなイメージで今回は作成を行いました。  

<img width="1012" alt="スクリーンショット 2019-12-03 16.23.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211927/ca7f2d65-d19d-4a87-9d4c-65f363944291.png">

①：firebaseのgoogle認証機能を利用してログイン処理を行う。  
②：ログインしていきたアカウントがfirebaseのユーザデータベースに登録しているアカウントか？の確認を行う。  
③：登録されていないアカウントの場合、ログイン画面にエラーメッセージを表示する。  
④：登録されているアカウントの場合、パスワードデータからアクセストークンが一致するコレクションからデータを抽出し、一覧で表示する。  
⑤：登録しているデータは編集削除が可能であり、また新規で登録も可能。  
⑥：ログアウトを行うと、ログイン画面に移動する。  

# 実際のデータ保持や、画面
ここからは、上記のイメージフローの実際の画面やデータベースの中身を説明したいと思います。  

## ログイン画面
ログイン画面はとてもシンプルになっています。「sign with google」のボタンをタップすると、googleアカウント選択ポップアップ画面が表示されます。
<img width="343" alt="スクリーンショット 2019-12-03 16.33.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211927/4ade4c18-fa0a-01cb-b554-3ec172fc3428.png">

firebaseのgoogle認証の使い方は以下の通りになります。([公式サイト](https://firebase.google.com/docs?hl=ja)に詳細に記載されていますので、詳しく知りたい方は、公式サイトを参考にすると良いと思います。)

```javascript
//google認証を行うために必要
const provider = new firebase.auth.GoogleAuthProvider();

//google認証のポップアップ表示からのアカウント選択後の処理
firebase.auth().signInWithPopup(provider).then((result)=> {
	//[result]にgoogleの情報が入っている
	//ex. result.user.email => googleアカウント
	
	//認証に成功した場合の処理...
	
}).catch((error) => {      
	//認証に失敗した場合の処理...
});
```

認証後、firebaseのデータベースに作成したユーザデータに登録しているアカウントかの確認を行います。  
もし、登録されていない場合は下記のようなメッセージが表示されてログイン画面から動かない状態です。 

<img width="340" alt="スクリーンショット 2019-12-03 16.54.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211927/44ba511d-23d7-28f5-9fde-72e096a06d14.png">

 
<img width="340" alt="スクリーンショット 2019-12-03 16.52.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211927/e6400991-0326-6f27-3ef6-7f3b2acbaeeb.png">

firebaseのデータベースの一覧データの取得方法は以下の通りとなります。  

```javascript
//firebaseconfigはfirebaseの設定、Firebase SDK snippetから取得してください。
const firebaseConfig = {
	apiKey: "XXXXXXXXXXXXXXXXXXXXXXXXXX",
	authDomain: "XXXXXXXXXXXXXXXXXXXXXXXXXX.firebaseapp.com",
	databaseURL: "https://XXXXXXXXXXXXXXXXXXXXXXXXXX.firebaseio.com",
	projectId: "XXXXXXXXXXXXXXXXXXXXXXXXXX",
	storageBucket: "XXXXXXXXXXXXXXXXXXXXXXXXXX.appspot.com",
	messagingSenderId: "XXXXXXXXXXXXXXXXXXXXXXXXXX",
	appId: "x:XXXXXXXXXXXXXXXXXXXXXXXXXX:xxx:XXXXXXXXXXXXXXXXXXXXXXXXXX",
	measurementId: "x-XXXXXXXXXXXXXXXXXXXXXXXXXX"
};

//firebaseのデータベースを使用する
const firebase_app = firebase.initializeApp(firebaseConfig);
const db = firebase.firestore(firebase_app);

//アクセスしたいコレクションを指定する。
const docRef = db.collection("colection");

//データベースにアクセスし、データ取得に成功した場合の処理
docRef.get().then((querySnapshot) => {
	querySnapshot.forEach((doc)=> {

		//[data].オブジェクトキーで保存しているデータの取得できます。
		let data = doc.data();

	})
	.catch((error) => {
		//データ取得時にエラーが発生した場合の処理

	})
});
```

## データ一覧画面
登録しているアカウントからアクセスした場合、データ一覧の画面に移動します。
移動した際に、データをパスワードを保持しているデータにアクセスを行い、アクセストークンが同じコレクションの中に保持しているデータを一覧で表示します。

nosqlでこういうデータの持ち方が良いのかわからないのですが、今回はこのようにデータを保持しています。

<img width="979" alt="スクリーンショット 2019-12-03 17.22.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211927/52a2a043-8ba7-ffda-eb72-54a213cc6347.png">

一覧画面は下記のようになります。（最初に紹介した画像と同じになります。）  
<img width="336" alt="スクリーンショット 2019-12-03 16.20.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211927/08e7ed30-9ea1-3cc5-cfc9-b54aedc23d36.png">

詳細を表示したいアカウントをタップすると詳細内容を表示します。  
<img width="342" alt="スクリーンショット 2019-12-03 17.29.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211927/551db2a7-b48c-5c63-4727-74fc20a60d02.png">



ピンクのボタンをタップするとコピーを行うことができます。  
主にパスワードをコピーして使用することが多いです。  
<img width="33" alt="スクリーンショット 2019-12-03 17.31.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211927/c58ce784-b5ab-5e19-29ef-178e8a9533d0.png">


編集タブをオンにすると登録している内容の編集を行うことが可能です。

登録しているデータの更新の方法は以下の通りになります。

```javascript
//更新したいドキュメントまでアクセスし、[set]で更新することができる。
db.collection("xxxxxx").doc(this.user.uid).collection("xxxxxx").doc(this.detail_data.doc_id).set({

	//キーと内容を全て記載する。更新したい内容だけ記載した場合、記載してない内容は消えるので注意です。
	/*
	  キー : 値　
	 ,キー : 値
	 ,キー : 値 ...
	 */

}).then(()=> {
	//データが更新した場合の処理
})
.catch((error)=> {
	//データ更新に失敗した場合の処理

});
```

## データ登録
ヘッダーにある「+」ボタンからパスワードの新規登録が可能です。  
「+」の左にあるボタンが一覧画面に移動、右側にあるボタンがログアウトボタンになります。

<img width="332" alt="スクリーンショット 2019-12-03 17.40.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211927/b75a3c18-f4be-9e23-9b6f-aa98f20f6de6.png">

入力する内容は入力欄に記載している通りとなります。  
「icon」は今回は、[fontawesome](https://fontawesome.com/)のフリーアイコンを表示できるようにしています。  
ただ、アイコンを使用するには、使用したい、classを検索して貼り付ける必要があるため少し面倒です。ここは改良する必要があるかなと考えています。  
パスワードは「CREATEPASS」をタップすることで自動で生成してくれるようになっています。
パスワードの長さも大文字を含むのか、数字を含むのかも設定可能です。

<img width="363" alt="スクリーンショット 2019-12-03 17.44.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211927/45927c6d-ef74-c718-6b43-9bb0115f79a5.png">

登録からデータを登録することができます。
ランダム生成の一意キーで登録する方法は以下の通りです。

```javascript
//登録したい、コレクションまでアクセスを行い、[add]でランダムキーで登録することができます。
db.collection("xxxxxx").doc(this.user.uid).collection("xxxxxx").add({
	/*
	  キー : 値　
	 ,キー : 値
	 ,キー : 値 ...
	 */
})
.then((docRef)=> {
	//データを登録完了した場合の処理

})
.catch((error) => {
	//データ更新に失敗した場合の処理
});
```

### 個人的な課題
今回、パスワードをデータベースに保存するので、「crypto-js」を利用して暗号化を行おうと試みました。  
しかし、実際に暗号化を行ってデータを新規登録を行おうとすると、ランダム生成されるキーがなぜか、毎回おんなじキーになってしまい、上手く利用することができずに課題になっているため、これは改善する必要があると考えています。

## PWA化
GASのアプリケーションでは不可能だった、PWA化を今回実装を行いました。  
[こちら](https://qiita.com/poster-keisuke/items/6651140fa20c7aa18474)のサイトを参考にさせて頂き、実装を行いました。

#最後に
意説明は以上となります。  
firebaseのサービスは本当に便利だと感じ、もっとfirebaseFunctionsとかを学びたいと思いました。  
まずは、このアプリケーションの課題を克服したいと思います。