【Shopify】Multipass ログイン時に「マルチパスログインを使用する権限が付与されていません」とエラーが発生した場合の解決方法


概要

とあるサービスの開発において、Shopify の Multipass ログインを利用した際に生じた 「マルチパスログインを使用する権限が付与されていません」 というエラーに長時間ハマる事になったため、その原因や解決方法に関してメモ書き。

背景

  • Auth0 を認証基盤とした Shopify へのシングルサインオン(SSO)

Multipass を用いた Auth0 と Shopify の連携方法については下記の記事を参考にしました。

原因

結論から言ってしまうと、直接的な原因は Auth0 の Rules 内に記述していたスクリプト内にありました。

./Auth0/Auth Pipeline/Rules
function (user, context, callback) {
  if (context.clientMetadata && context.clientMetadata.shopify_domain && context.clientMetadata.shopify_multipass_secret)
  {
    const RULE_NAME = 'shopify-multipasstoken';
    const CLIENTNAME = context.clientName;
    console.log(`${RULE_NAME} started by ${CLIENTNAME}`);

    const now = (new Date()).toISOString();
    let shopifyToken = {
      email: user.email,
      created_at: now,
      identifier: user.user_id,
      remote_ip: context.request.ip
    };
    if (context.request && context.request.query && context.request.query.return_to){
      shopifyToken.return_to = context.request.query.return_to;
    }

    if (context.user_metadata)
    {
      shopifyToken.first_name = user.user_metadata.given_name;
      shopifyToken.last_name= user.user_metadata.family_name;
    }

    const hash = crypto.createHash("sha256").update(context.clientMetadata.shopify_multipass_secret).digest();
    const encryptionKey = hash.slice(0, 16);
    const signingKey = hash.slice(16, 32);

    const iv = crypto.randomBytes(16);
    const cipher = crypto.createCipheriv('aes-128-cbc', encryptionKey, iv);
    const cipherText = Buffer.concat([iv, cipher.update(JSON.stringify(shopifyToken), 'utf8'), cipher.final()]);

    const signed = crypto.createHmac("SHA256", signingKey).update(cipherText).digest();

    const token = Buffer.concat([cipherText, signed]).toString('base64');
    const urlToken = token.replace(/\+/g, '-').replace(/\//g, '_');

   context.redirect = {
     url: `https://${context.clientMetadata.shopify_domain}/account/login/multipass/${urlToken}`
   };
  }
  return callback(null, user, context);
}

注目すべきは shopifyToken の部分で、

let shopifyToken = {
  email: user.email,
  created_at: now,
  identifier: user.user_id,
  remote_ip: context.request.ip
};

この中に remote_ip という値を含めてしまっていたのが問題だったみたいです。

どうやらこの remote_ip をトークン内に含めると、リクエスト元のブラウザのIPアドレスと一致しなかった場合に権限エラーを吐くようになるとの事。

Multipass returns the error "You are not authorized to use Multipass login" if the remote_ip doesn't match the IP specified in the customer data hash.

この辺は Shopify のドキュメント内やフォーラム内にも記載されていました。

解決方法

shopifyToken の中から remote_ip を削除。

元々、Multipass ログイン時の必須パラメータは

  • email
  • created_at

の2つのみなので、不要であれば取り除いてもOKみたいです。

セキュリテイ的な意味では弱くなるかもしれませんが、止むを得ない場合もあるのでそうしました。

まとめ

Shopify 関連のエラーはググっても日本語の情報があまり出てこないため、英語で検索する事の重要性を改めて感じました。

たとえば、今回のケースでも「マルチパスログインを使用する権限が付与されていません」と検索してもほとんど有力な情報は得られませんでしたが、それを英語に直して「You are not authorized to use multipass login」と検索した途端に回答が出てきたので、今後は注意したいところです。