spree-auth-permissions について
Spree 6 のスタッフ、インテグレーション、顧客に対する認可を解説するスキルです。権限キー、API キーのスコープ、レコード単位のアクセス制御、ロール管理、権限カタログの拡張を扱います。
主な機能
- 01スタッフのロールと権限キー
- 02インテグレーションの API キースコープ
- 03顧客の所有権による認可
- 04Admin API の認可フロー
- 05拡張権限スコープの登録
活用シーン
- 01店舗スタッフのロール設定
- 02API スコープによる連携アクセス制限
- 03Spree 拡張への権限追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ spree/ agent-skills --skill spree-auth-permissionsインストール後、Claude Code で/spree-auth-permissionsを入力して読み込まれたか確認します。
詳細
Spree 認証と権限
Spree 6 には 3 つのプリンシパルがあり、それぞれ認可の方法が異なります。
| プリンシパル | 認証方法 | 認可方法 |
|---|---|---|
スタッフ (Spree.admin_user_class、デフォルトは Spree::AdminUser) | POST /api/v3/admin/auth/login からの JWT(aud: admin_api) | 現在のストアで保有するロールの権限キー |
| インテグレーション(サーバー間) | X-Spree-Api-Key のシークレットキー sk_… | キーのスコープ(ロールと同じキー) |
顧客 (Spree.customer_class、デフォルトは Spree::Customer) | 公開可能キー pk_… +任意の JWT(aud: store_api) | 所有権:スコープ付きクエリと Spree::Storefront::AccessPolicy |
マーケットプレイスの出品者は 4 つ目のサーフェスです(/api/v3/seller、JWT aud: seller_api + X-Spree-Seller-Id)。詳しくは spree-marketplace を参照してください。
このスキルには、すべての基盤となる 2 つのルールがあります。
- キーで制限するのはレコードの種類であり、対象の行ではありません。
write_ordersは「注文を書き込める」という意味であり、どの注文が対象になるかはコントローラーのスコープ付きクエリ(current_store.orders、current_seller.products、current_user.wishlists)によって決まります。コントローラーを追加する場合は、スコープを設定する責任があります。 - レコードの状態に関するルールは、権限ではなくモデルとワークフローに属します。 「確定済みの注文は削除できない」というルールはシークレットキーにも適用されなければならず、シークレットキーがロールを介することはありません。
スタッフのロールはデータです
Spree::Role は、権限の対象(バックオフィスのスタッフなら Spree::Store、出品者チームなら Spree::Seller)に属し、permissions(JSON 配列)にフラットな権限キーのリストを保持します。権限セットのクラスや Ruby で定義されたロールはありません。
- キーは
read_<resource>/write_<resource>の形式です。write_xはread_xを含みます(Spree.permissions.expand_keys)。 - ロールの付与と削除には同じ制限が適用されます。
adminロールを付与または削除できるのはadminロールを持つユーザーだけです。それ以外のユーザーが付与または削除できるのは、自身が保有するキーを持つロールに限られます。また、ストアには常に少なくとも 1 人の管理者が必要です(403「ストアには少なくとも 1 人の管理者が必要です。」)。空のロールリストを割り当てることも、ロールの削除として扱われます。 - すべてのストアには、そのストア内の「あらゆる操作」を意味する保護された
adminロールが 1 つあります。名前の変更、編集、削除はできず、permissionsリストは無視されます(can :manage, :allが適用されます)。 - ロール名は所有者ごとに一意です。そのため、2 つのストアがどちらも「Manager」というロールを持つことができます。
- スタッフまたは保留中の招待が関連付けられているロールは削除できません。
mutable: falseを設定すると、ダッシュボードでロールが読み取り専用になります。
ロールの管理
ストアのほかの管理方法に合ったものを選んでください。
-
ダッシュボード: Settings → Roles(権限ピッカーはカタログから描画されます)。
-
Admin API:
/api/v3/admin/roles(CRUD)、/api/v3/admin/permissions(付与可能なカタログ)。どちらにもread_staff/write_staffが必要です。spree api post /roles -d '{"name":"Support","permissions":["read_orders","read_customers"]}'await adminClient.roles.create({ name: 'Fulfillment staff', permissions: ['read_orders', 'write_fulfillments', 'read_products'], }) -
シード(
db/seeds.rb)— ロールにはresourceが必要です。store = Spree::Store.default role = Spree::Role.find_or_initialize_by(name: 'support', resource: store) role.update!(permissions: %w[read_orders read_customers write_customers]) admin = Spree.admin_user_class.find_by!(email: '[email protected]') admin.add_role('support', store) # looks the role up by name + resource
不明なキー、またはロールの対象に付与できないキーは、バリデーションに失敗します。write_seller_profile を持つストアロールは保存できません。
スタッフを招待するには、Settings → Users → Invite を使うか、adminClient.invitations.create({ email, role_id }) を呼び出します(invitation.created が発行され、メールが送信されます)。role_id は必須です。招待がデフォルトで admin ロールになることはありません。また、呼び出し元にはそのロールを付与する権限が必要です。招待一覧には承諾リンク(アカウントを作成するトークンを含む)は表示されません。必要に応じて adminClient.invitations.acceptanceLink(id) → GET /api/v3/admin/invitations/:id/acceptance_link から取得してください。これには write_staff に加え、招待のロールを付与する権限が必要です(出品者の場合:sellers.invitations.acceptanceLink(sellerId, id) / Seller API の invitations.acceptanceLink(id))。招待を再送信するとトークンが更新されるため、以前のリンクは機能しなくなります。ローカル環境で管理者を作成するには、spree user create を実行します(デフォルトストアの admin ロールが付与されます)。
権限カタログ
ピッカーに表示されるグループ分けに従ったコアキーの全リストは、spree-api-v3/references/scopes.md にあります。実行時には GET /api/v3/admin/permissions で確認できます。シークレットキーのスコープは Spree::ApiKey.known_scopes から取得できます(スタッフに付与可能なすべてのキーと、read_all / write_all)。
知っておくと便利な点:
- 金銭に関連する領域は個別のリソースです。
payments、refunds、gift_cards、store_creditsはordersの対象外です。「注文は見られるが返金はできない」場合に、特別な対応は必要ありません。 - スタッフ管理には
read_staff/write_staff(/admin_users、/invitations、/roles)を使用します。 api_keysとwebhooksは機密性が高いため、settingsとは分けられています。write_api_keysを持つ呼び出し元が発行できるキーのスコープは、自身がすでに持っているものに限られます。- カスタムフィールドの値は親リソースに従います(
write_productsで商品カスタムフィールドを操作できます)。定義はsettingsに含まれます。 - エクスポート専用のスコープはありません。各エクスポートタイプには、エクスポート対象リソースの読み取りキーが必要です。インポートには書き込みキーが必要です。
read_dashboardに対応する書き込みキーはありません。
拡張機能のスコープを登録する
# config/initializers/spree.rb (or your engine's initializer)
Spree.permissions.register_scope(:reviews, group: :catalog, resources: -> {
[SpreeReviews::Review]
})
シグネチャ:register_scope(name, group:, resources:, write: true, audiences: [:store], read_only_for: [])。
groupはピッカー内のセクションを指定します。:analytics、:orders、:catalog、:customers、:sellers、:loyalty、:marketing、:settings、:access、または独自のグループを指定できます。行は登録順に表示されます。resourcesは、CanCanCan の対象(クラスまたはシンボル)を返すラムダです。遅延評価されるため、読み込み順は問いません。write: falseを指定すると、読み取り専用スコープ(read_<name>のみ)が登録されます。audiencesには、そのキーを保持できるロールが属するすべての対象を列挙します。デフォルトは[:store](スタッフ)です。%i[store seller]を指定すると、マーケットプレイスの販売者ロールにも公開されます。:storeを含めない場合、そのスコープはスタッフ用ピッカー、read_all/write_all、発行可能なシークレットキーから除外されます。read_only_for: %i[seller]を指定すると、その対象に読み取りキーのみを付与します。allという名前は予約されており、指定するとArgumentErrorが発生します。同じ名前を再登録すると既存の登録が置き換えられます。Spree.permissions.unregister_scope(:name)で登録を解除できます。settings、staff、api_keysを別の対象に公開しないでください。
ピッカーのラベルは spree.permissions_catalog.resources.<name>.label / .description の下にローカライズします。
次に、Admin API コントローラーでスコープを宣言します。
module Spree
module Api
module V3
module Admin
class ReviewsController < ResourceController
scoped_resource :reviews # index/show → read_reviews; everything else → write_reviews
protected
def model_class = SpreeReviews::Review
def serializer_class = SpreeReviews::Api::V3::Admin::ReviewSerializer
def resource_permitted_attributes = %i[rating body status]
end
end
end
end
end
spree:api_resource ジェネレーター(spree-resource を参照)は両方を生成します。Admin コントローラーに scoped_resource :reviews を追加し、対応する register_scope 行を config/initializers/spree.rb に追加します(--permission-group でグループを指定します。デフォルトは catalog)。さらに、config/locales/spree_reviews.en.yml にラベルを追加します。手書きのコントローラーでも両方が必要です。スコープを登録せずに scoped_resource だけを指定した場合、エンドポイントにアクセスできるのは read_all / write_all キーと admin ロールのみです。ほかのスタッフはアクセスを拒否され、read_reviews を持つキーも発行できません。
ゲートの仕組み(Admin API)
各 Admin API コントローラーでは scoped_resource :name を宣言します。別の方法で認可するコントローラーでは skip_scope_check! を呼び出し、必要に応じて only: または jwt_only: true を指定します。どちらも宣言していないコントローラーにリクエストが届くと MissingScopedResource が発生し、デフォルトで拒否されます。各リクエストでは、次の処理が行われます。
- アクションを
read_(index、showと、コントローラーのread_actionsに含まれるすべてのアクション)またはwrite_(カスタムのメンバーアクションであるcancelを含む、それ以外すべて)に割り当てます。 - シークレットキー:
current_api_key.has_scope?("write_orders")を確認し、該当しない場合は 403 を返します。{ "error": { "code": "access_denied", "message": "API key lacks scope: write_orders", "details": { "required_scope": "write_orders" } } } - JWT スタッフ: 現在のストアでユーザーのロールキーを展開したもの(
Spree::Ability#permission_keys)を確認し、該当しない場合は"details": { "required_permission": "write_orders" }を含む 403 を返します。adminロールはすべての権限を許可します。 - ゲート通過後、キーはレコードレベルのチェック用に CanCanCan ルールへコンパイルされます。
required_permissionを含まない 403 は、ユーザーがキーを持っているものの、レコードレベルのルールによってアクションが拒否されたことを意味します。
リクエストに JWT とシークレットキーの両方が含まれる場合は JWT が優先され、ユーザーのロールが適用されます。リクエストされたストアにロールを持たないスタッフユーザーは、有効なトークンがあっても拒否されます。
埋め込みデータもゲートで制御されます。 エンドポイントはそれ自体のキーで制御されますが、別の種類のレコードを取得する ?expand= セグメントは、呼び出し元が対応する読み取りキー(orders→read_orders、payments/payment_splits→read_payments、customer(s)→read_customers、gift_card(s)→read_gift_cards、store_credit(s)→read_store_credits)を持っていない場合は除外されます。また、read_gift_cards を持たない呼び出し元には、ギフトカードのコードがマスキングされます。独自の Admin コントローラーでは、別の権限で保護されるデータをシリアライズする前に holds_permission?('read_x') を使用してください(JWT スタッフとシークレットキーの両方でゲートと同じ判定を行います)。
GET /api/v3/admin/me は permission_keys(フラットなリスト)と、ダッシュボードが UI のゲート制御に反映する CanCanCan ルールのダンプを返します。UI でボタンを非表示にしても、認可にはなりません。 強制されるのは API ゲートだけです。
シークレットキーの詳細
- スコープはキーの作成後、変更できません。インテグレーションに許可する操作を変更するには、新しいキーを発行し、古いキーを失効させてください。
- パブリッシュ可能なキーは、1 つのチャネルにバインドできます(
channel_id。こちらも変更できません)。バインドされたキーは、サーバー側でリクエストのチャネルを設定し、競合するX-Spree-Channelヘッダーは拒否されます。 - 最小限のスコープでキーを発行してください:
spree api-key create --type secret --scopes read_orders,write_fulfillments。
Spree::Ability と ability_class について
CanCanCan は、キーゲートの背後でレコードレベルのルールに引き続き使用されます。すべてのスタッフ権限(Admin API の JWT スタッフ、Seller API のセラー、インポートとエクスポート)は、Spree.ability_class(Spree::Dependencies.ability_class。デフォルトは Spree::Ability)から構築されます。権限カタログでは表現できないルールが必要な場合は、次のように差し替えます。
# app/models/my_app/ability.rb
module MyApp
class Ability < Spree::Ability
def initialize(user, options = {}) # keep this signature
super # options[:store]; options[:resource] = the seller on the Seller API
cannot :destroy, Spree::Order # add can/cannot rules AFTER super
end
end
end
# config/initializers/spree.rb
Spree::Dependencies.ability_class = 'MyApp::Ability'
変更されない点は次のとおりです。
- キーゲートが最初に実行されます。 カスタム権限クラスは、キーで許可されているレコードを拒否できます(
required_permissionを含まない 403)が、権限キーがないリクエストを通過させることはできません。 - シークレット API キーはこの権限クラスを参照しません。 スコープのみで制御される
Spree::ApiKeyAbilityを使用します。 - セラーがいない場合の
GET /api/v3/seller/meの応答は、常にコアのSpree::Abilityから構築されるため、追加したルールがこの応答に漏れることはありません。 - Store API: 顧客の認可には CanCanCan をまったく使用しません(以下を参照してください)。
一覧で返す内容を絞り込む場合、権限ルールを追加するより、スコープ付きクエリを変更するほうが簡単なことがよくあります。「キャンセル済みの注文は返金できない」といった状態に関するルールは、モデルまたはワークフローに設定してください。
ストアフロントの認可(Store API)
顧客にロールはなく、Store API では CanCanCan を使用しません。アクセス権は所有権によって決まり、次の 2 つの方法で適用されます。
- スコープ付きクエリ。 すべてのストアコントローラーはストアと所有者を通じて読み込みます。例:
storefront_access_policy.scope(Spree::Wishlist.for_store(current_store))。 Spree::Storefront::AccessPolicy:readable?(record, token:)、writable?(record, token:)、scope(relation, token:)を備えた単一のオブジェクトです。- デフォルトでは、呼び出し元がレコードを所有します(
record.customer_id == user.id)。ゲストは何も所有しません。 - カート、注文、注文グループの場合、JWT による所有者、またはゲストトークン(
X-Spree-Token)の所持者が所有者です。カートまたは注文が完了すると、書き込みは拒否されます。 - 企業(B2B)の場合、そのノードまたは祖先ノードのいずれかで権限を持つメンバーが対象です。
- 拒否されると
Spree::Storefront::AccessDeniedが発生し、403access_deniedとして描画されます。
- デフォルトでは、呼び出し元がレコードを所有します(
顧客所有のカスタムリソースでは、コアのパターンに従ってください。
class Spree::Api::V3::Store::SavedListsController < Spree::Api::V3::Store::ResourceController
prepend_before_action :require_authentication!
protected
def scope
storefront_access_policy.scope(MyApp::SavedList.for_store(current_store))
end
def model_class = MyApp::SavedList
def serializer_class = MyApp::Api::V3::SavedListSerializer
def resource_permitted_attributes = %i[name]
end
アクセスを所有者の範囲を超えて許可する必要がある場合(企業全体での購入情報の可視化、共有ウィッシュリストなど)に限り、ポリシーを差し替えてください。サブクラスを作成し、super を呼び出します。
# app/models/my_app/company_access_policy.rb
class MyApp::CompanyAccessPolicy < Spree::Storefront::AccessPolicy
def scope(base, token: nil)
return base.where(company_id: approver_company_ids) if base.klass <= Spree::Order && approver?
super
end
end
# config/initializers/spree.rb
Spree::Dependencies.storefront_access_policy_class = 'MyApp::CompanyAccessPolicy'
承認必須や支出上限のようなアクションの拒否には、このポリシーを使用しないでください。これらはチェックアウトのワークフローにおける validate フックです(spree-workflows、spree-b2b を参照)。/customers/me/* は設計上、所有者のみが対象です。
認証戦略(ログインプロバイダー)
ログイン方法は利用面ごとにプラグイン可能です。POST …/auth/login の provider フィールドで、レジストリから戦略を選択します。省略した場合は email(パスワード)が使用されます。
| 利用面 | レジストリ | ユーザークラス | JWT aud | リフレッシュトークン |
|---|---|---|---|---|
| Store API | Spree.store_authentication_strategies | Spree.customer_class | store_api | レスポンス本文内 |
| Admin API | Spree.admin_authentication_strategies | Spree.admin_user_class | admin_api | /api/v3/admin/auth の HttpOnly クッキー |
| Seller API | Spree.seller_authentication_strategies | Spree.admin_user_class | seller_api | /api/v3/seller/auth の HttpOnly クッキー |
各利用面はそれぞれ固有のオーディエンスのみを受け付けるため、顧客トークンを Admin API に対して再利用することはできません。Spree は iss: spree を設定した HS256 JWT を発行します。署名シークレットは Spree::Api::Config[:jwt_secret_key](環境変数 SPREE_JWT_SECRET_KEY)、次に認証情報の jwt_secret_key、次に JWT_SECRET_KEY、最後に secret_key_base の順に解決されます。有効期間:顧客 JWT は 1 時間(jwt_expiration)、管理者 JWT は 5 分(admin_jwt_expiration)、リフレッシュトークンは 30 日です。
組み込み OIDC(スタッフ SSO)
Spree::Authentication::Strategies::OidcStrategy は、任意の OpenID Connect 発行者(Entra ID、Okta、Google Workspace、Keycloak、Auth0)で動作するリダイレクト戦略です。
# config/initializers/spree.rb
Rails.application.config.after_initialize do
Spree.admin_authentication_strategies.add(
:entra,
Spree::Authentication::Strategies::OidcStrategy.configure(
issuer: "https://login.microsoftonline.com/#{ENV['ENTRA_TENANT_ID']}/v2.0",
client_id: ENV['ENTRA_CLIENT_ID'],
client_secret: ENV['ENTRA_CLIENT_SECRET'],
redirect_uri: 'https://shop.example.com/api/v3/admin/auth/callback/entra',
label: 'Microsoft Entra ID'
)
)
# Optional: SSO-only staff login
# Spree.admin_authentication_strategies.remove(:email)
end
ダッシュボードは GET /api/v3/admin/auth/providers からプロバイダー一覧を取得し、GET /api/v3/admin/auth/callback/:provider でログインを完了します。スタッフアカウントが自動プロビジョニングされることはありません。 既知の ID はログインできます。メールアドレスが検証済みのメールクレームと一致する既存アカウントは、その ID を採用します。それ以外はすべて拒否されます。IdP のディレクトリがメールアドレスを管理している場合を除き、trust_unverified_email: false のままにしてください。
カスタムストラテジー(サードパーティーの JWT、Firebase、Cognito など)
# app/models/my_app/auth/external_jwt_strategy.rb
class MyApp::Auth::ExternalJwtStrategy < Spree::Authentication::Strategies::BaseStrategy
def provider = 'external_idp'
def authenticate
payload = verify_with_jwks(params[:token]) # pin algorithms, verify iss + aud
user = find_or_create_user_from_oauth(
provider: provider,
uid: payload.fetch('sub'),
info: { email: payload['email'], first_name: payload['given_name'], last_name: payload['family_name'] }
)
success(user)
rescue JWT::DecodeError, KeyError
failure(Spree.t('api.unauthorized'))
end
private
# Yours to implement — BaseStrategy has no JWT helper. Uses the `jwt` gem.
def verify_with_jwks(token)
jwks = JWT::JWK::Set.new(MyApp::Auth.fetch_jwks) # cache the issuer's JWKS
JWT.decode(token, nil, true, algorithms: ['RS256'], jwks: jwks,
iss: ENV['IDP_ISSUER'], verify_iss: true,
aud: ENV['IDP_AUDIENCE'], verify_aud: true).first
end
end
# config/initializers/spree.rb
Rails.application.config.after_initialize do
Spree.store_authentication_strategies.add(:external_idp, MyApp::Auth::ExternalJwtStrategy)
end
BaseStrategyでは、params、request_env、user_class、success(user)、failure(msg)、find_user_by_email、およびfind_or_create_user_from_oauth(provider:, uid:, info:, tokens: {})が利用できます。最後のメソッドは、Spree::UserIdentityを介してprovider + uidをユーザーに対応付けます。- パスワード方式のストラテジーでは
authenticateを実装します。リダイレクト方式のストラテジーではdef self.kind = :redirect(ボタン用にself.labelも)を定義し、authorization_url(state:)とcallbackを実装します。管理画面にはコールバックルートがあります。 - レジストリーは
add(key, klass)(上書きされます。:emailの置き換えにも使用します)、remove(key)、[key]、keysをサポートします。 Rails.application.config.after_initialize内で登録してください。 コアは独自のafter_initializeでストラテジーレジストリーを再代入するため、イニシャライザーのトップレベルやto_prepareで追加したものは消去されます。Spree::UserIdentityは、ストア、管理画面、およびセラーのストラテジーレジストリーのキーに対してproviderを検証するため、登録がないと初回ログイン時に失敗します。tokens:で渡したaccess_token/refresh_tokenは ID に保存され、保存時に暗号化されます(Active Record 暗号化。暗号化前の行を読み取れるようsupport_unencrypted_data: trueを設定)。ただし、暗号化キーが設定されている場合に限ります。設定されていない場合は平文です。spree-securityを参照してください。- サードパーティーのトークンはログイン時に一度だけ使用されます。その後、クライアントは Spree の JWT を使用します。保護されたエンドポイントで外部トークンを受け入れないでください。
- パスワードを確認するコードは、必ずロックアウトを通してください。
Spree::Authentication::Lockout.check(user) { user.valid_password?(pw) }で囲むと、:locked/:valid/:invalidが返されます(失敗はカウントされ、成功するとカウンターがクリアされます。上限はSpree::Config[:max_failed_login_attempts]/[:lockout_duration]です)。コアではログイン、現在のパスワードの確認、既存アカウントによる招待の承認にこの仕組みを使用します。これを通さないパスワード確認は、試行回数が制限されない推測の手がかりになります。 - IdP が
email_verifiedを保証する場合に限り、メールアドレスでアカウントを紐付けてください。未検証のメールアドレスで紐付けると、攻撃者にアカウントを乗っ取られるおそれがあります。
カスタムユーザークラス
# config/initializers/spree.rb
Spree.customer_class = 'MyApp::Customer' # String, never the Class
Spree.admin_user_class = 'MyApp::StaffUser'
- 顧客のデフォルトは
Spree::Customer(テーブルspree_customers、ID はcust_)です。スタッフのデフォルトはSpree::AdminUser(ID はadm_)です。カスタムクラスには、それぞれSpree::CustomerMethods/Spree::AdminUserMethodsを含めます。 - コードでは、必ず
Spree.customer_class/Spree.admin_user_classを経由してください。Spree.user_classは非推奨のcustomer_classエイリアスです。 - 顧客のライフサイクルイベント名は
user.*です。スタッフユーザー(Spree::AdminUser)はライフサイクルイベントを発行しません。
注意点
Spree::Role.find_or_create_by!(name: 'support')は失敗します — ロールはリソース(ストアまたはセラー)に属します。オーナーを通じて作成してください:store.roles.find_or_create_by!(name: 'support').update!(permissions: %w[read_orders read_customers])。Spree.permissions.assign(...)と権限セットクラス(Spree::PermissionSets::*)はもう存在しません。assignを呼び出すとPermissionSetsRemovedErrorが発生します。5.x からアップグレードする場合は、spree-upgrade-5-to-6を参照してください。- 新しい Admin コントローラーが
MissingScopedResourceで 500 を返す場合は、scoped_resource :xを宣言するか、skip_scope_check!を指定してください。 - スタッフメンバーのロールは「正しく見える」のに、
required_permissionを伴う 403 が発生する場合は、ロールがこのストアに設定されていること(X-Spree-Store-Id/ホストを確認)と、キーの綴りが正確であること(write_shipmentsではなくwrite_fulfillments)を確認してください。 - シークレットキーで
/admin_usersにアクセスすると 403 が発生します。このエンドポイントにはsettingsに含まれていないread_staffが必要です。 - ストアのスコープが適用された
scopeではなくSpree::Order.find(params[:id])を使うカスタム Admin コントローラーは、キーに関係なくストア間でデータを漏えいさせます。 - スタッフのパスワードリセット(
POST /api/v3/admin/auth/password_resets)でredirect_urlが尊重されるのは、ダッシュボード自身のオリジン(Spree::Stores::DashboardUrl)に属し、かつアカウントがそのストアのスタッフである場合のみです。それ以外の場合、メール内のリンクは<dashboard>/reset-passwordになります。許可されたオリジンを追加しても、この条件は緩和されません。 - Admin/seller のリフレッシュ Cookie は、HTTPS では
SameSite=None; Secureです。クロスオリジンのダッシュボードでは、そのオリジンを Settings → Allowed Origins にも追加する必要があります(spree-securityを参照)。
さらに詳しく読む
- スタッフとロール:
node_modules/@spree/docs/dist/developer/core-concepts/staff-roles.md - 権限カタログと拡張スコープ:
node_modules/@spree/docs/dist/developer/customization/permissions.md - カスタムログイン戦略:
node_modules/@spree/docs/dist/developer/how-to/custom-api-authentication.md - ID と SSO:
node_modules/@spree/docs/dist/developer/providers/sso.md - Admin API 認証:
node_modules/@spree/docs/dist/api-reference/admin-api/authentication.md - ソース:
spree/core/lib/spree/core/permission_configuration.rb、spree/core/lib/spree/core/permissions/default_catalog.rb、spree/api/app/controllers/concerns/spree/api/v3/scoped_authorization.rb、spree/core/app/models/spree/storefront/access_policy.rb - 関連スキル:
spree-api-v3(スコープの一覧、エラーエンベロープ)、spree-security、spree-marketplace(セラー向けの対象ユーザー)、spree-b2b(会社アクセス)、spree-dashboard(UI の権限ゲーティング)。