💣

セッションが確立されていないFE/BE間でトークンを用いて簡易的なセッションを実現する

2022/03/06に公開

ritouです。

何の話か?

このあたりの話です。

FE + BE が存在するID連携

SPAやネイティブアプリといったフロントエンドと、バックエンドサーバーを組み合わせたサービスでID連携を行う際、バックエンドサーバーを起点、終点としたフローを考えられるとセキュアにできますよ、みたいな話を前に書きました。

https://zenn.dev/ritou/articles/d26c7861047a2d

次に、認可サーバー/リソオースサーバーとのやりとりを Backend Server に任せる パターンです。

リソオース...

前提として、モバイルアプリやSPAとBackend Serverの間にセッションが確立しており、Client は認可リクエストのURLにリダイレクトするだけ、認可レスポンスのパラメータを Backend Server に送るだけです。

このセッションが確立している前提について、ログイン後のID連携などではセッションが確立されているが未ログイン状態のソーシャルログインではセッションが確立されていない!どうすればいいんだ!って話もあるかと思います。

そこでこのTweetですね。

立場上、サービス間の連携などではなるべく標準化仕様になってるプロトコルを利用すべきってなことは良く言いますが、FE/BE間のやりとりは利用している仕組みに応じて危なくない方法で実装してもらえばと思っています。

という立ち位置において、セッションのない状態で簡易的なステートフルアクセスを実現するために次のような設計、実装をすることがあるのですこし紹介します。

セッショントークン(仮)を用いたステートフルなしくみ

(図をここに書くつもりだったがめんどい)

今回の話で言うと、BEはOIDCの認証リクエストを生成しつつ

  • nonce
  • 複数のIdPと接続する場合はIDTokenに含まれることを期待する識別子など

といった辺りを後から確認できるようなセッショントークンも同時に生成し、FEに渡します。

FEはどうにかしてそのトークンを保持しつつ、認証リクエストをIdPに送ります。

IdPから認証レスポンスが戻ってきたら、保存していたセッショントークンと一緒にBEに送るわけです。後はもういいよね。

FEのやることはシンプルだし、BEにロジックを集約できるので個人的には満足してる設計です。

セッショントークンの実装は?

もちろん自分で実装するときはeyJなやつとデータストアの組み合わせですが、一般的なセッションの要件を満たせたら何でも良いでしょう。

  • 複数のパラメータを保持できる
  • 改竄できない、もしくは検知できる
  • 他人のトークンを推測できない
  • 無効化できる

ID連携以外の用途

この簡易なセッショントークンのしくみの用途はID連携に限りません。

  • SMSやメール経由のOTPを用いたログインや新規登録
  • WebAuthnを利用したログイン

といったように、ログインセッションがない状態から複数リクエストを用いて実現する処理との相性が良いでしょう。

まとめ

簡易的なセッションの機能を実現するためにトークンを使うアイディアを紹介しました。
SPAではないレガシー?なWebアプリケーションをメジャーなフレームワークで動かそうと思うと

  • ちょちょっと設定したらなんとなくセッションはられる
  • HTMLフォームをフレームワークの仕組みで生成すると、自然にCSRFトークンが発行され、検証される

ってやって担保されてた部分をサーバーサイドをAPIベースにしたときにどう実現できるか?というお話と読み替えてみても良いかもしれません。

ではまた!

Discussion