Auth0のNew Universal Loginを利用したログイン画面のデザインを調整する

2023年8月現在、Auth0を利用してログイン・サインインフローを提供する場合、セキュリティやユーザー体験の快適さからNew Universal Login（NUL）を利用することがOktaから推奨されており、またアプリケーション側での実装が不要なため開発コストも低く済むので、導入を検討する方が多いことと思います。

今回はこのNULにおいて、所望のデザインを実現する方法について紹介します。
NULの概要についてはAuth0の記事をはじめ、いろいろなページで詳細に解説されていますので、今回は説明しません。

https://auth0.com/blog/introducing-the-new-auth0-universal-login-experience/

# NULで調整できる項目と、その調整方法
NULを利用する場合、大きく分けて以下の二つの要素を調整可能です。
1. ログインユーザーが入力するフォーム部分（`auth0:widget`と呼ぶことにします）
2. フォーム以外の部分

ここでいう１番のフォーム部分というのは、[下の画像（ソースはリンク）](https://images.ctfassets.net/23aumh6u8s0i/54lZ5srDBAM0dqWSRkdxXk/f4260dcf2af6e7b5b4a52c62769e0745/lightweight-login)のような、プロダクトもしくは開発企業のロゴやメールアドレス・パスワードの入力フォーム、ソーシャルログインボタンを備えたwidgetを指します。
パスワードの再発行などでもこのwidgetが活躍し、その際は入力部分が存在しない場合もあるので、厳密にはフォームとは呼べないかもしれません。今回はこの要素を`auth0:widget`と呼ぶことにします。
`auth0:widget`ではロゴ画像や表示される文言、フォントの色やサイズ、ボタンの色などを調整可能です。ただしそのテンプレートの全てを調整できるわけではなく、その表示順序だったりサポートされていない要素の配置などは基本的に不可能です。
![スクリーンショット 2023-08-06 17.21.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677068/b7724958-3260-567c-f667-355ecd5c8210.png)
調整可能な項目については、Auth0のWebダッシュボードで`Branding > Universal Login`に進むことで簡単に操作可能です。API（[Management API](https://auth0.com/docs/api/management/v2)）からも管理が可能です。
Webは下の画像のようなUIなのですが、とてもわかりやすく変更も「Try」からすぐに確認可能なため、今回は解説しません。
ちなみに２枚目の画像において、何も文言を何も入れたくない項目については半角スペースを入力すると、何も表示がされなくなります。
![スクリーンショット 2023-08-06 19.09.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677068/84d02da5-687e-32c9-6f50-407acf094a99.png)
![スクリーンショット 2023-08-06 19.10.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677068/ef062cdc-8360-39b8-94a0-c4ece8a6cfac.png)

２番目のフォーム以外の部分というのは少しわかりづらい表現ではありますが、１の`auth0:widget`以外の部分全てです。
NULの画面はサーバー側でレンダリングされた状態でクライアントに届くのですが、デフォルトの状況でそのhtmlを眺めると`<main></main>`で囲われた要素が見つかると思います。
そこが`auth0:widget`の部分なのですが、そのmainタグ以外の部分はテンプレートとして調整が可能です。
これにより、NULの画面にヘッダーやフッターを配置したり、aタグを使って利用規約へのリンクを表示したりすることも可能です。

こちらに関してもManagement APIから操作可能な他、[Auth0 Deploy CLI](https://github.com/auth0/auth0-deploy-cli/pull/438)（コマンドはa0deploy）や[Auth0 CLI](https://auth0.com/docs/customize/universal-login-pages/universal-login-page-templates#using-the-auth0-cli-)（コマンドはauth0）を利用することでも操作が可能です。
このテンプレートの調整の作法と、Management APIを利用したデプロイ方法について以下で解説します。

# NULテンプレートの作法
Management APIを利用したNULテンプレートデプロイの公式Docsがあります。こちらを参照しながら実行していくのが確実ですが、いくつかポイントを解説します。

https://auth0.com/docs/customize/universal-login-pages/universal-login-page-templates

まず、NULテンプレートはLiquid templateを利用してカスタマイズすることになります。
恥ずかしながら私はこの開発に携わるまで、Liquid templateを知らなかったので、ChatGPTに聞いてみました。

:::note info
Liquidテンプレートとは？
Liquid（リキッド）は、ウェブテンプレートエンジンの一種です。ウェブアプリケーションや電子商取引サイトなどで、ダイナミックなコンテンツの生成や表示を行うために使用されます。特に、Shopifyというeコマースプラットフォームで広く使われており、テーマのデザインやレイアウトをカスタマイズする際に活用されています。
:::
その後ググって齟齬がないか確認してみましたが、誤りはありませんでした。
どうやらShopifyが開発したようで、2006年誕生のようです。

今回の記事はLiquid templateの記事ではないので詳しくは説明しませんが、テンプレート中の`{{ }}` 内に変数やタグを配置することで、テンプレート内で変数表示や条件分岐、ループなどの動的な情報の表示や制御を行うことができます。

上のAuth0の公式Docsを見ると、NUL画面のシンプルなテンプレート例は以下のように提示されています。
```html
<!DOCTYPE html>
<html>
  <head>
    {%- auth0:head -%}
  </head>
  <body>
    {%- auth0:widget -%}
  </body>
</html>
```
`auth0:head`と`auth0:widget`はどちらもNULテンプレートに**必須**のオブジェクトです。
`auth0:widget`はログインやパスワードリセットなど、各ページに表示されるウィジェットのhtmlを返します。（上の章で名付けた`auth0:widget`とそのまま対応します）
`auth0:head`は、ウィジェットをレンダリングするために必要なタグ（meta、style、scriptタグ等）を返します。

つまり、`auth0:head`と`auth0:widget`を適切な位置に含むようにさえすれば、あとは自由にhtmlを改造可能ということです。
公式Docsでは、右側に画像を表示する用やレイアウトやフッターを表示するようなレイアウトが紹介されています。

私自身はhtmlをうまく書くことで、下の画像のような見た目を実現しました。
ヘッダーやフッターを追加したり、使用規約やプライバシーポリシーを追加したりしています。
`auth0:widget`内の表示文言やボタンの色はWebのコンソールから修正しています。
![スクリーンショット 2023-08-06 20.37.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677068/b165b604-0177-99a9-2e9b-3ecbcb7c405e.png)
ちなみにLiquid templateで利用可能な変数は、[こちら](https://auth0.com/docs/customize/universal-login-pages/universal-login-page-templates#available-variables)に一覧表示されています。
もしなんらかの用途で画面に応じて条件分岐をしたい場合などは、そちらにある値は利用可能です。

# NULテンプレートのManagement APIを利用したデプロイ方法
htmlが準備できたら、あとはデプロイするだけです。
その方法は[公式Docs](https://auth0.com/docs/customize/universal-login-pages/universal-login-page-templates#page-templates-api)にある通りではありますが、一応解説します。

まず初めにWebコンソールから`Applications > APIs`に進みます。
すると、Auth0 Management APIというAPIがデフォルトであると思います。
![スクリーンショット 2023-08-06 23.33.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677068/acd71fd4-0692-ee5c-bb73-d6a43a1b8433.png)
その項目のAPI AudienceのURLがエンドポイントになっているので、そのドメインをコピーして下のcurlコマンドの自分のドメインのところに対応させてください。
```bash
curl --request PUT \
  --url 'https://自分のドメイン/api/v2/branding/templates/universal-login' \
  --header 'authorization: Bearer ここにアクセストークン' \
  --header 'content-type: text/html' \
  --data 'ここにhtml'
```
その後、Auth0 Management APIを押下するとAPI Explorerというタブがあると思うので、そちらに進みます。
（この作業によって、ApplicationsにAPI Explorer Applicationというアプリが自動で追加されるはずです）
すると、Tokenが表示されると思うので、それをコピーして上のコマンドの「ここにアクセストークン」のところに貼り付けます。（「Bearer + 半角スペース」はそのまま）
あとは「ここにhtml」のところに、ご自身で作成したhtmlをベタ書きで貼り付けて実行すればOKです。

実行後にNULのログイン画面などにアクセスすると、うまくテンプレートが反映されているのが確認できるはずです。

# ダッシュボードでは調整できないような仕様を`auth0:widget`に反映させるには
ここまではAuth0が用意してくれている正攻法で、好みのデザインを実現する方法を紹介してきました。
テンプレートには自由にhtmlを記述することができるため大方のデザインは実現できると思いますが、`auth0:widget`内部のデザインはそのままでは実現できるデザインに限度があります。

これを無理やり調整するには、`auth0:widget`によって提供されるhtmlの構造を把握して、特定の要素にcssを適用することが有効です。
例えば2023年8月現在において、ログイン画面におけるパスワード忘れへの対応リンクは、`main > section > form > p`という構造で置かれていることがわかります。
そのため例えば、以下のようなstyleをheadに追加することで、パスワード忘れの文言のデザインを調整することが可能です。
```html
<head>
  <style>
    main section form p {
      margin-top: 10px;
      margin-bottom: -10px;
    }
  </style>
</head>
```
これを応用すれば、特定の要素を`display: hidden`にすることで非表示にしたり、scriptを利用することで文言を追加したり、特定のページのみでとある要素を非表示にしたりする、といったことが可能です。

ただしAuth0の公式Docsの最後に次のような注意が書かれています。

:::note warn
Additional considerations:
- The HTML structure of these pages may also change. Any customizations that depend on that structure could stop working at any time.
:::
つまりhtmlの構造はいつでも変わる可能性があるので、このような調整をしていると突然デザインが崩れることもある、ということです。
このことをきちんと頭に入れた上で、上記のテクニックを利用するようにしてください。

# まとめ
Auth0のNew Universal Loginを利用したログイン画面等のデザインを調整法を紹介しました。
テンプレートやwidget内部の見た目を調整する機能が提供されているので、おおよそのデザイン要件はそれらを活用することで実現可能であるはずです。

実は現在、Auth0を認証基盤として利用したSaaSを開発しており、その中で得た知見を記事化しました。
そちらのサービスは、Qiitaを利用している皆さんにとって役に立つであろう機能を中心としたものになっています。
皆さんにご利用いただけるのが楽しみです。
早く皆さんにご提供できるよう、開発に力を入れていきたいと思います！