NOT SO BAD なブログ

ぼっちスタートアップが日々がんばっています。

2016-12-28

Riot.js x Firebaseで作る、超お手軽なパスワード不要のログインシステム「Magic Login」

(2018年8月追記)
現在この機能はfirebase公式で提供されています。
このブログの実装方法もまだ使えますが、簡単なのでぜひ公式のをお使いください。
JavaScript でメールリンクを使用して Firebase 認証を行う  |  Firebase
(追記終わり)


Webサービスで本当にパスワードっているの??という意識高いスタンスから、
むかしQiitaにRailsでパスワードなしログインの実装について記事を書きました。

qiita.com

完全に使うあてもなく趣味で作った機能だったけど、 本体のSorceryにプルリク送ったらかなり歓迎されて、 あとはテストさえ書けば取り込んでもらえそうな状態です。
(じゃあ書けよっていう。。)

Add Magic Login submodule by athix · Pull Request #8 · Sorcery/sorcery · GitHub

しかし最近はFirebaseがマイブームなので、Firebase版のパスワードなしログインシステム「Magic Login」を実装してみました。

Firebaseには匿名認証の仕組みもあるので、ユーザー登録なしでも使えて、本登録するときは「MagicLogin」という組み合わせにすると、かなりいい感じになりましたよと。環境

  • Firebase: 3.5.0
  • Riot.js: 3.0.0
  • SemanticUI: 2.2.4

Firebase x Riot.jsのセットアップ

この2つを使ったシステムのセットアップについては、
むかしQiitaに記事書きましたのでこちらを参考にしてください。

qiita.com

以下この記事の内容をベースに追加修正していきます。

実装方針

  • サイトに訪問したら自動で匿名ユーザーとしてログインさせる
  • メアドを入力したら、そのアドレスにトークン付きのワンタイムログインリンクを送る
  • リンクを踏んで来たらログインさせる
  • 匿名ユーザーで作成してたデータを本ユーザーアカウントに紐づける(今回は省略)

こんな感じ。

今回はユーザーが新規登録かログインかを意識せずに使えるように設計してみました。

メアド入れたときに、既登録ならそのままログインリンクを送り、未登録なら新規登録した上でログインリンクを送る、という感じにしています。

新規登録とログインの間違えってけっこう多いし、そんなんシステムで判断してくれよ、って個人的には思うのですよね。。

ログイン画面

完成イメージ

こんな感じの見た目にしていきます。

Slackのメールだけログイン画面にあからさまに影響を受けた、メールと魔法の杖のアイコンがすてきです。

なんとこれ、画像一切つかわずやってるってなかなかすごくないですか。
SemanticUIのアイコン合成機能です。Semanticすごい!

実装

auth.tagをこんな感じで実装。



Magic Login
Get a magic linked email for super easy sign-in;)

{ message.text }


キモはfirebase.auth().sendPasswordResetEmail(that.refs.email.value)の部分で、要するにパスワードリセットメールを送ってるのですね。

これを踏んだあとの処理を魔改造することで、マジックログインを超簡単に実装しています。
次はそっちを見てみましょう。

リンク踏んだあとの処理

riot.jsのroutingで、ログインメールのリンク踏んだときの処理を受け付けています。

route('/auth..', function(){
  var q = route.query()
  if(q.mode == 'resetPassword') {
    firebase.auth().verifyPasswordResetCode(q.oobCode).then(function(email) {
      var newPassword = Math.random().toString(36).slice(-12)
      firebase.auth().confirmPasswordReset(q.oobCode, newPassword).then(function(){
        firebase.auth().signInWithEmailAndPassword(email, newPassword)
        alert('ログインしました')
      })
    }).catch(function(error){
      alert('ログインに失敗しました..')
    })
  }
})

auth?mode=resetPassword&oobCode=xxxxxxという感じのURLを踏んでくるイメージです。
(パラメータはFirebaseが自動付与)

やってることは、

  • verifyPasswordResetCode(q.oobCode)でトークンの検証
  • 正しいトークンならランダムに生成した文字列を新パスワードに設定
  • 新パスワードでログイン

というだけです。

キモは新パスワードをユーザーが意識することはないし、システム側でも管理しないというところ。超セキュア!

次ログインするときはまたリセットするだけですからね。

Firebaseの設定

Firebase側では、ログインメール(=パスワードリセットメール)のリンクURLを設定しておきます。

Consoleで、

Authentication > メールテンプレート > パスワードの再設定

から設定を編集し、「アクションURLをカスタマイズ」というメニューで好きなURLを設定しておきます。

https://hogehoge.com/auth

こんな感じで設定しておけば、パラメータ部分はFirebaseが自動で付与してくれます。

まとめ

というわけで、Firebaseの標準機能に乗っかることで超お手軽にMagicLoginが実装できました。

この記事では触れなかったけど、アクセス時に全員匿名ユーザーとして裏でログインさせておいて、 データを永続化したいときはこの仕組みで簡単ログイン、という組み合わせにするとかなりいい感じです。

このサービスで実践投入してますので、よければどんな感じか見てみてください。

the-timeline.jp

年表たのしいでよ。