2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

他の投稿はこちら

TL;DR

  • 非保持型権限委譲 = アプリやデバイス側にトークン等の認証情報を一切持たせない権限アーキテクチャ(特許第7870515号)
  • 認証済みセッションと暗号通信路をサーバー内部でペアリングし、この対応関係が成立している間だけ権限が存在する
  • トークンがないので、盗まれる・漏れる・失効管理する、という問題が発生源ごと消える

はじめに:そのAPIキー、盗まれたらどうなりますか?

.envにAPIキーを書いたことのある人なら、一度は冷や汗をかいたことがあると思います。うっかりGitHubにpushしたキーは数分でクローラーに拾われますし、pushしなくても、アプリに保存したトークンは端末ごと盗まれれば使われます。退職した人が持っていたキー、全部ローテーションしましたか?

私たちはこれを「気をつける」で守っています。.gitignoreに入れる、Secret Managerという金庫に仕舞う、有効期限を短くする、端末に縛る、漏れたらすぐ止められるようにする。対策はどんどん堅牢になっていますが、並べてみると全部「配ったトークンをどう守るか」の話です。どれだけ金庫を頑丈にしても、中に価値ある物が入っている限り、盗まれる可能性があります。

本稿では、トークンを配るのをやめる。権限を端末に置かず、サーバー内部の対応表の一行として成立させる——金庫に入れる物を、最初から作らない構造の話をします。

0. Webとネイティブアプリの連携

Webアプリからローカルのネイティブアプリを呼び出して、サイレント印刷やUSB機器の操作をさせる——そんな構成を以前の記事で紹介しました。

では、そのネイティブアプリに「ログインしたユーザーにだけ使わせたい」というアクセス制限をかけたい場合、どうすればよいでしょうか。

素直に考えると「ネイティブアプリにID・パスワードやアクセストークンを持たせる」になりますが、これは漏洩リスクと運用負荷を抱え込むことになります。

本稿では、この課題を解決するために考案した「非保持型権限委譲」モデルを解説します。

結論を先に言うと、権限を端末に「持たせる」のをやめ、サーバー内部の対応関係として「成立させる」設計です。

1. 従来方式の課題 — 「再利用可能な資格情報」という構造問題

Webアプリ側でユーザーがログイン済みでも、ネイティブアプリは別プロセス(あるいは別端末)であり、ログイン状態をそのまま共有できません。
そこで従来は、ネイティブアプリの設定ファイルにID/パスワードを持たせる、あるいは長期アクセストークンを発行して保存する、といった方法が取られてきました。

どちらも、ネイティブアプリ側に後から再利用できる資格情報を置く方式です。

ここで注意したいのは、サーバー側のパスワードはハッシュ化して「元の値を持たない」形にできるのに対し、再ログインに使う側の資格情報は、実行時に元の値へ戻せる形で持たざるを得ないという非対称性です。
暗号化して保存しても、実行時に復号して使える以上、侵害された環境では取り出される余地が残ります。保存時の保護はできても、「権限そのものをアプリが保持している」という構造は変わりません。

つまり問題は個々の保護策の強度ではなく、盗む価値のあるものが端末に存在するという構造そのものにあります。かといって、これを避けるためにユーザーへ都度入力を求めれば、利便性が著しく低下します。

2. 発想の転換 — セッション・通信路ペアリング

本モデルは、権限の置き場所を端末からサーバー内部へ移します。

システムを、ユーザーをサーバーが認証する認証層と、ネイティブアプリとサーバーが暗号通信を行う権限委譲層に分け、両層を論理的に独立させます。
ネイティブアプリは、ID・パスワードもアクセストークンも保持しません。代わりに、サーバーが次の対応関係を動的に管理します。

fig1_pairing.png

権限は、この対応関係が成立している間だけ、サーバー内部に存在します。

3. システム構成と処理シーケンス

本システムは、サーバー、ブラウザ(中継)、ネイティブアプリの3つで構成されます。処理の流れは以下の通りです。

fig2_sequence.png

[1] Browser --> Server : ログイン(認証済みセッションの確立)
[2] Native  --> Server : 鍵情報を生成し、Browser経由で暗号通信路を確立
[3] Server             : [セッション識別情報 <-> 暗号鍵] の対応関係を登録
                         ※この時点で権限が「成立」する

[4] Browser --> Server : 操作要求を送信(例:「印刷して」)
[5] Server  --> Native : 対応する暗号鍵で暗号化した制御命令を送信
                         ※Browserは復号できないまま中継する
