Auth0から内製認証基盤へ移行を決めた背景と移行方法

ogp

はじめに

こんにちは、ソフトウェアエンジニアの大山です。

enechainではこれまでユーザー認証基盤としてAuth0を利用してきましたが、事業の成長に伴い自社開発の認証基盤(eAuth)へ移行しました。 本記事では、Auth0から内製へ移行する意思決定の背景、移行の設計について紹介します。

なぜ内製化を選んだのか

enechainでは元々Auth0を認証基盤として採用していました。 少人数のチームでサービスを立ち上げるフェーズでは認証認可の開発運用コストを低く抑えられていましたが、事業が成長しサービスが増えていく中で課題が顕在化し、主に以下の理由から認証基盤を内製化する意思決定を行いました。

プラットフォーマーとしての説明責任

enechainは国内最大のエネルギーのマーケットプレイスを運営しており、外部サービスの障害を理由に「自社サービスが使えない」という状況は避けなければいけません。

また、先日の資金調達のアナウンスにもあった通り、エネルギー取引における社会インフラとしての役割を担っていくためにこれまで以上に快適かつ安心安全に使えるプラットフォームを開発していくフェーズにいます。 Auth0側の障害や仕様変更でサービスに影響が出る場面もあり、認証基盤のコントローラビリティを自社で確保し、ユーザーへ説明できる体制を構築する必要がありました。

制約の解消とコスト削減

Auth0が提供する認証認可フローやUIのカスタマイズには制約があり、サービス固有の要件を実現しようとするとAuth0の仕様に合わせた回避策が必要になるケースがありました。

また、エネルギーのマーケットプレイスというドメイン上、認可については権限の細かい制御や反映速度など要件が厳しいという背景もありました。

加えて、ユーザー数の増加に伴いライセンスコストも無視できない規模になってきており、これらの制約とコストの両面を解消することが内製化の大きな動機でした。

認証基盤を内製で持つリスク

一方で、認証基盤の内製化には大きなリスクも伴います。社内では以下のような項目を始め様々な観点からリスクが検討されました。

  • 独自実装による脆弱性を作るリスク
  • 外部からの攻撃を少人数で守ることの難しさ
  • IDaaSに任せていた運用を自社で引き受けることによる責任範囲・負荷の拡大
  • セキュリティのトレンドや脆弱性情報の継続的なキャッチアップと自社対応の必要性

今回enechainでは、これらのリスクを踏まえてもなお、プラットフォーマーとして認証基盤のコントローラビリティを自社で持つことの重要性が上回ると判断しました。

移行の設計

Auth0から内製認証基盤(eAuth)への移行は、ユーザー影響を最小限に抑えながら安全に進める必要がありました。 ここでは、移行にあたっての設計方針を紹介します。

並行稼働による段階的移行

移行において最も重要視したのは、Auth0とeAuthの並行稼働です。 一度に全てを切り替えるのではなく段階的に移行を進めることで、リスクを最小化しました。

並行稼働期間中はAuth0とeAuthの両方の認証システムが同時に動作している状態を維持します。 これにより以下のようなメリットがありました。

  • ロールバックが容易: 問題が発生した場合はすぐにAuth0に切り戻すことができる
  • 段階的な移行: 一部のサービスから順次eAuthへ切り替えることで影響範囲を限定できる
  • 十分な検証期間の確保: 社内向け管理画面などで先行して本番環境での動作を十分に検証できる

並行稼働にあたり、認証基盤を以下のような構成に変更しました。

Before

Auth0での認証認可基盤構成

After

並行稼働中の認証認可基盤構成

構成要素は以下の通りです。

  • eLogin (上部・青): 内製のログインページ。Frontend + BFF + API で構成され、eAuthと連携する
  • eAuth (右上・黄): 内製の新認証基盤
  • Auth0 (右下・青): 既存の旧認証基盤
  • 移行後のサービス (中央・赤): eLogin経由で認証するeAuthに移行済みのサービス
  • 移行前のサービス (下部・赤): Auth0経由で認証するAuth0を使用している移行前のサービス

eAuthはenechainに従来からあったユーザー管理サービスで、今回はそこに追加する形で機能を実装しました。 また、移行コストを抑えるため、Auth0から提供されている @auth0/auth0-react とインターフェースを揃えた @enechain/auth-js を各サービスのfrontend用に提供しました。

使用するデータソースの統一(SSoT)

並行稼働中は、旧認証基盤であるAuth0もAuth0管理のDBではなくeAuthのDBを参照するようにしました。 これにより、新旧どちらの認証基盤を経由しても同一のデータソースを参照するため、データレベルでの齟齬が発生しません。 並行稼働前後でAuth0のインターフェースに変化はなく、移行前のサービスからは従来と同じように見えます。

Auth0からeAuthのDBを参照するには、Auth0のカスタムDBとアクションスクリプトを利用しました。 カスタムDBはAuth0上でNode.jsスクリプトを実行する仕組みで、Login等の認証イベントごとに外部DBへの問い合わせロジックを定義できます。

例としてLoginイベントに対しては以下のような関数を実装することになります。

async function login(identifierValue, password, callback) {
  // 1. 外部DBに接続
  // 2. 認証
  // 3. 成功した場合はユーザープロファイル、失敗した場合はエラーを返却
  ...
  return callback(null, {
    user_id: ...,
    app_metadata: {
      ...
    },
    user_metadata: {
      ...
    },
  });
}

