0
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?

e-Gov電子申請API v2 の OAuth/OIDC 認証フローとトークン設計まとめ

0
Posted at

e-Gov電子申請API v2 の OAuth/OIDC 認証フローとトークン設計まとめ

タグ案: e-Gov OAuth2.0 OpenIDConnect PKCE API

この記事について

行政手続きをオンライン化する e-Gov電子申請API で連携システムを組もうとすると、最初にぶつかるのが「認証・認可をどう設計するか」です。

「アクセストークンを取得して、それを使って各APIを叩く」——ここまでは想像がつきますが、いざ設計を始めると疑問が出てきます。

  • トークンはどう取得するのか。マシン間で完結するのか
  • API を叩くたびに認証し直す必要があるのか
  • トークンはどこにどう保管すればよいのか
  • エラーが返ってきたとき、何が原因か分かるのか

この記事は、公式の e-Gov Developer の仕様(電子申請API v2、確認日 2026-07-22)を読み解いて、実装に入る前に押さえておきたい認証設計のポイントをまとめたものです。

対象読者:e-Gov電子申請APIでの連携システムをこれから設計する方。
前提知識:OAuth 2.0 / OpenID Connect の基本的な用語。
なお、パラメータ名・エンドポイント・有効期限などの固有値は執筆時点の公開仕様に基づきます。実装時は末尾の一次資料で最新を確認してください。


結論:認証モデルの全体像

e-Gov電子申請APIは、API の認可に OAuth 2.0 の「認可コードフロー(Authorization Code Grant)+ PKCE」、利用者の認証に OpenID Connect を使います。役割を分けて言うと次のとおりです。

  • OAuth 2.0(認可):業務APIを叩くためのアクセストークンを発行する
  • OpenID Connect(認証):誰がログインしたか(利用者)を確認する

ここで最大のポイントは、client_credentials(マシン間だけでトークンを取り回す方式)ではないことです。

初回に「人によるブラウザログイン+同意」が必要で、そこで得たリフレッシュトークンが有効な間は、対話なしでアクセストークンを更新し続けられる。


ハマりどころ:「API実行のたびに認可フローをやり直す」必要はない

設計初期にありがちな誤解が、「API を叩く前段で毎回トークンを取り直す」というものです。これは見直しが必要です。理由は2つ。

  1. 認可フローの開始には人の操作が挟まる。 初回のトークン発行には認可サーバでのブラウザログイン・同意が必要で、これを毎回やり直すことはできません(バッチ処理では現実的でない)。なお、認可コードは短命で原則1回限りの使い捨てです。
  2. アクセストークンは有効期限(60分)まで使い回すのが前提。 毎回取り直すのは無駄なオーバーヘッドです。

正しい運用は次の形です。

  • 初回だけ対話認可でトークンを発行する
  • アクセストークンは有効期限まで使い回す
  • 期限が切れたら、リフレッシュトークンで /token を叩いて更新する(対話不要)
  • リフレッシュトークンが失効/最長期限(180日)到達/同意取消のときは、再び対話認可が必要になる

「毎回認証」は非効率で、認可フロー部分は人手が挟まるため自動化もできません。**「トークンを使い回し、切れたらリフレッシュ更新、失効したら再認可」**が基本形です。


エンドポイント一覧(認証・認可)

認可サーバは業務APIとは別ホストです。ベースURL・対象環境は末尾の一次資料で確認してください。

エンドポイント 用途
GET /auth ユーザー認可(認証・同意画面)→ 認可コード発行。初回・再認可時の対話ステップ
POST /token アクセストークンの取得/再取得
POST /token/introspect トークンの有効性検証
POST /logout ログアウト。公式仕様では取得済みの access / refresh トークンが無効化されるとされる

① ユーザー認可:GET /auth(対話・ブラウザ)

パラメータ 必須 内容
client_id ✅ 開発事業者に発行されるソフトウェアID
response_type ✅ code 固定
scope ✅ openid offline_access(offline_access でリフレッシュトークンを要求)
redirect_uri ✅ APIキー発行時に登録したURL(要URLエンコード)
state 推奨 CSRF対策のランダム値
code_challenge 任意※ PKCE用ハッシュ値
code_challenge_method 任意※ S256

※ 仕様上 PKCE は任意ですが、実装では S256 の採用を強く推奨します。

PKCE の作り方に注意。
code_verifier は十分な乱数から生成した 43〜128 文字の文字列。code_challenge は「その code_verifier の SHA-256 ハッシュを BASE64URL(末尾の = パディングなし) で符号化」したものです。通常の BASE64 ではありません。手組みせず OAuth/PKCE 対応ライブラリの利用を推奨します。

