2024年2月3日土曜日

OpenID Providerを作る)仮名に加えて匿名をサポートする

こんにちは、富士榮です。

厳密にはOpenID Connectの仕様に定義されていませんが、以前実装したPairwise識別子(PPID)に加えて匿名の識別子(Transient Identifier)をサポートしたくなるシーンが存在するので、対応を入れていきたいと思います。

その前にこれまでのおさらいです。


識別子の種別、および仮名と匿名の違い

識別子は主体を一意に特定するために利用される属性(群)を表しますが、名寄せのリスクなどに応じてどのような値を返すべきかについて十分な考慮が必要です。

そもそも識別子には公開、仮名(かめい)、匿名の3種類が存在します。
区分共有範囲OpenID Connectでの区分SAMLでの区分解説
公開全体publicunspecifiedやemailaddress全RPに対して共通の識別子を送出する
仮名RPpairwisepersistent特定のRPに対して一意の識別子を送出する
匿名なし-transient毎回異なる識別子を送出する

上記の表に示した通り、全てのRPに対して同じ識別子の値を送出するpublicなタイプ、同一のRPに対しては毎回同じ値を送出するPairwiseがOpenID Connectにおいては定義されています。ただし、特定のケースにおいて同一識別子出会ったとしても毎回送出する識別子を別のものに変えたい、というケースも存在します。SAMLにおいてはこのケースを想定してnameid-formatとしてpersistent(いわゆる仮名であるPairwise)に加えてtransient(匿名)を定義していました。
ここで仮名と匿名の違いを正しく理解しておきましょう。
  • 仮名:連続性がある。つまり外野から見ると誰だか分からないが、特定のRPから見ると一意に主体を識別できる
  • 匿名:連続性がない。外野から見ても特定のRPから見ても一意に主体を識別することができない

この辺りはかなり昔にイベントでしゃべった資料が出てきたので貼り付けておきます。


実装してみる

前置きが長くなりましたが、実装してみましょう。
基本的にはpairwiseの中の種別として実装をしてみたいと思いますので、設定ファイルにスイッチを作っておき、指定されたオプションによって仮名か匿名かを決めていきたいと思います。

.envに識別子のタイプを指定できるようにします。
# 識別子の種別:PERSISTENT or TRANSIENT
IDENTIFIER_TYPE=TRANSIENT

次に識別子を生成するところのロジックを分岐させます。
oauth2/oauth.js
// 識別子タイプの判定(Persistent or Transient)
let PPID;
switch(process.env.IDENTIFIER_TYPE){
case "TRANSIENT":
// 魔界異なる識別子を生成する
PPID = crypto.randomUUID();
break;
case "PERSISTENT":
default:
// Pairwise識別子の生成
PPID = utils.createPPID(payload.local_identifier, req.query.redirect_uri);
}

以上で完成です。

初回アクセスでの識別子(sub)の値

2回目のアクセス時の識別子(sub)の値


同じRPへのアクセスですがsubの値が変わっていることがわかります。

今回のコードを含めこちらに挙げてありますので参考にしてみてください。


0 件のコメント: