すでに直面している課題もあるでしょう。アプリのログインは動作し、ユーザーは Google、Microsoft、またはメールでサインインでき、API はトークンを受け入れます。そこからが本題です。このユーザーは別アカウントの請求書を見られてしまわないか? デスクトップアプリはアクセストークンをローカルにキャッシュすべきか? Capacitor ビルドで、WebView とネイティブ層の間で状態を漏らさずに同意を扱うにはどうすべきか?
ここからアプリ認可は単なるチェック項目ではなくなり、製品の信頼性、インシデント対応、そしてアプリストアの審査結果にまで影響し始めます。クロスプラットフォームアプリ、特に Capacitor や Electron では、難しいのは認可の概念を理解することではありません。ブラウザの前提が通用しない場所、プラットフォームごとにセキュアストレージの挙動が異なる場所、そしてクライアント側での手抜きがサーバー側のリスクにつながる場所で、いかに実装するかです。
目次
- アプリ認可(App Authorization)の真の意味とは
- 認可を構成する要素
- 一般的な認可モデルとプロトコル
- OAuth 2.0 フローの仕組み
- セキュリティ上の脅威と必須のベストプラクティス
- Capacitor と Electron の実装パターン
- セキュアなアプリ認可への道
アプリ認可(App Authorization)の真の意味とは
ユーザーがアプリをインストールし、「Google で続行」をタップしてサインインに成功すると、連絡先やカレンダーデータの読み取りを許可するか尋ねる同意画面が表示されます。この瞬間には、アクセス権の両面が含まれています。サインインは本人確認を行い、同意画面は本人確認後にアプリが何をできるかを定義します。
この違いは、今もチームを悩ませます。 認証 ユーザーが誰であるかを証明します。 認可 そのユーザー、セッション、またはアプリが何にアクセスできるかを決めます。IDは建物に入るためのもの。キーはどのドアを開けられるかを決めます。
アプリ開発では、この違いが重要です。チームはログインフローのセキュリティを固めても、その後の設計が不十分になりがちだからです。トークンを過信してサーバー側の権限チェックをスキップしたり、本来ポリシーで管理すべきアクセスルールをクライアント側で決めさせたりします。こうして「ユーザーがログインしている」状態が、いつの間にか「ユーザーが過剰な権限を持っている」状態へと変質してしまうのです。
認可(Authorization)は、信頼を具体的な形にするプロセスです。ユーザーは、アプリが自分を認識していることだけを気にしているわけではありません。自分が許可したものだけにアプリがアクセスすることを気にしています。
3つのアクターを押さえておきましょう:
- ユーザー サインインし、同意を与える可能性があるユーザー。
- アプリケーション ユーザーに代わってアクセスを要求するアプリケーション。
- リソースオーナーまたは API データを保護し、決定を強制する主体。
実際、アプリの認可はMFAのようなより強力なアクセス制御と重複する部分があります。2023年1月時点で、 世界のユーザーの約66%がMFAを利用していましたや 2024年のJumpCloud調査では、1,000人以上のSME ITプロフェッショナルのうち83%が、すべての社内リソースへのアクセスにMFAを必須としていました これは、 JumpCloudのMFA統計まとめ。これは認可を置き換えるものではなく、アクセス要求を行う資格を持つユーザーの基準を引き上げるものです。
チームでロール、スコープ、委任アクセスを整理している場合、 Capacitor アプリにおけるRBACによるOTA更新の保護方法 というガイドは、ここで議論されている実装の選択肢を補完する有用な資料です。
認可を構成する要素
認可をトークン内の魔法のようなものとして扱わなくなると、はるかにシンプルになります。より良いメンタルモデルはホテルです。
ホテルのキーカードは良いメンタルモデル
ゲストがフロントデスクへ行き、身分証を提示します。ホテルは本人確認を行い、宿泊記録を作成し、ルームキーを発行します。そのカードは、ドアを開けるたびにゲストの身元を証明するものではありません。限られた期間中、特定の場所へのアクセスを許可する権限を保持しているだけです。
アプリも同じ仕組みで動きます。

重要な点は、カード自体がポリシーではないということです。カードはポリシーを反映しているだけです。ドアには、そのカードが特定のロックを開けるべきかどうかをチェックするシステムが必要です。ソフトウェアでは、それがあなたの API ゲートウェイ、バックエンドミドルウェア、ポリシーエンジン、またはサービスレベルの認可レイヤーです。
実際のシステムで重要な用語
プリンシパル
アクセスを要求する主体。通常はユーザーですが、デバイス、バックグラウンドジョブ、またはサービスアカウントの場合もあります。
リソース
保護対象となるもの。プロジェクト、請求書、管理用ルート、ファイル、API エンドポイント、またはデータベース内の単一レコードなど。
適用範囲
要求されているアクションの集合。プロフィールの読み取り、ファイルのアップロード、請求管理など。スコープは狭く、分かりやすいものであるべきです。
同意
要求されたアクセスレベルに対するユーザーの承認。優れた同意画面はリクエスト内容を明確に伝えますが、不適切なものはすべてを要求してしまいます。
アクセストークン
認可が成功した後、クライアントがリソースサーバーに提示する認証情報。機密データとして扱うべきです。
実装上のミスの多くは、「ユーザーがトークンを持っているなら、アクセスを許可する」という一つの思い込みから生まれます。これは本番環境では通用しません。トークンが有効であっても、現在の操作、テナント、環境、またはリソースに対して不適切な場合があります。
モバイルおよびデスクトップチームにとって、トークンの扱いは特別な注意を要します。ストレージは、望むかどうかに関わらず認可システムの一部だからです。クライアントがアクセス成果物を無造作に保存すると、後でポリシー設計が救ってくれません。このガイドは モバイル開発者向けの安全なトークン保存 について、リリース前に確認する価値があります。
持続可能なルールはシンプルです。認証、同意、トークン発行、サーバーサイドの強制執行を、頭の中だけでなくcodeでも分離してください。これらを混同するチームは、多くの場合、誤ったレイヤーで権限バグをデバッグすることになります。
一般的な認可モデルとプロトコル
チームが「OAuthを使っている」と言うとき、それはしばしば複数の異なることを同時に意味しています。これが混乱の一因です。プロトコルと認可モデルは、異なる問題を解決します。
プロトコルがやり取りを処理する
OAuth 2.0 は主に委任認可(delegated authorization)に関するものです。アプリがユーザーのパスワードを直接扱わずに、ユーザーに代わって動作するための権限を要求し、取得する方法を定義します。
OpenID Connect(OIDC)は OAuth 2.0 の上に構築され、ID 情報を追加します。実用上、OAuth は「このアプリで何ができるか」、OIDC は「誰がサインインしたか」を判断するのに役立ちます。
この違いは Capacitor や Electron アプリで重要です。多くのバグは、access token が期待される場面で ID token を使ったり、サインインに成功すれば API が後続のすべてのアクションを許可するはずだと決めつけたりすることから始まります。実際はそうではありません。
これをハイブリッドアプリに組み込むなら、ステップバイステップの Capacitor アプリ向けの OAuth2 実装ガイド は、実装フローで避けられるミスを大幅に防いでくれるリソースです。
モデルが意思決定ロジックを担います
自社システム内でも、アクセスを許可すべきかを判断するルールは依然として必要です。そこで登場するのが RBAC と ABAC です。
ロールベースアクセス制御(RBAC) は、権限を admin、editor、support agent、viewer といったロールにマッピングします。理解しやすく、監査可能で、比較的安定しているため、よく使われます。 BrightSec による安全な認証と認可に関する解説によれば, RBACは、きめ細かな権限を適用するための業界標準のメカニズムです。また、そこで引用されているエビデンスは、階層的なロール構造と定期的な権限監査を伴うRBACの実装が エンタープライズ環境のセキュリティインシデントを最大40%削減することを示しています.
属性ベースのアクセス制御(ABAC) は、ロールだけでなく属性に基づいて判断を行います。これには、部署、デバイスの状態、レコードの所有権、アカウントティア、地域、リクエスト時刻、セッションがMFAを通過したかどうかなどが含まれます。ABACはより表現力が高い反面、ポリシーを十分に文書化しないと、中身が不透明になりやすい側面もあります。
実践的なルール: 製品の権限が安定していて人間が理解しやすいなら、RBACから始めましょう。コンテキストが実際に判断を変える場合にABACを追加しましょう。
RBAC vs. ABAC の比較
| 基準 | ロールベースアクセス制御(RBAC) | 属性ベースのアクセス制御(ABAC) |
|---|---|---|
| 基本的な考え方 | ロールでアクセスを許可 | 属性を評価してアクセスを許可 |
| 最適 | 社内ツール、ダッシュボード、管理パネル | マルチテナントアプリ、規制対象のワークフロー、コンテキスト依存のアクセス |
| 推論しやすさ | チームや監査人が理解しやすい | より柔軟だが、デバッグは難しい |
| 変更管理 | ロールの追加・変更 | ポリシーと属性ルールの調整 |
| よくある失敗パターン | ロールの乱立 | ポリシーの乱立と隠れたエッジケース |
| 例 | 「サポート担当者はチケットを閲覧できる」 | 「サポート担当者は、シフト勤務中に担当地域のアカウントのチケットを閲覧できる」 |
最も高度なモデルを選んでも特別な評価はありません。より良い選択は、チームが一貫して適用できるものです。多くのプロダクトのコードベースでは、広範なアクセス境界にはRBAC、所有権・テナント・デバイス状態などの例外には的を絞った属性を使うことを意味します。
OAuth 2.0 フローの仕組み
OAuthの解説は抽象的すぎることが多いです。実際のアプリでは、特にクライアントシークレットを安全に保持できない Capacitor やElectronアプリのようなパブリッククライアントでは、シーケンスが重要になります。
ユーザーがログインをタップすると何が起きるか
ユーザーが Capacitor アプリを開き、「GitHub でログイン」をタップします。アプリはPKCEの code verifierと、そこから派生した code challengeを作成し、システムブラウザまたはセキュアなブラウザタブで認可サーバーへユーザーを送ります。アプリは、自身が開始したリクエストへのレスポンスであることを検証できるよう、state も含めます。

認可サーバーでは、必要に応じてユーザーがサインインし、要求されたアクセスを承認します。その後、サーバーは直接使える長期間有効な認証情報ではなく、認可 code を付けてリダイレクトで戻します。アプリは、設定済みのリダイレクトURI経由でその code を受け取ります。
次に、アプリは code をトークンと交換します。このプロセスでは PKCE が極めて重要です。アプリは元の code verifier を、認可 code と共に送信します。サーバーはこれを事前に送られた code challenge と照合します。一致すればトークン交換は成功します。もし誰かが code を傍受しても、verifier がなければ交換は失敗します。
だからこそ、ネイティブおよびハイブリッドクライアントには PKCE が不可欠です。これらのアプリはパブリッククライアントです。攻撃者が bundle を検査したり、code のパスをリバースエンジニアリングしたり、ローカル状態を改ざんしたりできると想定すべきです。PKCE は、リダイレクトベースのフローにおける最も一般的なリスクの一つを軽減します。
code でこのシーケンスを実装する前に、視覚的に確認したい方へ簡単なウォークスルーを用意しました:
クロスプラットフォームアプリがよくつまずくポイント
プロトコル自体は単純ですが、実装はそう単純ではありません。
Capacitor アプリは通常、次のいずれかで失敗します:
- サインインに埋め込み WebView を使う システムブラウザではなく埋め込み WebView を使うと、想定されるセキュリティ境界が損なわれ、Cookie の挙動が一貫しなくなる可能性があります。
- リダイレクト状態の消失 ブラウザからネイティブシェルにアプリが戻る際に起こります。
- トークンをブラウザストレージにそのまま保存する Web アプリとしてプロジェクトが始まり、チームがモバイル向けストレージを見直さなかったためです。
Electronアプリには別種の課題があります。チームは時折、レンダラープロセスに認証ロジックを過剰に任せ、厳格な境界なしにIPC経由でトークンを露出し、デスクトップアプリを信頼できる環境とみなします。そうではありません。パッケージ化されたデスクトップアプリにも、敵対的クライアントを前提とする考え方が必要です。
リフレッシュの挙動も意図的に設計する価値があります。アクセストークンは期限切れにし、セッションはクリーンに復旧できるようにすべきです。また、リフレッシュロジックが複数の同時リクエスト間で競合状態を生まないようにすべきです。これは セキュアなトークンリフレッシュフローガイド は、リトライループや古いセッションの混乱に陥らずにその部分を構築するための確かなリファレンスです。
実装上の習慣が1つあるだけで、多くの場合に効果を発揮します。OAuthハンドシェイクは、入出力が明確な小さな認証モジュールに隔離してください。リダイレクト処理、トークン解析、リフレッシュロジックを、コンポーネントやフック、場当たり的なネットワークユーティリティに分散させないでください。
セキュリティ上の脅威と必須のベストプラクティス
認可のバグは、code レビューでは劇的に見えることはほとんどありません。利便性のように見えるのです。ここでスコープを広げ、そこでトークンをキャッシュし、UIがすでにボタンを隠しているからとサーバー側のチェックを省く。そしてアプリをリリースすると、そうした近道が攻撃対象になります。
繰り返し起きる失敗
モバイルエコシステムは有用な警告サインを示しています。 DeepStrikeのモバイルセキュリティ統計によると、, テストされたモバイルアプリの95%が、認証と認可に関連するOWASP MASVSコントロールの少なくとも1つに失敗しました。や 分析したモバイルアプリの85%にセキュリティ上の欠陥が見つかったセキュリティマーケティングのすべてのフレーミングを受け入れる必要はありませんが、その核心シグナルは真剣に受け止めるべきです。認可のミスはよくあります。

パターンはよく見かけるものです:
- トークンの漏洩 安全でないストレージ、ログ、クラッシュレポート、またはレンダラーからアクセス可能な状態から。
- スコープの過剰指定 すべてを要求する方が、同意を時間とともに進化させるよりも簡単だからです。
- クライアントサイドでの強制 アプリが未認可のアクションを非表示にしているが、API はそれを受け入れている場合。
- リプレイ攻撃とリダイレクト攻撃 状態、PKCE、またはリダイレクトURIの検証が不十分な場合。
- 権限のドリフト 定期的なレビューなしでチームがロールや例外を追加し続けると起こります。
バックエンドが保護されたすべてのアクションで認可を検証していなければ、それはアプリの認可ではありません。ただのUIのヒントです。
実践的で信頼できるチェックリスト
最小権限の原則を、後からの修正作業ではなくデフォルトにしてください。実際のプロジェクトでは、各トークンでできることを減らし、トークンの置き場所を減らし、各認証情報が使える期間を短くするということです。
- スコープを絞って要求する: 今ユーザーが使っている機能に必要な権限だけを求めてください。アプリが同意を後回しにできるなら、そうしてください。
- サーバー側で強制する: クライアントは信頼できないものとして扱ってください。ボタン、ルート、隠し画面などはセキュリティ境界ではありません。
- プラットフォームのセキュアストレージを使う: モバイルでは、平文のローカルストレージではなく、プラグイン経由でネイティブのKeychainやKeystoreにアクセスしてください。デスクトップでは、機密情報をレンダラーから容易にアクセスできない場所に保管してください。
- stateとリダイレクト処理を検証する: 認証レスポンスは、アプリが開始したリクエストと一致する必要があります。
- 有効期限は短く、リフレッシュは慎重に: 有効期限の短いアクセストークンは漏洩時の被害を抑えます。リフレッシュ処理はクリーンにローテーションし、fail closed で動作すべきです。
- 必要なときに失効させる: セッションの終了やインシデント対応には、トークンの無効化と再認証の強制を含めるべきです。
- 入力を検証し、通信を保護する: HTTPS、適切な場面での証明書ピンニング、入力検証はすべて重要です。認可は周辺の脆弱性を突いてバイパスされ得るからです。
ストア経由でアプリをリリースするチームにとって、認証設計はAPIの露出やコンプライアンス審査にも関わってきます。この要約は App Store のコンプライアンスに向けた API セキュリティ基準 認可チェックリストと併せて読むのにうってつけです。
最後に見落としがちなポイントです。最小権限は内部ツールにも当てはまります。管理パネル、サポートコンソール、ステージングアプリは、多くの場合もっとも機密性の高い操作を扱うのに、社内でもっとも緩い権限管理になりがちです。
Capacitor と Electron の実装パターン
クロスプラットフォームアプリの認可は、アプリを単なる「パッケージ化されたブラウザ」だと考えるのをやめればもっと簡単になります。Capacitor も Electron も、ネイティブストレージ、プロセス境界、リダイレクト処理を尊重するパターンが必要です。