これにより、Auth0を経由している移行前のサービスでも、サービスに渡されるユーザープロファイルはeAuthのDBから生成されます。 Auth0内部のデフォルトの認証ロジックをカスタムDBによる独自実装に置き換える形ですが、Auth0のインターフェース自体は変わらないため、各サービスへの影響はありません。

ユーザープロファイルの項目はあまり見直しをされてこなかった経緯があり、現在は不要と思われる項目もありました。ただ、移行前後でのユーザー影響のリスクを考慮し、まずはeAuthでも同様の項目を提供することにしました。

実際のDBを切り替える際はAuth0のDBからeAuthのDBにデータをExport/Importする必要があります。Export作業はメンテナンスタイミングに合わせてAuth0側で実施頂きました。

一方、ユーザー作成などデータの起点となる操作については両基盤での並行稼働が難しいため、並行稼働開始のタイミングでeAuthに一本化しました。また、即時反映が必要な一部情報については、eAuthからAuth0のManagement APIを使用して更新するなどの対応をいれています。

認証基盤の内製化、並行稼働をしてみて

各サービスの内製認証基盤への移行は現在も継続中ですが、ここまでの作業で見えてきたメリットや知見を紹介します。

認証基盤全体がコントローラブルになった

内製化による最も大きなメリットは、認証認可に関わる全ての要素を自社でコントロールできるようになったことです。 外部サービスの仕様変更や障害、メンテナンスに左右されることなく、自社のペースで機能追加や改善を行えるようになりました。

またこれによりサービス固有の要件をサポートしやすくなり、デザイン面でも他のサービスやページと共通のコンポーネントを利用できるようになるなど多くのメリットがありました。

内製化で得られた価値

内製化により、IDaaSの仕様に縛られていた部分を自社の要件に最適化できるようになりました。実際に内製化によって実現できたことをいくつか紹介します。

  • Session revoke
    • 移行前のセッションはAuth0が管理していたため、状態確認やrevokeなどの制御手段が限られていました。内製することによってより細やかな制御が提供できるようになりました。
  • 管理画面の統合
    • セッションや使用デバイスなど認証認可に関連する情報を従来からあった内製のユーザー管理画面に統合できました。今まで一部の情報はAuth0から提供されているWeb Dashboardから確認する必要があり、確認の手間やそれらを閲覧するためのユーザー権限の管理が分離されてしまっていたなどの問題がありました。
  • ユーザー体験の向上
    • エラー発生時に原因に応じた分かりやすいメッセージや適切なリカバリ導線など、他の社内サービスと同等の粒度でユーザー体験を設計できるようになりました。

今回の移行で認証基盤に関するデータやルール、ログを自社で直接管理できる土台が整いました。今後はこの土台を活かし、他サービスとの連携の拡充、自社要件に最適化したパスワードポリシーやMFA設定の継続的な改善、コンプライアンス要件への対応した監査ログの整備などさらなる向上に取り組んでいきます。

並行稼働について

並行稼働とSSoTの設計方針は、移行フェーズにおいて大きな効果を発揮しました。

問題が発生してもAuth0へ即座に切り戻せる状態を維持しているため、厳密なスケジュール管理が不要で、各サービスの状況に合わせたスケジュールを組むことができました。サービス毎に移行していくため、実際に想定外の事象が発生した際も、そのサービスに集中して対応にあたることができています。 SSoTによりAuth0とeAuthの両方が動作している状態でもデータの実体はeAuthのDBに一本化されていることは対応の大きな助けになりました。

また、切り戻しの選択肢があることで冷静に原因調査と対応を進めることができ、ユーザー影響を最小限に留められました。

発生した課題

一方で、事前の想定通りにはいかなかった部分もありました。

認証基盤の移行は、開発だけでなくCS(カスタマーサポート)を含む社内全体の運用にも影響を及ぼすプロジェクトでした。 並行稼働中はAuth0とeAuthでそれぞれ独立したログインフォームを使用し、セッションも独立しているため、ユーザーが両方のシステムを跨いで利用するケースでは、ユーザーの状態を適切に判断するためにAuth0とeAuthのどちらで認証しているかを把握する必要があります。

これらの情報はユーザーが意識するものではないため、問い合わせ対応時にCSチームが状況を切り分けるための認知負荷が想定を超えて大きく上がりました。

「このユーザーは今どちらの認証基盤を使っているのか」「このサービスは移行済みなのか」といった判断が問い合わせのたびに必要になり、従来のAuth0のみの環境と比べて対応の複雑さが増しました。

また、サービスごとの移行状態を関連チームへ正確に伝達しきれていなかった場面もありました。各開発チーム側では移行スケジュールや各サービスの切り替え状況を把握していたものの、その情報が適切に共有されておらず、問い合わせ対応時に混乱が生じるケースがありました。

CSを始めとした関係各所の柔軟な対応のお陰でなんとか乗り切りましたが、 並行稼働は開発チームだけでなく運用チームも含めた全体の協力が不可欠であり、技術的な設計だけでなく、運用プロセスの対応も同じくらい重要だったと感じています。

まとめ

本記事では、enechainにおけるAuth0から内製認証基盤への移行について意思決定の背景や移行設計を紹介しました。

enechainでは規模や事業フェーズに合わせて内製化に踏み切りましたが、認証基盤を内製するかどうかの意思決定は、必要性が明らかであったとしても非常に難しいものです。 本記事で紹介した背景や検討項目が少しでも役に立てば幸いです。

認証基盤が内製されコントローラブルになったことで、今後はセキュリティのさらなる強化はもちろん、サービスの成長に合わせた柔軟な機能追加や改善をより積極的に続けていく予定です。


enechainでは、一緒に事業を拡大していける仲間を募集中です。