認可開始時に state と code_verifier をセッションへ保存し、コールバックで受け取った state を(定数時間比較で)照合してから、code と code_verifier をトークンエンドポイントへ送ってコード交換する——という流れを忘れずに。


② トークン取得/更新:POST /token

ヘッダー

Authorization: Basic {base64(client_id:client_secret)}
Content-Type: application/x-www-form-urlencoded

Authorization: Basic の値は client_id:client_secret を Base64 化したものですが、特殊文字を含む場合の取り扱いで壊れやすいため、curl -u や OAuth ライブラリのクライアント認証機能を使うのが安全です。

ボディ(取得時) — 初回、認可コードと引き換え

grant_type=authorization_code
code={認可コード}
redirect_uri={/auth で指定したもの}
code_verifier={PKCE の元文字列}

ボディ(更新時) — 2回目以降、サイレント更新

grant_type=refresh_token
refresh_token={保管しておいたリフレッシュトークン}

レスポンス(JSON)

フィールド 内容 区分
access_token アクセストークン 標準
expires_in アクセストークンの有効期限(秒) 標準
refresh_token リフレッシュトークン 標準
token_type bearer 固定 標準
id_token IDトークン(OIDC) 標準
scope 付与されたスコープ 標準
refresh_expires_in リフレッシュトークンの有効期限(秒) e-Gov仕様に記載
session_state / not-before-policy セッション状態・有効開始時刻 実装依存の付随項目

client_id / client_secret は、開発事業者に発行される ソフトウェアID / APIキー に対応します。

id_token は「利用者が誰か」を表す OIDC のトークンです。利用する場合は署名・iss・aud・exp 等の検証が必須で、業務APIには id_token ではなく access_token を送ります。利用者確認が不要なら、実装上は access_token だけを扱えば十分です。


③ 業務APIの呼び出し

取得したアクセストークンを Bearer で載せます。

GET /apply/lists
Authorization: Bearer {access_token}
X-eGovAPI-Trial: true   # 任意。付けると「トライアル動作」になる

X-eGovAPI-Trial は動作確認向けのヘッダーです。指定なしで通常動作になります。本番の副作用(実際に申請が到達するか等)は必ず一次仕様で確認してください。


トークンの有効期限

トークン 有効期限(公式記載値)
アクセストークン / IDトークン 60分(3,600秒)
リフレッシュトークン 180日(15,552,000秒)

固定値の直書きに頼らず、実装ではレスポンスの expires_in / refresh_expires_in を正として期限管理するのが安全です(将来の仕様変更に耐えます)。


トークンの保管設計(Azure Key Vault などのシークレットストア)

公式の共通仕様には、次の管理要件が明記されています。

  • APIキー等のクレデンシャルや各トークンは「第三者が参照・取得できない安全な領域で管理」すること
  • 「不要になったアクセストークンは適切なタイミングで無効化」すること

これはそのまま、シークレットストア(Azure Key Vault 等)を使う根拠になります。設計の勘所は以下です。

  1. 本命は client_secret(APIキー)と refresh_token。 特にリフレッシュトークンは180日と長寿命で、実質の「鍵」。最優先で安全に保管します。
  2. リフレッシュトークンのローテーションに注意。 /token を叩くたびにレスポンスで新しい refresh_token が返る運用なら、更新のたびにシークレットストアへ書き戻しが必要です。古い値を放置すると失効し、再ログインが必要になります(Key Vault なら新バージョンとして発行)。
  3. 同時更新の競合を防ぐ。 複数プロセス/インスタンスが同時に更新すると、新旧トークンの保存順が入れ替わって使用不能になり得ます。更新処理は排他制御し、新しい access / refresh を原子的に保存します。
  4. アクセストークン(60分)は短命キャッシュで十分。 毎回シークレットストアに書くとコスト・レイテンシがかさむため、メモリ等でのキャッシュ+期限管理が現実的。保管するなら取得時刻や絶対期限も一緒に持ち、数十秒の安全マージンを引いて期限を判定します(時計ずれ・通信遅延対策)。
  5. 認可アカウント単位でトークンが分かれる。 複数の申請主体を扱うなら、主体ごとにシークレットを分ける設計に(対応関係の正確な用語は一次仕様を参照)。

エラーレスポンスの読み方

エラー処理では、業務APIと認可サーバを分けて考えます。

業務API のエラー(RFC 7807)

業務API(電子申請API)のエラーは RFC 7807 準拠のレスポンスで、原因を3階層で特定できます。

  • status(HTTPステータス)= 大分類
  • title = エラー種別(公式メッセージ一覧で約26種)
  • detail = 具体的な原因(同・130件超)

HTTPステータスの message に出る正式セットは次の8種です(成功コードを含む点に注意。エラーは 4xx / 5xx 側です)。

コード message 区分
200 OK 成功
202 Accepted(受理) 成功
400 Bad Request(リクエスト不正) エラー
401 Unauthorized(認証エラー) エラー
404 Not Found(対象なし) エラー
413 Request Entity Too Large(送信データ超過) エラー
500 Internal Server Error エラー
503 Service Unavailable(停止・メンテ) エラー

title(エラー種別・全26種)

title を見れば、どの系統のエラーかがすぐ分かります。公式メッセージ一覧に載る26種を系統別に整理すると次のとおりです。

系統 title の例
システム/利用不可 システムエラーが発生しました。/不明なエラーが発生したため処理が中断されました。/システムを利用することができません。
入力・データチェック 入力値エラーが発生しました。/申請データチェックエラーが発生しました。/データ取得でエラーが発生しました。入力内容を確認の上、再度送信してください。
ファイル/Zip ファイルサイズエラーが発生しました。/Zip形式ファイル展開処理時にエラーが発生しました。/添付ファイルが見つかりません。
ウィルス ウィルスチェックエラーを検出しました。
受付・期間 受付期間外の手続です。
存在しない(NotFound系) 申請案件が見つかりません。/公文書が見つかりません。/指定された電子公文書が見つかりません。/通知文書が見つかりません。/手続に関するご案内情報が見つかりません。/申請案件に関する通知取得が見つかりません。
プレ印字・様式 プレ印字データを取得できませんでした。/様式情報が存在しません。
納付 納付状況に問題があります。
取下げ 取下げ依頼ができない手続です。
公文書・署名検証 このXMLファイルは、当処理の対象ではありません。/公文書ファイルのタグ構成が不完全です。/公文書署名検証で異常が発生しました。 再度実行して下さい。/添付ファイル名の先頭(または途中)に半角シャープ「#」が付いている電子公文書を検証することはできません。

detail(具体的な原因・130件超)

detail には、そのケースの具体的な原因が日本語で入ります。全件は公式「メッセージ一覧」の別紙(XLSX)にありますが、実装でハンドリングする観点で系統ごとに代表例を挙げます。

  • メンテナンス/システム
    • 現在、システムメンテナンス等により当該機能の利用を停止しています。
    • システムでエラーが発生したため処理が中断されました。
  • 受付期間
    • 指定された手続は現在申請できません。
    • 現在、本手続は受付期間外のため、申請できません。受付期間を確認し、期間内に申請いただけますようお願いいたします。
  • 存在しない(指定値が見つからない)
    • 指定された手続識別子/送信番号/到達番号/納付番号/金融機関名称/初回受付番号/補正情報は存在しません。入力内容を確認の上、改めて送信してください。
    • 該当する到達番号または通知通番が存在しません。
    • 公文書取得期限年月日を過ぎているため、公文書を取得することができません。
  • 必須項目の未入力(多数)
    • 手続識別子/申請届出識別情報ラベル・値/様式ID/様式バージョン/申請書XML/送信番号/対象期間開始日・終了日/取得件数/取得ページ番号/到達番号/お知らせID/通知通番/納付番号/金融機関名称/ファイル名/ファイルデータ/申請データ は必須項目です。入力してください。
  • 形式・桁・文字種(多数)
    • 到達番号は16桁以上18桁以内で入力してください。/手続識別子は16文字で入力してください。/様式IDは18文字で入力してください。/送信番号は18桁で入力してください。
    • 手続識別子・様式ID・到達番号・お知らせIDは半角英数字で/送信番号・納付番号・取得件数・通知通番は半角数字で入力してください。
    • 対象期間開始日・終了日は YYYY-MM-DD 形式で入力してください。
    • 取得件数は 30件(または50件)以下で入力してください。/取得件数の上限を超過しました。取得条件を変更してください。
    • ファイル名/送信データファイル名/申請データファイル名に使用できない文字が入力されています(255byte以内 等)。
  • サイズ・エンコード・Zip
    • 送信されたデータ容量が上限サイズを超えています。データファイルのサイズが上限(100Mbyte)を超えないよう修正し、改めて送信してください。
    • 一括申請データファイル(Zip形式)の解凍に失敗しました。/受信したファイルデータをZip形式ファイルとして処理できませんでした。
    • 送信されたファイルデータのエンコード形式が正しくありません。
    • 一括申請データファイル内の手続フォルダ件数が上限(999件)を超えています。
  • ウィルス
    • 申請書等からウィルスが検出されたため、提出された申請書等を破棄しました。申請データを確認の上、改めて送信してください。
    • ウイルスチェック時にサーバ側でエラーが発生しました。e-Gov利用者サポートデスクにご連絡ください。
  • 納付
    • 既に納付が行われています。/納付期限を過ぎているため、電子納付を行うことはできません。/納付情報が取り消されているため、電子納付を行う必要はありません。/現在、システムのメンテナンス等により、電子納付を行うことができません。
  • 取下げ
    • 取下げ依頼ができない手続です。送信内容を確認してください。
    • 取下げ依頼XML(.手続名称/.依頼年月日)に誤りがあります。
    • 取下げ依頼XML.到達番号とリクエストボディの到達番号が一致していません。
  • 構成管理XML・添付書類・提出先
    • 構成管理XML(.手続番号/.手続名称/.申請種別/.申請書属性情報)に誤りがあります。
    • 構成管理XMLの手続IDが入力パラメータの手続識別子と異なっています。/構成管理XML.初回受付番号とリクエストボディの到達番号が一致していません。
    • この手続の場合、ファイル添付が認められていません/手数料情報は不要/提出先の指定は不要——など、手続とデータの整合エラーが多数。
  • GビズID連携
    • GビズID側で法人情報に登録している郵便番号を修正していただき、再度申請を行ってください。
    • GビズID側で郵便番号を修正していただき、再度申請を行ってください。