[6] Native             : 鍵情報で復号し、ローカルデバイスや外部装置を制御
[7] Native  --> Server : 処理結果を暗号化して返却(Browser経由)
[8] Server  --> Browser: 画面表示用の処理結果をレスポンス

従来ネイティブアプリが自ら行っていた認証を、ブラウザの認証済み経路に「相乗り」する形で担保している、と見ることができます。

ここでブラウザは、サーバーとネイティブアプリ間の暗号化データを中継しますが、復号する機能を持ちません。中身の読めない「土管」です。

この構成が作り出す性質 — 相互不可知

土管化の帰結として、次の状態が成立します。

  • ブラウザは、自分が何と何を繋いだのかを知らない。 セッションと暗号化された鍵を運ぶだけで、権限の中身に触れられない。
  • ネイティブアプリは、自分が誰として繋がったのかを知らない。 鍵は持つが、セッションIDも認証資格情報も一切受け取らない。
  • 両方を知っているのは、サーバーの対応管理だけ。

認証と認可の「分離」は昔から提唱されてきましたが、既存方式の分離は責務の分離にとどまり、認証の成果物(トークン等)は結局、実行側へ渡っていました。

本モデルは、認証の成果物が実行側に一切流れない、情報の流れのレベルでの分離を実現します。

4. 何が嬉しいのか

① 盗む対象が端末から消える

ネイティブアプリが保持するのは、自ら生成した鍵情報だけです。鍵単体では権限は成立せず、サーバー側の対応関係と揃って初めて有効になります。
「盗まれると困るもの」を守るのではなく、盗む対象そのものを端末から無くす防御です。
しかもユーザーから見れば、ブラウザでログインするだけでアプリが使える——安全性の向上と導入の簡素化が同時に成立します。

② 中継経路を信頼しなくてよい

権限委譲層の機密性は、中継するブラウザや途中経路の安全性に依存しません。仮に中継経路が平文であっても、委譲される権限データと鍵は暗号化されたまま通過します(なお認証層のセッション保護は、従来どおりTLSで行います)。
ブラウザ拡張や開発者ツールが通信を覗ける環境でも、権限の中身は読めません。

③ トークン運用そのものが消える

OAuthやAPIキー方式では、配布したトークンについて有効期限、リフレッシュ、失効伝播、保存場所の保護、端末ごとの棚卸しを考え続ける必要があります。
本モデルではトークンを配布しないため、これらの運用が発生しません。
権限を止めたいときは、端末に散ったトークンを回収するのではなく、サーバー側の対応関係を一行消すだけです。
失効が分散問題ではなく局所操作になります。

④ 片側奪取では権限を再構成できない

認証する端末と実行する装置が物理的に離れている場合——ドローン、車載装置、工場設備、IoT機器——この設計の効果が最も鮮明に現れます。

操作端末が持つのは認証済みセッション、実行装置が持つのは暗号鍵。どちらか一方を奪っても、権限の素材は揃いません。
実行装置が奪取され、メモリから鍵を抜かれたとしても、その装置単体ではセッション側の素材を欠くため、権限主体として機能できないのです。

同じ理由で、漏洩を起点にした横展開も成立しにくくなります。従来方式では漏洩したトークンそのものが別端末・別経路への足場になりましたが、本モデルでは一部の素材をコピーしても、サーバー内の対応関係を別環境で再現することはできません。

⑤ 監査が「誰の認証で、どの装置が、何をしたか」で語れる

トークン方式の監査ログは「どのトークンがどのAPIを呼んだか」を追う形になり、トークンが一度端末へ渡った後のコピー・持ち出し・再利用の経路は追いづらくなります。
本モデルでは権限の成立点がサーバー内部にあるため、誰の認証済みセッションが、どの実行端点に紐付き、その結果として何が実行されたかを、一貫した記録として残せます。

5. OAuth・ゼロトラストとの本質的な違い

OAuthとの違い — スナップショットか、生きた関係か

OAuthのアクセストークンは、発行時点の権限を切り出したスナップショットです。トークンを持つ主体は、その有効期間中、発行時の権限を提示によって行使できます。だからこそ失効の伝播やリフレッシュという管理問題がついて回ります。

本モデルの権限は、行使のたびにサーバー内の対応関係を参照して成立する生きた関係です。実行主体も認証主体も単独では権限を持たず、各主体の素材がサーバーで組み合わさった瞬間にだけ権限が発現します。

