Skip to content

SQL 系ストア(sql / ora / npg)で CIBA / Device Authorization Grant が動かない #208

Description

@OsscJpDevInfra

現象

UserStoreTypemem 以外(sql / ora / npg)にすると、CIBA と Device Authorization Grant が動かない。
#207 で入れたストア切り替えで初めて回せるようになり、7 件の不具合が出た。

sql(SQL Server)での E2E 通しは 224 件中 103 件が失敗で始まった。

System.InvalidOperationException: Sequence contains no elements
   at Dapper.SqlMapper.ThrowZeroRows(Row row)
   at ...CibaProvider.ReceiveTokenReq(...)
ORA-01400: ("SCOTT"."DeviceAuthZData"."Id") に NULL は挿入できません
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
  Cannot implicitly convert type 'decimal' to 'long'. An explicit conversion exists (are you missing a cast?)
   at ...DeviceAuthZProvider.ReceiveTokenReq(...)

内訳は次の 3 系統。

A. provider の SQL 分岐(3 方言すべて)

内容 箇所
A-1 Dapper の QueryFirst は、行が無いと例外を投げるnull を返さない)。そのため直後の if (dyn == null)(「レコードなし」の分岐)が到達不能で、存在しない device_code / auth_req_id を渡すと HTTP 500 になる 9(DeviceAuthZProvider 6 / CibaProvider 3)
A-2 Result 列は未応答のとき NULL だが、SQL 分岐は非 null 前提でキャストしていた。GetState は空文字を「未応答」として authorization_pending を返す作りなので、NULL は空文字として渡すのが正しい 6
A-3 RequestObjectProvider.Get が、行が無いとき SQL 分岐だけ null を返していた(Memory 分岐は "")。その nullJsonConvert.DeserializeObject(null) に渡り ArgumentNullException になる 1

A-1 / A-2 は mem では通る(Memory 分岐は別実装)ため、これまで露出していなかった。

B. Oracle の DDL(#206 で追加した分の作り込み)

内容
B-1 CREATE SEQUENCE …; / ALTER TABLE …;行末にコメントを書くと、sqlplus が次の文を飲み込むORA-03405)。結果、後続の表が作られない
B-2 ORA-01400(20 件)。sqlserverIDENTITY(1,1)pstgrsserial で自動採番されるが、Oracle を「シーケンス + NOT NULL」にしたため、Id を渡さない provider の INSERT が落ちるUserClaims だけは provider 側が NEXTVAL を明示しているので通っていた)

C. Oracle の方言(既存)

内容
C-1 Oracle に boolean が無い。 ResultNUMBER(3) で 0 / 1 / NULL。((bool)…) では変換できず、bool.TryParse("1") が失敗して GetStateirregularity_data を返す。例外は出ないため、authorization_pending / access_denied が出ないまま 14 件が静かに失敗する
C-2 Oracle の NUMBERdecimal で返る。 dynamic 経由の暗黙変換は通らず RuntimeBinderException(4 件)。CibaProvider((long)dyn.AuthReqExp) と明示していて、これが「CIBA は通るのに Device AuthZ が落ちる」差そのものだった

環境

バージョン 1st_agent_ph1d9645c0 時点)
構成要素 CommonLibrary、files/resource/MultiPurposeAuthSite/Sql/oracle/Create_UserStore.sql
ターゲット net48 / net10.0(npg は Npgsql が #if NETCORE のみのため net10.0 だけ)
UserStoreType sql / ora / npgmem では再現しない)

再現手順

  1. 対象の DBMS を起動し、Create_UserStore.sql でストアを作る
  2. E2E テストで UserStoreType を切り替えられるようにする(SQL 系のストアが未検証) #207 のオプションでストアを指定して E2E を通す
.\2_RunAllTests.ps1 -Launch -UserStoreType sql -ConnectionString '...;Encrypt=false;'
.\2_RunAllTests.ps1 -Launch -UserStoreType ora -ConnectionString '...'
.\2_RunAllTests.ps1 -Launch -UserStoreType npg -ConnectionString '...'

期待する動作

4 ストアで E2E の結果が同じになる。 ストアの違いは実装の内側の話で、プロトコルの応答は変わらないはず。

調べたこと

修正前後を実測した。

UserStoreType 修正前 修正後
mem 222 成功 / 0 失敗 / 2 Skip 222 / 0 / 2(変化なし)
sql 103 失敗 → 12 失敗 222 / 0 / 2
ora 18 失敗 → 14 → 8 222 / 0 / 2
npg 111 / 0 / 113 111 / 0 / 113(Skip 113 は net48 が Npgsql 非対応のため)

ビルドは エラー 0 / 警告 45(net48)・39(net10.0)で、警告は増えていない。

A-1 / A-2 は 6f6eda1 の親にも同じ形で存在し(QueryFirst(DeviceAuthZProvider 6 箇所・CibaProvider 3 箇所、bool result = dyn. が 3 箇所)、今回の変更で持ち込んだものではない。
B-1 / B-2 は 6cdf3b8#206)で Oracle 側に表を足したときの作り込み。

静的な確認では出ない種類の不具合である。 いずれも「SQL 系ストアに実際に回した」ことで初めて分かった。#207 のストア切り替えが無ければ、mem が緑である限り気付けない。

利用者への影響

あり。 mem 以外のストアでは、CIBA と Device Authorization Grant が使えない
(存在しないコードを渡すと HTTP 500、Oracle では応答が irregularity_data になる)。
mem のみで運用している場合は影響しない。

なお、修正は既に作ってあり、この Issue の番号で同一コミットとして入る。
上の「調べたこと」の実測表は、その修正の前後を測った値である。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions