決済基盤、会員基盤をメインにサーバーサイドエンジニアをやっているルンバです。
今日はNAVITIMEの認証基盤をマイクロサービス化したときのお話をいたします。
複数プロダクトを開発運用している方の参考になれば幸いです。
はじめに
NAVITIMEでは様々なアプリを開発運用しています。
NAVITIMEのプロダクトは大まかには下記の形で開発運用されています。
・ユーザーデータはアプリローカルではなくDBに保存する
・アプリから各プロダクトの専用APIサーバーに接続し、ユーザーデータの参照更新を実施している
既存システム
既存システムの問題点
1. 仕様差分
各プロダクトAPIサーバーで独自実装しているため、プロダクトによって微妙な仕様差分が発生していました。社内独自フォーマットにユーザー情報を格納し社内独自の暗号化形式で作られていたのですが、サービスによっては認証には直接関係ない情報がフォーマットに追加されていく状況でした。もちろんググってもHow To記事は出てこないため、年季の入ったドキュメントを1から読んだり有識者にヒアリングする必要があり、学習コストが高い仕様でした。
3. クラウド化の流れ
社内のアーキテクチャがクラウド化していく中で、いわゆる「サーバーレス」という選択肢も出てくるようになりましたが、この独自の認証仕様をどのように踏襲していくかが悩みの種でした。
認証機構APIの構築
問題を解決するため、全社が同時に参照するAPIサーバーを構築しました。
1. 認証処理専用のAPIを構築
認証処理を賄うAPIサーバーを構築しました。
2. JWT規格に統一
認証規格は①一般化されていて、ググればおおよその仕様の理解ができるもの②クライアント側がどういうアーキテクチャであっても実現できるものという軸で選定し、JWT(RFC 7519)を採用しました。
3. トークンを使ったユーザーデータ参照APIも構築
認証機構APIの構築と合わせて、ユーザーデータ参照APIも構築しました。今までは各プロダクトのAPIサーバーでDB接続して参照更新していたユーザーデータを、認証機構APIで発行したトークンを用いて参照更新する形に刷新しました。認証機構と合わせて、主なユーザーデータの参照更新の仕様もAPI化することで統一されました。
改善された点
認証仕様の全社的な統一化
基本的には認証機構APIをリクエストしJWTを受け取るだけ、という仕様に統一化されました。今まで各プロダクトのAPIで独自で実装していた処理がごっそりなくなることでコードも単純化され、また新規サービスの開発も遥かに簡単になりました。APIの仕様書通りにリクエストするだけでいいので1時間程度で開発が完了します。
仕様の汎用化
JWTという一般化された規格を用いることで、一般的なドキュメントを読むことで認証処理の大枠は理解できるようになりました。JWT内部のクレーム情報にはいくつかNAVITIME独自の仕様が含まれていますが、そこは社内整備されたドキュメントを読めば理解できるようになりました。
クラウド化に対応
APIベースでのJWTのやり取りで認証処理が完結するため、クライアント環境がAWSでもGCPでも、サーバーレスであっても、統一的な仕様で認証が行えるようになりました(基本的にはAPIにリクエストするだけでいい)
気をつけていること
全プロダクトが1つのAPIを参照するため、アクセス数の見積もりには気を使う必要があります。
このAPIサーバーが輻輳するとサービス全断リスクがあるため、認証APIサーバーは他APIサーバーよりも余裕を持った台数で稼働しています。
まとめ
ドキュメントの整備やアクセス負荷の対応等、まだ課題はありますが
認証機構をAPI化することで開発運用の効率化ができました。