トークンを強化するのではなく、「権限の引換券を配る」という設計そのものを無くしている——ここが各種のトークン改良方式との決定的な違いです。

ゼロトラストとの違い

ゼロトラストは「ネットワーク境界を信頼せず、アクセスごとに検証する」思想です。
本モデルはこの思想と高い親和性を持ちますが、分割する対象が異なります。
ネットワークの内外ではなく、権限の成立条件そのものを認証層と権限委譲層に分割し、両層をサーバー内部で組み合わせる。
ゼロトラストの検証原則を、資格情報の配布なしに実装する一つの解、と位置付けられます。

6. トレードオフ — 何を手放しているか

この設計が手放しているものについて記述します。

権限行使のたびにサーバー側の対応関係を参照するため、トークン方式が持つ検証のオフライン性・自己完結性はありません。 リソース側がトークン署名だけで検証を完結できる方式に比べ、サーバーの可用性と参照性能への依存が生まれます。

したがって本モデルが最も効くのは、即時失効・資格情報レス・奪取耐性が性能コストに見合う領域——特権操作、遠隔制御、物理的に奪取されうる装置、監査要件の厳しい環境——です。

7. Webの枠を超える — 「分散セキュアIPC」への一般化

ここまで「ブラウザ」と「ローカルPCのネイティブアプリ」というWeb連携の形で説明してきましたが、このアーキテクチャの本質はWebスタックに閉じていません。

「サーバー」「中継クライアント」「ネイティブアプリ」という名称は機能的役割を指す呼称であり、装置形態・通信プロトコル・物理配置に縛られません。

一歩引いて見れば、これは中継経路の安全性を前提にしない、汎用的な分散セキュアIPC(プロセス間通信)フレームワークとして抽象化できます。

応用① スマートフォンによる共有設備の一時操作

利用者はスマートフォンアプリで認証されます。設備側のQRコード、NFCタグ、BLEビーコンを読み取ると、サーバーが「この認証済み利用者」と「この設備の通信路」を一時的に対応付けます。宅配ロッカーの指定扉を一度だけ開ける、会議室機器を一定時間だけ有効化する、といった操作がこれで成立します。

利用者の認証情報は設備へ渡らず、設備の鍵はスマートフォンへ渡りません。
権限はどちらの端末にも保存されず、サーバー上の一時的な対応関係としてのみ存在します。

応用② 管理対象端点への一時的な操作委譲

企業内PC、サーバー、工場設備、検査装置、エッジゲートウェイなどの管理対象端点にエージェントを配置し、サーバーとの暗号通信路を維持させます。

管理者は組織の認証基盤で認証されます。入口はWeb管理画面に限らず、CLI、モバイル端末、ChatOps、承認ワークフローなど任意です。診断ログ取得や設定変更の要求に対し、サーバーは認証状態・ロール・対象端点・操作内容・承認状態を検証し、条件を満たす場合だけ管理主体と実行端点の通信路を一時的に対応付けます。

実行端点に管理者のアクセストークン、共有アカウント、固定APIキー、保守用パスワードを保存する必要はありません。

端点が侵害されても、そこから資格情報を抜いて別端点へ横展開する経路が絶たれ、かつ「誰の認証と承認に基づき、どの端点で、何が実行されたか」がサーバー側に一貫して残ります。

応用③ バックエンド処理からの一時的な実行委譲

認証主体は人間である必要もありません。バッチ処理、CI/CDパイプライン、監視システムが、事前定義されたポリシーに基づく認証済み主体になります。実行主体はデプロイ対象サーバー、エッジノード、ロボット制御プロセスなどです。

サーバーが認証済みワークフローと実行端点の通信路を対応付け、許可された操作だけを実行させます。
実行端点にCI/CD用の長期トークンや管理者APIキーを配布する必要はなくなります。

近年の自律エージェントに一時的・条件付きの権限を安全に与える、という文脈でも同じ構造がそのまま使えます。

まとめ

非保持型権限委譲は、「認証資格情報の永続化リスク」と「中継環境の脆弱性リスク」を、運用ではなく構成の力で無効化するアーキテクチャです。

権限を端末に持たせるのではなく、セッションと通信路のペアリングによって、サーバー内部の対応関係として成立させる。認証する側と実行する側は互いを知らず、両者を結ぶ知識はサーバーにしか存在しない。

この「認証の成立条件」と「実行の成立条件」の分離は、物理配置やスタックに依存しない設計思想として、特権操作・遠隔制御・自律エージェントといった、これからの分散システムが直面する権限管理にそのまま適用できます。

Q&A