実装のコツ:title で大分類のハンドリング(リトライ可否・利用者への表示メッセージ切替)を行い、detail は利用者にそのまま提示できる原因文として扱うと堅牢です。細かな分岐が必要な場合のみ detail の文言(または別紙XLSXの管理番号)を参照します。

上記メッセージ一覧の8種に 403 は含まれません。HTTP 403 は一般にはアプリケーションの認可拒否にも使われますが、e-Gov の業務APIメッセージ一覧の範囲外です。公式は 403 受信時に「接続元IPアドレス+受信時刻を添えて専用窓口へ問い合わせ」を案内しています。

認可サーバのエラー(別形式の可能性・要確認)

/token などの認可・トークンエンドポイントのエラーは、業務APIの Problem Details と同一とは限りません。OAuth 2.0 / OIDC では慣例的に error / error_description 形式が使われます。実装前に、認可サーバ側のエラー形式を一次仕様で確認してください。

401 を受けたときの再試行に注意

アクセストークン期限切れの 401 はリフレッシュ更新で解決しますが、更新後の一律再送は危険です。

  • 安全に再送できるのは GET など冪等な操作のみ。
  • /apply(申請データ送信)のような非冪等APIをむやみに再送すると二重申請になり得ます。まず 401 の内容を確認し、必要なら申請案件一覧・到達番号で結果を照会してから再送可否を判断します。

まとめ

  • 認可は OAuth 2.0 認可コードフロー+PKCE、認証は OIDC。client_credentials ではない。
  • 初回だけ対話認可、以降はアクセストークンを使い回し、切れたらリフレッシュトークンで更新。失効時は再認可。
  • 有効期限はアクセス 60分 / リフレッシュ 180日(実装は expires_in を正に)。
  • クレデンシャルとトークンは安全なシークレットストアで管理。リフレッシュトークンのローテーション書き戻しと同時更新の排他に注意。
  • エラーは業務API=RFC 7807、認可サーバ=OAuth形式の可能性で分けて扱う。非冪等APIの盲目的リトライは二重申請に注意。

行政APIというと身構えがちですが、認証の骨格は一般的な OAuth 2.0 + OIDC です。「初回だけ人が認可、あとは機械が更新、失効したら再認可」という形を押さえれば、設計はぐっと見通しが良くなります。


参考リンク

本記事は執筆時点(2026-07-22)の公開仕様(電子申請API v2)に基づきます。エンドポイント・パラメータ・有効期限などの固有値は、必ず最新の一次資料で確認してください。エラーレスポンスの表記について、e-Gov 仕様は RFC 7807 準拠とされますが、同 RFC は後継の RFC 9457 に更新されています。

0
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
0
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?