🏫

Firebase AuthenticationのログインをGoogle Workspace組織内に制限する

6 min read

https://qiita.com/advent-calendar/2020/sgg
この記事は SGG(すごくなりたいがくせいぐるーぷ) Advent Calendar 2020 23日目の記事です。

はじめに

新型コロナウイルスの感染が拡大する中、行事を始めとする学校生活にも多くの影響が出ました。僕の参加する部活でも、「部員が作成した作品をWeb上でたくさんの人に見てもらおう」ということになりましたが、校内限定公開という条件がつきました。ということで、この条件を Google Workspace + Firebase を利用してクリアしていきたいと思います。

環境

使用したもの バージョン
Firebase CLI 9.1.0
Firebase SDK(JavaScript) 8.2.1
Firebase Authentication -
Firebase Hosting -

手順

1. プロジェクトの作成


プロジェクトを組織に紐付けて作成

Firebase コンソール上でプロジェクトを作成します(CLIでもOK)。このとき、組織に所属するGoogleアカウントでログインし、組織に紐付いた状態になっていることを確認してください。

画面上での作成後は、firebase initコマンドを利用してローカルのプロジェクトとの紐付けを行ってください。(SPA設定、GitHubデプロイ設定は任意)

2. Firebase Authenticationの設定


Googleログインの有効化
コンソールのAuthenticationの設定で、Googleログインを有効にします。

3. ログイン処理の仮実装

コード
index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Google Workspace ログイン制限のテスト</title>
    <script defer src="/__/firebase/8.2.1/firebase-app.js"></script>
    <script defer src="/__/firebase/8.2.1/firebase-auth.js"></script>
    <script defer src="/__/firebase/init.js"></script>
  </head>
  <body>
    <h1>Google Workspace ログイン制限のテスト</h1>
    ログイン状態: <span id="status">未ログイン</span><br />
    <script>
      document.addEventListener("DOMContentLoaded", () => {
        const provider = new firebase.auth.GoogleAuthProvider();
        firebase
          .auth()
          .signInWithPopup(provider)
          .then(function ({ user }) {
            document.getElementById(
              "status"
            ).innerText = `ログイン済 (${user.email})`;
          })
          .catch(function (error) {
            document.getElementById(
              "status"
            ).innerText = `ログインエラー (${error.message})`;
          });
      });
    </script>
  </body>
</html>

firebase deployコマンドでサーバーへデプロイします。



すべてのアカウントでログイン可能

この段階では、すべてのアカウントでのログインが可能となっています。

3-1. アカウントを組織内に限定する

Google Cloud Platform上の設定を変更します。
Firebaseと紐付けられているプロジェクトを開き、APIとサービス > OAuth同意画面を開き、ユーザーの種類を内部にします。

内部へを押しユーザーの種類を変更


403 認証エラー
この時点で、組織外からのログインがすべてブロックされます。

例えば、生徒は student20201223@students.example.ac.jp、先生はteacher20201223@teachers.example.ac.jp のように、生徒と先生でサブドメインが別になっている場合でも正しく処理されます。

3-2. (任意) ログイン画面に表示されるアカウントを制限する

3-1の設定をしても、Googleのログイン画面上には組織外のアカウント(@gmail.comほか)が表示されます。これを防ぐために、以下のコードを追加してください。

scriptタグ内抜粋
const provider = new firebase.auth.GoogleAuthProvider();
// 以下を追記
provider.setCustomParameters({
  "hd": "[Google Workspaceのドメイン]",
});
// ここまで
firebase
  .auth()
  .signInWithPopup(provider)


組織内アカウントのみが表示される
以上で、ログイン画面に表示されるアカウントを制限することができます。

3-1の例のように、生徒と先生で別のサブドメインを利用している場合、どちらのサブドメインを利用しても両方のアカウントが表示されます。

なお、このコードで制限できるのは表示のみである(詳しくは追記部分について内参照)ため、3-1の設定も必ず適用するようにしてください。

追記部分について

provider.setCustomParametersは、OAuthリクエストに付け加えて送信されるパラメーターを指定するものです。hdパラメーター(hosted domainの略)は、ログイン画面に表示するアカウントを制限するためのものです。詳しくはGoogle Developersを参照してください。
なお、このパラメーターはURLに付け加えられるため、クライアント側で削除することができます。そのため、この作業は主にユーザーのスムーズなアカウント選択のためであると考えてください。

未ログイン時の挙動について

未ログイン時には以下の画像のように、サブドメインまで入力された状態のログイン画面が表示されます。生徒と先生で同一ドメインを利用している場合にはさほど問題がありませんが、別のドメインの場合はログインに少し困る人が出る可能性があります。そのため、

  • (多く)使う人に合わせて生徒用/先生用のサブドメインを設定する
  • 1つ上の階層のドメインを指定する

といった工夫をしてみてください。


こう見えてstudents.example.ac.jpgmail.comも入力可能

一方、多くの人は生徒用(先生用)ドメインが表示されていると、先生(生徒)はログインができないと感じてしまうかもしれません。また、後者の手段をとった場合でも、サブドメインが入力できないと勘違いしてしまう可能性があります。ログイン前の画面で、ドメインはキーボードでの上書き入力が可能であることをどこかに追記しておく工夫も考慮してみてください。

その他の注意事項

  • ブラウザでサードパーティーのCookieの利用を許可する必要があります。
    特にChromeのシークレットモードを利用して検証を行う場合に注意してください(僕はこのことに気づかずに3週間近く無駄な修正を繰り返していました)。

    Cookieをブロックしてはいけない

  • コード例では signInWithPopup を利用しましたが、signInWithRedirect を利用することも可能です。

  • コード例ではSDKを予約済み URLから読み込んでいますが、環境に応じて適宜変更してください。

  • 各種フレームワーク(Vue/React/Angularほか)と合わせて利用する場合も手順は変わりません。

まとめ

以上で、任意のサイトにGoogle Workspaceによるアクセス制限を設定することができます。学校をはじめとする組織内専用のアプリケーションやWebサイトを作成するときにぜひ参考にしてみてください。

あとがき

昨日とは変わって学生らしい(?)記事を書いてみました。

僕の部活の作品の公開は期末テストが迫っていたため2週間と短いものでした。あわせて、廊下にはポスターも掲示していたものの、なかなか目には止まらず、アクセス数が伸び悩んでしまったのが残念でした。次こそはたくさんの人に見てもらえるよう、ポスターを含めてしっかり練り直していきたいと思います。

なお、

  • ページのデザインや構成を自分の手でつくりたい
  • アプリケーションを作成している

といった場合を除き、アクセス制限を含む場合には Google サイトを利用するのが最善策だと思います。(僕がFirebaseを利用することになったのは両方の要因が挙げられます。)