Q. OAuthじゃだめなの?

だめではありません。ただしOAuthは、アクセストークンという「権限の引換券」をアプリに渡す方式です。渡した瞬間から、保存場所の保護、有効期限、リフレッシュ、漏れたときの失効といった、引換券の管理問題が始まります。

本モデルは引換券を渡しません。権限はサーバーの中の対応関係としてだけ存在します。なので、管理問題が発生源ごと消えます。

Q. トークンを渡しても、サーバー側で毎回チェックすれば同じじゃない?

実際、毎回サーバーに問い合わせて有効性を確認する方式もあります。

ただその場合も、アプリが提示するトークン自体は「盗んだ人でも使える通行証」として残ります。本モデルのアプリが持つのは自分で生成した鍵だけで、「提示して使う通行証」がそもそも存在しません。チェックを厳しくするのではなく、盗む物を無くすアプローチです。

Q. じゃあトークンを端末に紐付けて、他の端末で使えなくすれば?

その改良も存在します。ただし「トークン」と「紐付け用の鍵」は結局同じ端末に載るので、端末ごと乗っ取られれば両方揃います。

本モデルは権限の素材を端末を跨いで分離できます。操作する端末にはセッション、実行する装置には鍵。片方を奪われても、権限は復元できません。

Q. ただの暗号化(E2EE)と何が違うの?

暗号通信路の作り方自体は前作と同じです。

違いは使い道です。暗号化が保証するのは「途中で盗み見られない」ことまでで、「誰の権限で動いてよいか」は別の仕組み(トークン等)に頼るのが普通でした。本モデルは、その暗号通信路を認証済みセッションとサーバー内部で結び付けることで、通信路そのものを権限の器にしたところが新しい点です。

Q. ただのセッション管理と何が違うの?

Cookieセッションは「認証した主体=実行する主体」が前提です。

本モデルは、認証する主体(ブラウザ)と実行する主体(ネイティブアプリ)が別で、しかも互いの秘密を知らないまま、サーバー内部でだけ結び付きます。セッション管理の延長というより、セッションと暗号通信路の「ペアリング」です。

Q. ネイティブアプリのメモリから鍵を抜かれたら終わりじゃないの?

鍵単体では権限が成立しません。権限の行使にはサーバー側の対応関係、つまりセッション側の素材も必要だからです。

さらに実装上は、鍵の登録時にアプリの識別情報も一緒に登録しておき、以降の通信で照合する構成にできます。こうすると、鍵だけ抜かれても、別の環境からの通信は正当なものとして扱われません。「トークンをコピーしたら即、別端末から使える」構造とは、漏洩時のリスクの質が違います。

Q. ブラウザのセッションを乗っ取られたら意味なくない?

セッション乗っ取りへの防御は、従来どおりTLSやCookieの保護で行います。そこはこのモデルの守備範囲ではありません。

このモデルが保証するのは、中継やアプリ側から認証情報・鍵・権限データが漏れないこと、そして漏れた断片を別環境に持ち出しても権限を組み立て直せないことです。

Q. localhostのWebSocketって、他のサイトからも繋げるよね?

はい。なのでOriginチェック等の従来対策は引き続き必要です(初回記事のQ&A参照)。

その上で、仮に悪意あるページが中継に相乗りしても、流れているのは復号できない暗号データで、そのページはサーバーの認証済みセッションとの対応関係も持ちません。盗聴もできず、権限も成立しません。中継が信頼できない前提で設計してあるので、相乗りされても権限の窃取には発展しない、という位置付けです。

Q. 一番最初の鍵のやり取りで、中継が偽物の鍵にすり替えたら?

これは本モデルに限らず、鍵を交換する仕組み全般につきまとう「最初の一回をどう信じるか」という問題です。ここは押さえておく必要があります。

まず前提として、ネイティブアプリが鍵を暗号化するのに使う「サーバーの鍵」は、アプリにあらかじめ埋め込んでおく(あるいは正しいものだけを受け入れるよう固定しておく)ことができます。こうしておけば、間に入った中継が別の鍵に差し替えても、アプリはそれを受け付けません。

加えて、アプリの側から「自分が本物であること」を証明し続ける構成も取れます。アプリに署名用の秘密鍵を持たせ、対になる公開鍵をサーバーに置いておき、最初の鍵登録に署名を添え、以降の通信でも同じ鍵で署名し続けるやり方です。秘密鍵はアプリの外に出ないため、中継や第三者にはこの署名が作れません。サーバーは公開鍵で署名を確かめるだけで、「アプリが本物である」ことを毎回検証でき、アプリのすり替えが成立しなくなります。