Capacitor の効果的なパターン
Capacitor の場合は、PKCE を使ったシステムブラウザ経由の OAuth と、適切なディープリンクまたは App Link のコールバックをサポートするプラグインや認証ライブラリを使ってください。例えば、 capacitor-oauth2 を使えば code の実装におけるボイラープレートを大幅に削減できますが、トークンの保存方法とリフレッシュの挙動は明示的に管理し続ける必要があります。
実用的な構成は次のとおりです:
- 認証コーディネーター: ログインを開始し、状態を追跡してコールバックを処理します。
- トークンサービス: ブラウザストレージではなく、ネイティブのセキュアストレージ経由でトークンを保存します。
- API クライアント: アクセストークンを付与し、リフレッシュ時に1回リトライし、回復不能な失敗時には強制サインアウトします。
- ポリシーを考慮したバックエンド: トークンのクレームをサーバー側の認可チェックにマッピングします。
ハイブリッドアプリのライフサイクルに適合するセッション管理ツールも必要です。そのレイヤーの選択肢を検討しているなら、 セキュアなセッション管理向けの Capacitor プラグイン アプローチを比較するのに適しています。
トークンリフレッシュの最小構成を擬似コードで示すと次のようになります:
async function authorizedFetch(request) {
let token = await tokenStore.getAccessToken()
let response = await api(request, token)
if (response.status !== 401) return response
const refreshed = await auth.refresh()
if (!refreshed) {
await auth.signOut()
throw new Error('Session expired')
}
token = await tokenStore.getAccessToken()
return api(request, token)
}
重要なのは構文ではなく、リフレッシュを一元管理して、各画面が独自のセッション挙動を勝手に実装しないようにすることです。
特に注意が必要なElectronのパターン
Electronではより厳格な境界が必要です。可能な限り、トークン交換とセキュアストレージはメインプロセスで扱ってください。レンダラーに生のトークンを渡して正しく動作することを期待するのではなく、限定的なIPCメソッドだけを公開しましょう。
デスクトップアプリはモバイルアプリよりも制御しやすいと感じがちですが、その感覚を「保証」ではなく「リスク」として捉えてください。
次のショートカットは避けてください:
- レンダラーからアクセスできるlocalStorageにトークンを保存しない 回避できるなら、回避してください。
- すべてのウィンドウに広範な認証コンテキストを共有させるのは、 ウィンドウの用途とセッションの有効期間を確認しない限りやめましょう。
- preloadスクリプトを過信しないでください。 プロセス分離や明示的な API の境界の代わりにはなりません。
運用の可視性も重要です。Splunkの アプリケーションセキュリティ要件の概要によると、アプリケーションの認可は継続的なアクティビティ監視およびロギングと統合されるべきであり、同資料で引用されているベンチマークデータによると、認可イベントを積極的にログ記録・監視している組織は、 不正アクセスの試行の95%を15分以内に検知しています。実務では、拒否されたアクション、トークンリフレッシュの失敗、ロール変更、同意の取り消し、異常なリソースアクセスパターンをログに記録することを意味します。
リリースプロセスにハイブリッドアプリのアップデートが含まれる場合、このエコシステムにおける一つの選択肢は Capgo, Capacitor や Electron アプリ向けに署名付き Live Updates を提供します。これ自体が認可を実装するわけではありませんが、認証ロジックやリダイレクト処理、セッション code に緊急の修正が必要になったとき、どれだけ早く修正をリリースできるかに影響します。
セキュアなアプリ認可への道
優れたアプリ認可は、一つの判断で決まるものではありません。一連の判断がすべて噛み合っている必要があります。ユーザーを正しく認証し、必要なアクセスだけを要求し、OAuth 2.0 with PKCE のような安全なフローでトークンを交換し、シークレットを適切な場所に保存し、毎回サーバー側で権限を強制する必要があります。
Capacitor や Electron チームにとって最も重要なのは、境界部分での規律です。ブラウザ時代の近道は、ネイティブストレージ、ディープリンク、デスクトップのプロセス境界、アプリ審査要件に直面すると通用しません。トラブルを避けられているチームは、特別なことをしているわけではありません。スコープ、セッション管理、サーバー側チェック、監査可能性について一貫しているだけです。
現在の認証まわりが複雑に感じるなら、それは普通のことです。まずは境界を一つずつ固めましょう。フローを直す。ストレージを直す。アクセスルールを UI から外に出す。許可されていないものを要求されたときに気づけるログを追加する。
そうすれば、安全なアプリ認可は管理しやすくなります。理論上シンプルになるのではなく、code でより安全になるのです。
Capgo を使えば、ストア審査を待たずに Capacitor や Electron アプリへ修正を配信できます。認証フロー、トークン処理、セッションのバグをすばやく修正したいときに重要です。クロスプラットフォームリリースのより細かな管理、対象を絞ったロールアウト、ロールバック対応を求めるなら、 Capgo アプリの認可スタックと併せて検討する価値があります。