概要
Shopifyアプリは、ストアのデータ(注文・商品・顧客など)を勝手に見られるわけではありません。「あなたは誰か(認証)」と「何を見てよいか(認可)」の2つの関門を必ず通る必要があります。
非エンジニア向けに言い換えると、次のようになります。
認証(Authentication) = 社員証のチェック。アプリの画面からアプリのサーバーへ届いたリクエストが、本物のShopify管理画面から来たものかを確かめる。ここで使うのがセッショントークン。
認可(Authorization) = 入室許可証。ストアオーナーが「注文は見てよい」「顧客情報は見てよい」と許可を出す。その結果アプリが受け取るのがアクセストークン。
この2つは別物で、セッショントークンではShopify APIを呼べません。API呼び出しに使えるのはアクセストークンだけです。ここを混同した実装は、必ずどこかで詰まります。
出典: Authentication and authorization
何ができるか
やりたいこと |
使う仕組み |
業務課題の例 |
|---|---|---|
管理画面に埋め込んだアプリで、Cookieを使わず安全にログイン状態を保つ |
セッショントークン |
ブラウザのCookie制限(Safari等)でアプリが動かなくなる事故を防ぐ |
インストール時の画面のちらつき・リダイレクトをなくす |
Shopify managed installation |
導入初日の離脱を減らす。「入れたのに画面が何度も飛ぶ」というクレームをなくす |
マーチャントの操作なしに夜間バッチでAPIを叩く |
オフラインアクセストークン |
深夜の在庫同期・レポート集計を無人で回す |
操作したスタッフの権限を尊重してデータを出し分ける |
オンラインアクセストークン |
「アルバイトには売上を見せない」といった社内統制をアプリ側でも守る |
使う機能に応じて後から権限を追加してもらう |
optional_scopes(任意スコープ) |
初回インストールのハードルを下げ、必要になった時だけ追加許可を求める |
不要になった権限を返上する |
appRevokeAccessScopes |
トークン漏洩時の被害範囲を狭める。セキュリティ監査での説明材料になる |
権限が変わったことを検知する |
app/scopes_update Webhook |
権限が減らされた時に機能を自動でオフにし、エラー多発を防ぐ |
認証 — セッショントークンの仕組みと制約
Shopify管理画面の中に表示されるアプリ(埋め込みアプリ)は、セッショントークンを使わなければなりません。理由は、ブラウザがサードパーティCookieを制限しており、従来のCookie方式では動作しなくなるためです。
Shopifyは、Cookieを使い続けているアプリについてアプリ審査プロセスで移行を要請することがあり、その要請は「即時対応が必要」と明記されています。
項目 |
内容 |
実務上の意味 |
|---|---|---|
形式 |
JWT(JSON Web Token) |
ストア名・ユーザーID・有効期限などが入っている |
有効期限 |
1分 |
リクエストのたびにApp Bridgeから取り直す。使い回すと必ず失敗する |
署名 |
クライアントシークレットで署名 |
バックエンドで検証すれば、なりすましを防げる |
API呼び出し |
できない |
Shopify APIを叩くにはアクセストークンへの交換が必要 |
対応アプリ形態 |
シングルページアプリ(SPA)のみ完全サポート |
マルチページ構成のアプリはSPA的に振る舞うよう改修が必要 |
見落としやすい注意点として、広告ブロッカーがセッショントークンの動作を妨げることがあります。App Store申請時の自動チェックが進まない場合、広告ブロッカーを無効にして操作し直すようShopifyが案内しています。
インストール方式は2つ、推奨は明確に片方
Shopify managed installation(推奨) |
Authorization code grant(従来方式) |
|
|---|---|---|
スコープの宣言場所 |
設定ファイル( |
アプリのコード側で都度指定 |
インストール中のリダイレクト |
なし |
あり(画面のちらつきが起きる) |
Shopifyからアプリへの呼び出し |
なし(Shopify側で完結) |
あり |
スコープ変更時 |
デプロイするだけでShopifyが処理 |
OAuthフローを自前で組み直す |
Shopifyの評価 |
推奨 |
「劣化したユーザー体験(degraded user experience)」と明記 |
アプリの種類ごとに使える組み合わせは以下のとおりです。
アプリの種類 |
インストール方式 |
トークン取得方式 |
|---|---|---|
管理画面に埋め込むアプリ |
Shopify managed installation(推奨) / authorization code grant |
Token exchange(推奨) / authorization code grant |
スタンドアロンアプリ |
Shopify managed installation(推奨) / authorization code grant |
authorization code grant のみ |
管理画面で作るカスタムアプリ |
作成時に自動でインストール済み |
管理画面でトークンを発行 |
新規案件では、「管理画面埋め込み + Shopify managed installation + Token exchange」が事実上の標準です。Shopify CLIで生成する雛形アプリはこの構成になっています。
出典: Enable Shopify-managed installations / Authentication and authorization
アクセストークンの2つのモード
オフライン(既定) |
オンライン |
|
|---|---|---|
紐づく相手 |
ストア |
操作している個々のスタッフ |
有効期限 |
期限付き / 無期限の2種類(後述) |
ログアウト時、または24時間後のいずれか早いほう |
権限の範囲 |
アプリに付与された全スコープ |
そのスタッフが持つ権限に制限される |
主な用途 |
バックグラウンド処理、Webhook受信後の処理、夜間バッチ |
スタッフが画面を操作している最中の処理 |
取得方法 |
指定しなければこちら |
明示的にリクエストが必要 |
オンラインモードで気をつける点は3つあります。
権限のないデータを要求すると
403 Forbiddenが返ります。トークンが失効していれば401 Unauthorizedです。この2つを区別して処理する必要があります。アプリ未インストールのストアでオンラインモードをリクエストした場合、インストール操作をするスタッフが必要な全スコープを持っていないとインストール自体が失敗します。権限の弱いスタッフが導入作業をすると詰まります。
キャッシュを持つ場合はスタッフ単位でキャッシュを分ける必要があります。分けないと、権限の違うスタッフに他人の見える範囲のデータを見せてしまいます。
最重要 — オフライントークンの期限付き移行(期日あり)
本日の最重要トピックです。公開アプリには期限が切られた強制移行があります。
これまでオフラインアクセストークンは無期限でした。アプリをアンインストールするかシークレットを失効させるまで、同じトークンがずっと使えます。裏を返せば、漏洩したら永久に悪用できるということです。Shopifyはこれを解消するため、2025年12月に期限付きオフラインアクセストークンを導入しました。
期日 |
内容 |
|---|---|
2025年12月 |
期限付きオフライントークンのサポート開始 |
2026年4月1日以降 |
この日以降に作成された公開アプリは、期限付きトークンの使用が必須 |
2027年1月1日 |
それ以前に作成された公開アプリの移行期限 |
2027年1月1日以降 |
無期限トークンでREST / GraphQL Admin APIを呼ぶ公開アプリはエラーが返る |
カスタムアプリとマーチャントが作成したアプリは対象外です。自社が公開アプリを持っている場合は、2026年内に対応を計画に組み込む必要があります。
期限付きトークンの数値は以下のとおりです。
項目 |
値 |
意味 |
|---|---|---|
アクセストークンの寿命 |
3600秒(1時間) |
1時間ごとに更新処理が走る前提の設計が要る |
リフレッシュトークンの寿命 |
7776000秒(90日) |
更新のたびに90日が再設定される |
リフレッシュトークンの再利用 |
1回限り |
使うと即座に無効化される |
アプリ+ストアあたりの本数 |
1本のみ |
新しく取ると古いほうのリフレッシュトークンは即無効 |
運用設計で押さえるべき点を挙げます。
リフレッシュのレスポンスを受け取り損ねた場合は、同じリフレッシュトークンですぐ再送するのが正しい対応です。短いリトライ猶予の中であればShopifyは同じ結果を返します。猶予を過ぎると、そのリフレッシュトークンは二度と使えません。
90日間まったくアクセスがなくリフレッシュトークンが失効した場合、マーチャントがアプリを開き直す必要があります。無人で復旧できません。長期間放置されるストアで無言の障害になります。
無期限トークンから期限付きトークンへの移行は、ストアごとに1回限りで、後戻りできません。交換に成功した時点で元の無期限トークンは失効します。無期限に戻すには、マーチャントの操作を伴う取得フローをやり直すしかありません。
移行にあたっては、セッション保存領域に
expires_at/refresh_token/refresh_token_expires_atの3項目を追加する改修が必要です。既存アプリでは地味に影響範囲の広いDB変更になります。
出典: Offline access tokens / Expiring offline access tokens required for all public apps as of January 1, 2027 / Expiring offline access tokens required for new public apps as of April 1, 2026
アクセススコープ — 必須と任意の使い分け
設定ファイルには2種類のスコープを書けます。
scopes(必須スコープ) |
optional_scopes(任意スコープ) |
|
|---|---|---|
いつ許可を求めるか |
インストール時にまとめて |
インストール後、アプリから都度 |
マーチャントが拒否できるか |
できない(拒否=インストールできない) |
できる |
後から取り消せるか |
できない |
できる |
動的にリクエストできるか |
できない |
できる |
業務目線での使い分けはこうなります。インストール時に求める権限が多いほど、マーチャントは警戒して離脱します。「注文も顧客も商品も全部読ませてください」といきなり出るアプリは、導入検討段階で敬遠されます。基本機能に必要な最小限だけを scopes に置き、追加機能を使おうとしたタイミングで optional_scopes を求める設計にすると、初回導入のハードルが下がります。
スコープを変更したときの挙動は、増やす場合と減らす場合で非対称です。
scopesを増やした場合 — マーチャントが次にアプリを開いたときに承認画面が出ます。承認するとapp/scopes_updateWebhookが発火します。承認されるまで新しいデータは読めません。scopesを減らした場合 — 確認画面は出ず、マーチャントがアプリを開いた時点で自動的にアクセス権を失います。同じくapp/scopes_updateが発火します。optional_scopesを追加しただけでは何も変わりません。アプリが動的にリクエストし、マーチャントが承認して初めて付与されます。
動的リクエストの制約も明確です。
scopesに書いたスコープは動的にリクエストできず、動的に取り消すこともできません。スタンドアロンアプリでリクエストURLを使う場合、指定できるのは設定ファイルで宣言済みの
optional_scopesのサブセットに限られます。埋め込みアプリなら
shopify.scopes.request()でリダイレクトなしにモーダルを出せます。ユーザー体験としてはこちらが圧倒的に優れます。
不要になった権限は appRevokeAccessScopes で返上できます。Shopifyはトークン漏洩時の被害を抑えるため、返上を推奨しています。
Authorization code grant を自前実装する場合の必須チェック
スタンドアロンアプリや、Shopify managed installation を使っていない既存アプリは、この方式を自前で実装することになります。セキュリティチェックを1つでも飛ばすと重大な脆弱性になるため、Shopifyはテンプレート利用を強く推奨しています。
必須の検証は3つです。いずれか1つでも失敗したら、エラーとして処理を中断しなければなりません。
検証 |
内容 |
飛ばすとどうなるか |
|---|---|---|
HMAC検証 |
リクエストが本当にShopifyから来たか署名で確認 |
第三者が偽の認可リクエストを送り込める |
nonce(state)検証 |
認可要求時に発行したランダム値と、署名付きCookieの値が一致するか |
CSRF攻撃の対象になる |
shopドメイン検証 |
|
不正なドメインへ誘導される |
さらに落とし穴が3つあります。
Authorization code grant のHMAC検証手順は、Webhookの検証手順とは異なります。同じコードを流用するとどちらかが壊れます。
Shopify管理画面は
X-Frame-Options: DENYのため、iframe内から直接リダイレクトできません。埋め込みアプリではembedded=1を見てApp Bridgeのredirect actionでiframeを脱出してから、通常のリダイレクトを行う必要があります。マーチャントは認可画面のURL内の要求スコープを改変できます。したがってアプリは、アクセストークンを使う前に必要なスコープが実際に付与されたかを必ず確認しなければなりません。readとwriteを両方要求した場合は、writeだけを確認します(readはwriteに含まれるため、レスポンスから省かれます)。
アプリ画面へ戻すリダイレクトでは、shop と host パラメータを必ず付ける必要があります。これがないとApp Bridgeが初期化できず、セッショントークンを取得できません。なお host はBase64のパディング(=)が除去されているため、言語によってはデコード前にパディングを補う必要があります。
クライアントシークレットのローテーション
クライアントシークレットは、アクセストークンの取得とWebhookの署名検証の両方に使われる、アプリの最重要機密です。従業員の退職やソースコードへの誤コミットに備えて、定期的な交換(ローテーション)が推奨されています。
手順の要点と、事故になりやすい箇所は以下です。
手順 |
内容 |
注意点 |
|---|---|---|
新しいシークレットを作成 |
Dev Dashboard の Settings から Rotate |
新旧が一時的に併存する |
Webhookの設定 |
新旧どちらの署名も受け付けるようにする |
Shopifyは「最も古い、まだ失効していないシークレット」で署名する。新しいほうだけで検証すると全Webhookが弾かれる |
OAuthの設定 |
トークン取得は新しいシークレットのみ使用 |
— |
リフレッシュトークンを生成 |
Dev Dashboard で発行 |
発行から1時間で自動失効。作業を止めずに進める必要がある |
保存済みトークンを更新 |
全ストア分のアクセストークンを取り直す |
全部終わるまで旧シークレットを消してはいけない |
旧シークレットを失効 |
Dev Dashboard から revoke |
失効させると、それに紐づくアクセストークンも削除される |
ローテーションで最も多い事故は、Webhook署名の切り替えを先にやってしまい、全ストアのWebhookが検証エラーで落ちるというものです。Shopifyの署名は古いほうのシークレットを使い続けるため、新旧両対応の期間を必ず設けます。
重大なセキュリティ侵害が起きた場合は話が別です。この場合は新しいシークレットを作る前に、まず侵害されたシークレットを即座に失効させるべきとされています。高リスクな状況では、アプリのダウンタイムは避けられない場合があるとShopifyも明記しています。
自社ストア向けのアプリであれば、grant_type=client_credentials でクライアントID・シークレットから直接アクセストークンを取得できます。このトークンは24時間で失効します。
出典: Client credentials / Rotate and revoke client credentials
できないこと・注意点のまとめ
セッショントークンでShopify APIは呼べません。認証と認可は別物です。
セッショントークンの寿命は1分です。使い回しは必ず失敗します。
セッショントークンはSPAのみ完全サポート。マルチページ構成のアプリは改修が必要です。
広告ブロッカーがセッショントークンを妨げることがあります。審査の自動チェックが止まる原因になります。
公開アプリは2027年1月1日までに期限付きオフライントークンへ移行が必須。以降、無期限トークンでのAPI呼び出しはエラーになります。
2026年4月1日以降に作成された公開アプリは期限付きトークン必須です。
無期限→期限付きの移行はストアごとに1回限り、不可逆です。元のトークンは失効します。
リフレッシュトークンは1回限りの使用。猶予時間を過ぎると再利用できません。
リフレッシュトークンが90日で失効すると、マーチャントがアプリを開き直すまで復旧しません。
scopesに書いたスコープは動的にリクエストも取り消しもできません。スコープを減らす場合、マーチャントへの確認なしに自動で失われます。
オンラインモードで未インストールのストアに入れる場合、実行スタッフの権限が足りないとインストールが失敗します。
Shopify管理画面のiframe内からは直接リダイレクトできません(
X-Frame-Options: DENY)。マーチャントは認可URLのスコープを改変できます。トークン使用前の付与確認は必須です。
Shopifyは最も古い未失効のシークレットでWebhookに署名します。ローテーション中は新旧両対応が必要です。
シークレットを失効させると、紐づくアクセストークンも削除されます。
Authorization code grant のHMAC検証手順はWebhookのそれとは別物です。
Shopifyは authorization code grant を「劣化したユーザー体験」と明記しています。新規案件で選ぶ理由はほぼありません。
この機能で解決できる業務課題
導入初日の離脱を減らす — Shopify managed installation でリダイレクトとちらつきをなくし、インストール直後の体験を改善できる
権限要求によるインストール敬遠を避ける — 必須スコープを最小限にし、任意スコープで後追い許可を求めることで、検討段階の心理的ハードルを下げられる
社内統制の維持 — オンラインアクセストークンでスタッフごとの権限をアプリ側でも尊重でき、「アプリ経由なら誰でも売上が見える」という抜け道を塞げる
無人運用の実現 — オフラインアクセストークンで夜間バッチや在庫同期を人手なしで回せる
セキュリティ監査への回答 — トークンの有効期限・ローテーション手順・不要権限の返上を、プラットフォーム標準の仕組みとして説明できる
保守契約の根拠づくり — 2027年1月1日の期限付きトークン移行という明確な期日があるため、既存の公開アプリを持つ顧客への改修提案の根拠になる
前回(2026-07-30)からの変更点
changelog を再確認しましたが、7月24日以降に新規の追加項目はありません。最新は変わらず 07.24 の「無効なメタフィールドクエリがエラーを返すようになる(2026-10以降)」です。
本日のテーマに関わる直近の重要な変更は、changelog上では以下の3件です。いずれも新着ではありませんが、期日が近づいており今後の案件で必ず論点になるため、あらためて整理しておきます。
2026年5月20日 — 全公開アプリに対し、2027年1月1日から期限付きオフラインアクセストークンが必須になることが告知された(Breaking changes扱い)
2026年3月20日 — 2026年4月1日以降に作成される新規公開アプリには期限付きトークンが必須になることが告知された(Action required扱い)
2025年12月10日 — オフラインアクセストークンが有効期限とリフレッシュに対応した
この3件は一連の流れです。Shopifyは無期限トークンを段階的に廃止しようとしています。既存の公開アプリを保守している場合、2026年内に移行対応を予算化しておく必要があります。
併せて注目すべき動きとして、**2026年4月1日に「アプリ所有のmetaobjectはアクセススコープなしで使えるようになった」**という変更があります。アプリ専用のデータ置き場については権限要求が不要になっており、要求スコープを減らす方向の設計余地が広がっています。
出典: Developer changelog / App-owned metaobjects can be used without access scopes
次回以降に整理する予定のテーマ
Agents(shopify.dev/docs/agents) / Checkout拡張の制約 / Metafields・Metaobjects のデータモデル / App Store 審査要件と課金(App Pricing移行) / Protected customer data(保護対象の顧客データ)の追加要件 / Flow・POS・Customer accounts の拡張ポイント / App Events(アプリの利用状況データ)
未確認事項
クライアントシークレットを同時に何本まで保持できるか、および新旧併存の上限期間はドキュメントに記載がありません。明示されている時間は「Dev Dashboardで発行するリフレッシュトークンの1時間」のみです。
リフレッシュトークンの再送猶予(リトライウィンドウ)の具体的な長さは公開されていません。
Protected customer data(保護対象顧客データ)に該当するスコープの一覧と追加要件は本日未着手です。認可設計に直結するため、次回以降に整理が必要です。
Agents(shopify.dev/docs/agents)のリファレンスは本日も未着手です。

