Auth0を使って複数のウェブアプリでのログインの入力回数を最小限にしてみた

2020.10.23

前置き

「認証機能の開発工数削減をデモで体験!次世代認証基盤サービス『Auth0』導入実践ウェビナー」 にご参加いただいた方、ありがとうございました。

https://dev.classmethod.jp/news/201022-auth0-webinar/

上記のウェビナーで 複数のウェブアプリケーションでSSOを実現するにはどうすれば良いですか? といったご質問をいただいたのですが、しどろもどろな回答しかできず、大変申し訳ございませんでした。

Auth0 で SSO を実現するには下記のドキュメンテーションやサンプルを参考にしていただければと思います

ただ、実際にやってみないとよくわからない部分があったので、 また、提供されているサンプルは既存の Application に対して行っていたため、 新規に環境を作って試してみました。そちらの作業ログを記載します。

確認した内容はこちらです。

作業時のリポジトリはこちらになります

https://github.com/cm-kojimat/auth0-multiwebapp-example

検証した環境

❯ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.7
BuildVersion:   19H2

❯ docker version
Client: Docker Engine - Community
 Cloud integration  0.1.18
 Version:           19.03.13
 API version:       1.40
 Go version:        go1.13.15
 Git commit:        4484c46d9d
 Built:             Wed Sep 16 16:58:31 2020
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.13
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       4484c46d9d
  Built:            Wed Sep 16 17:07:04 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.3.7
  GitCommit:        8fba4e9a7d01810a393d5d25a3621dc101981175
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

❯ docker-compose version
docker-compose version 1.27.4, build 40524192
docker-py version: 4.3.1
CPython version: 3.7.7
OpenSSL version: OpenSSL 1.1.1g  21 Apr 2020

❯ mkcert --version
v1.4.1

Auth0 での作業

  • まず対象となるアプリケーションを作ります。
    • Service1 - SPA - Google の Connection のみ認証可能
    • Service2 - SPA - Google, GItHub で認証可能
    • Service3 - RegularWeb - Google, GItHub で認証可能

  • アプリケーションの設定時にはこちらを注意してください。

    • Service3 の callback URL の最後には /callback を忘れない
    • Service1, Serivce2 の リフレッシュトークンの振る舞いは Rotating に設定する

    https://auth0.com/docs/tokens/refresh-tokens/refresh-token-rotation

    英語では Default では Non-Rotating になっていること、SPA, Native には Routating を推奨してあることが注意書きとして記載されているのですが、英語故に見落としていました。

  • 次に Connection の作成します。いずれも開発キーで行っています

    • Google
    • GitHub

ローカル側での作業

  • サンプルアプリケーションをクローンします

    git clone https://github.com/auth0-samples/auth0-javascript-samples
    git clone https://github.com/auth0-samples/auth0-nodejs-webapp-sample
  • 今回はアプリを docker-compose でまとめて立ち上げたいので docker-compose.yaml を用意します
      ---
      version: "3.9"
      services:
        proxy:
          image: jwilder/nginx-proxy:alpine
          ports:
            - "80:80"
            - "443:443"
          volumes:
            - /var/run/docker.sock:/tmp/docker.sock:ro
            - ./etc/certs:/etc/nginx/certs:ro
        app1:
          build: auth0-javascript-samples/01-Login
          volumes:
            - ./etc/app1/auth_config.json:/app/auth_config.json:ro
          environment:
            - VIRTUAL_HOST=app1.local.gd
            - VIRTUAL_PORT=3000
            - CERT_NAME=shared
        app2:
          build: auth0-javascript-samples/01-Login
          volumes:
            - ./etc/app2/auth_config.json:/app/auth_config.json:ro
          environment:
            - VIRTUAL_HOST=app2.local.gd
            - VIRTUAL_PORT=3000
            - CERT_NAME=shared
        app3:
          build: auth0-nodejs-webapp-sample/01-Login
          volumes:
            - ./etc/app3/.env:/home/app/.env:ro
          environment:
            - VIRTUAL_HOST=app3.local.gd
            - VIRTUAL_PORT=3000
            - CERT_NAME=shared
    • SSL の設定を用意している理由として auth0 の SPA library が localhost や一部のドメイン以外では SSL でしか動作しないためです。
    auth0-spa-js must run on a secure origin.
          See https://github.com/auth0/auth0-spa-js/blob/master/FAQ.md#why-do-i-get-error-invalid-state-in-firefox-when-refreshing-the-page-immediately-after-a-login
          for more information.
  • SSL の用意が必要なため、mkcert で証明書を用意します
    mkdir -p etc/certs/
    mkcert -install
    mkcert -cert-file etc/certs/shared.crt -key-file etc/certs/shared.key "*.local.gd"
    • 今回使うドメインは https://local.gd/ のサービスを利用させていただきました。

    nip.io, xip.io 同様にサブドメインを振っても全て 127.0.0.1 を返してくれる DNS サービスです

  • アプリケーションに auth0 の設定を行っていきます

    mkdir -p etc/app{1,2,3}
    vim etc/app{1,2}/auth_config.json
    vim etc/app3/.env

    auth_config.json は下記の項目を設定してください

    {
    "domain": "",
    "clientId": ""
    }

    env は下記の項目を設定してください

    AUTH0_DOMAIN=
    AUTH0_CLIENT_ID=
    AUTH0_CLIENT_SECRET=
    AUTH0_CALLBACK_URL=
  • docker-compose でサービスを立ち上げます
    docker-compose up --detach --build

確認してみる

  • SPA のサンプルでは https://app2.local.gd/profile,

    RegularWeb のサンプルでは https://app3.local.gd/user の URL で

    未ログイン時であれば認証ページへ

    ログイン済みであればユーザ画面を表示することができます

    今回は、https://app2.local.gd/profile にアクセスして、 GitHub 認証していきたいと思います

    open https://app2.local.gd/profile

    認証ページに飛ばされました

    認証後はユーザのプロフィールが表示されます

  • では次に https://app3.local.gd/user で確認します。

    open https://app3.local.gd/user

    他の webapp にアクセスしましたが、認証ページが表示されることなく、ログインしたアカウントが表示されました

  • 最後に https://app1.local.gd/profile を確認します。

    認証ページが表示されました

    認証もできます

  • https://app2.local.gd/profile に戻ってみると。。

    ユーザが Google のアカウントに切り替わっていることが確認できました

まとめ

Auth0 ではアプリを編集することなく、シームレスなSSOが実現できることを確認できました。 また、設定も容易にexportできるため、検証環境を github に公開することが可能でした。