mcpField
S
spree-auth-permissions

spree-auth-permissions

github.com/spreeセキュリティ10104 回インストール4 週間前に更新
リポジトリ

spree-auth-permissions について

Spree 6 のスタッフ、インテグレーション、顧客に対する認可を解説するスキルです。権限キー、API キーのスコープ、レコード単位のアクセス制御、ロール管理、権限カタログの拡張を扱います。

主な機能

  1. 01スタッフのロールと権限キー
  2. 02インテグレーションの API キースコープ
  3. 03顧客の所有権による認可
  4. 04Admin API の認可フロー
  5. 05拡張権限スコープの登録

活用シーン

  1. 01店舗スタッフのロール設定
  2. 02API スコープによる連携アクセス制限
  3. 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 つのルールがあります。

  1. キーで制限するのはレコードの種類であり、対象の行ではありません。 write_orders は「注文を書き込める」という意味であり、どの注文が対象になるかはコントローラーのスコープ付きクエリ(current_store.orders、current_seller.products、current_user.wishlists)によって決まります。コントローラーを追加する場合は、スコープを設定する責任があります。
  2. レコードの状態に関するルールは、権限ではなくモデルとワークフローに属します。 「確定済みの注文は削除できない」というルールはシークレットキーにも適用されなければならず、シークレットキーがロールを介することはありません。

スタッフのロールはデータです

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 が発生し、デフォルトで拒否されます。各リクエストでは、次の処理が行われます。

  1. アクションを read_(index、show と、コントローラーの read_actions に含まれるすべてのアクション)または write_(カスタムのメンバーアクションである cancel を含む、それ以外すべて)に割り当てます。
  2. シークレットキー: current_api_key.has_scope?("write_orders") を確認し、該当しない場合は 403 を返します。
    { "error": { "code": "access_denied", "message": "API key lacks scope: write_orders",
                 "details": { "required_scope": "write_orders" } } }
    
  3. JWT スタッフ: 現在のストアでユーザーのロールキーを展開したもの(Spree::Ability#permission_keys)を確認し、該当しない場合は "details": { "required_permission": "write_orders" } を含む 403 を返します。admin ロールはすべての権限を許可します。
  4. ゲート通過後、キーはレコードレベルのチェック用に 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 つの方法で適用されます。

  1. スコープ付きクエリ。 すべてのストアコントローラーはストアと所有者を通じて読み込みます。例:storefront_access_policy.scope(Spree::Wishlist.for_store(current_store))。
  2. 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 が発生し、403 access_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 APISpree.store_authentication_strategiesSpree.customer_classstore_apiレスポンス本文内
Admin APISpree.admin_authentication_strategiesSpree.admin_user_classadmin_api/api/v3/admin/auth の HttpOnly クッキー
Seller APISpree.seller_authentication_strategiesSpree.admin_user_classseller_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 の権限ゲーティング)。

コメント