この署名用の鍵の組は、アプリに同梱して配布する方法のほかに、初回接続時にアプリ自身がその場で生成し、公開鍵だけをサーバーに登録する方法も取れます。秘密鍵は端末の外に一度も出ず、インストールごとに固有の鍵になるため、配布物から鍵を抜かれる心配も、端末ごとに鍵を配って回る手間もありません。初回の登録だけは「このログインセッションで最初に登録してきたアプリ」を本物とみなすことになりますが、二回目以降は署名によって同一性が保証され続けます。

Q. 権限を使うたびにサーバー参照とか、重くない?

対応関係の参照はキー1個のルックアップで、1ミリ秒もかかりません。そのあとに実行される本来の処理(DBクエリ、帳票生成、機器制御)の方が何十倍も重いので、全体から見れば誤差と言えます。

ログイン状態をセッションストアで毎リクエスト確認する負荷は、通常のWebサービスと実質的に同じと言えるでしょう。

Q. サーバーが落ちたら全滅では?

その通りです。検証点がサーバーに集中するため、トークン方式のように「サーバーに聞かなくても検証できる」性質はありません。

ただ、本モデルの主な適用先——自社サービス+専用アプリ、管理サーバー+管理対象の機器——では、サーバーが落ちれば業務そのものが止まります。権限チェックだけ生き残っても意味がないので、実質的な追加リスクになりにくい領域を選んで使う、という整理です。

Q. どこかで使われてるの? 標準化は?

標準化はされていません。本稿は考案したアーキテクチャの解説であり、「非保持型権限委譲」という呼び方も本稿で導入したものです。

権限をサーバー側で毎回判定する方向の仕組み自体は大規模ソリューションにも存在しますが、それらは「誰に何を許すか」というルール側の話で、「アプリが何を持って自分を証明するか」までは変えていません。そこまで踏み込んで、証明に使う資格情報そのものを無くすのが本モデルです。

Q. 標準化されてないなら、他社サービスや既存の基盤とは繋げないのでは?

「標準がない」事は相互運用性の面でデメリットですが、「繋げない」ということではありません。

組織を跨ぐ連携も、相手のサーバーとの間に暗号通信の関係を一本張れば成立します。連携解消のときはその一本を切るだけで、相手側に渡っていた権限がまとめて失効します。
トークンを交換し合う方式との違いは、繋げるかどうかではなく、繋ぎ目に配布物が残るかどうかです。

Q. 実装が大変そう。特殊な暗号ライブラリとかが要るのでは?

いいえ、使う部品はすべて枯れた既製品です。公開鍵暗号で鍵を運ぶ、共通鍵で暗号化する、ログイン状態をセッションで管理する、対応表を1つ持つ——どれも各言語の標準ライブラリや、普通のWebフレームワークに最初から入っている機能だけで組めます。

新しいのは部品ではなく組み合わせ方です。専用のミドルウェアや独自プロトコルの実装は必要ありません。むしろ認可サーバーを別途立ててトークンの発行・検証・更新・失効を作り込む方式と比べると、作る部品の数は少ないくらいです。

Q. オフラインでは何もできなくなるのでは?

いいえ。切れている間にできなくなるのは、サーバーとの新しいやり取り——新しい指示の受信や、データの送信——だけです。アプリそのものが止まるわけではなく、すでに受け取って復号済みの権限や指示に基づく動作は、切断中もそのまま継続できます。

鍵もセッションの有効期間中は保持して再利用できるので、通信が戻れば、再ログインなしで元の権限状態のまま送受信を再開できます。切断中に溜めたデータを、再接続時にまとめて暗号化して送る、という使い方も可能です。

なお、切断中にどこまでの動作を許すかは、サーバーが権限を発行する時点で範囲や期限として制御できます。断続的にしか繋がらない現場の機器は、本モデルがむしろ得意とする環境です。

Q. 前回の記事(特許第6451963号)との関係は?

前回は「信頼できないブラウザ越しに、安全な暗号チャンネルを作る」方法でした。

今回はその上に、「認証済みセッションとその暗号チャンネルをサーバー内で結び付けて、権限そのものを成立させる」層を積んだものです。土管の発明と、土管の上に載る権限モデルの発明、という関係になります。

という内容の

特許を取得しました。(特許第7870515号、国際出願中)

業務で当技術の利用を検討されている方は、お気軽にご相談ください。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?