Client Credentials Exchange

Client Credentials Exchange(クライアント資格情報交換)拡張ポイントでは、フックにより、クライアントの資格情報フローを使用して認証APIのPOST /oauth/tokenエンドポイントからアクセストークンが発行される際にカスタムアクションを実行できます。たとえば、トークンが発行されないように拒否する、アクセストークンにカスタムクレームを追加する、またはそのスコープを修正することができます。詳細については、「クライアントの資格情報フロー」をお読みください。

この拡張ポイントでのフックはブロッキング(同期的)であり、トリガーのプロセスの一部として実行されます。そのため、フックが完了するまでAuth0パイプラインの他の部分の実行が停止されます。

スターターコードとパラメーター

Client Credentials Exchange(クライアント資格情報交換)拡張ポイントで実行されるフックを作成する際、以下のスターターコードが役立つかもしれません。Hook関数に渡され、使用されることができるパラメーターは、コード例の最上部にリストされています。

/**
@param {object} client - client information
@param {string} client.name - client name
@param {string} client.id - client ID
@param {string} client.tenant - Auth0 tenant name
@param {object} client.metadata - client metadata
@param {array|undefined} scope - either an array of strings representing the token's scope claim, or undefined
@param {string} audience - token's audience claim
@param {object} context - Auth0 context info
@param {object} context.webtask - Hook (webtask) context
@param {function} cb - function (error, accessTokenClaims)
*/

module.exports = function(client, scope, audience, context, cb) {
  var access_token = {};
  access_token.scope = scope; // do not remove this line

  // Modify scopes or add extra claims
  // access_token['https://example.com/claim'] = 'bar';
  // access_token.scope.push('extra');

  // Deny the token and respond with an OAuth2 error response
  // if (denyExchange) {
  //   // To return an HTTP 400 with { "error": "invalid_scope", "error_description": "Not authorized for this scope." }
  //   return cb(new InvalidScopeError('Not authorized for this scope.'));
  //
  //   // To return an HTTP 400 with { "error": "invalid_request", "error_description": "Not a valid request." }
  //   return cb(new InvalidRequestError('Not a valid request.'));
  //
  //   // To return an HTTP 500 with { "error": "server_error", "error_description": "A server error occurred." }
  //   return cb(new ServerError('A server error occurred.'));
  // }

  cb(null, access_token);
};

Was this helpful?

/

以下の点にご注意ください。

  • サンプルコードの終わりにあるコールバック関数(cb)は、完了を知らせるもので、必ず含まれなければなりません。

  • access_token.scope = scopeという行は、すべての付与されたスコープがアクセストークンに存在するようにします。それを取り除くとすべてのスコープをリセットすることになり、トークンにはスクリプトで追加したスコープのみ含まれます。

デフォルトの応答

Client Credentials Exchange(クライアント資格情報交換)拡張ポイントでフックを実行すると、デフォルトの応答オブジェクトは次のようになります。

{
  "scope": "array of strings"
}

Was this helpful?

/

スターターコードの応答

スコープと追加クレームを使用してスターターコードをカスタマイズしたら、Hookエディタに埋め込まれたランナーを使用してフックをテストできます。ランナーは、Client Credentials Exchange(クライアント資格情報交換)で得られるものと同じ要求ボディと応答を使ってフックへの呼び出しをシミュレートします。

スターターコードに基づいたフックを実行する場合、応答オブジェクトは以下の通りになります。

{
  "audience": "https://my-tenant.auth0.com/api/v2/",
  "client": {
    "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "name": "client-name",
    "tenant": "my-tenant",
    "metadata": {
      "plan": "full"
    }
  },
  "scope": [
    "read:connections"
  ]
}

Was this helpful?

/

スクリプト例:アクセストークンに追加スコープを追加する

この例では、既存のスコープに加えてアクセストークンに追加のスコープを付与するためにフックを使用します。

module.exports = function(client, scope, audience, context, cb) {
    // Scopes to be added
    var access_token = {};

    // Get the scope that's currently on the Access Token
    // and add it to the object we're working with
    // Do not remove this line!
    access_token.scope = scope;

    // Append the `read:resource` scope
    access_token.scope.push('read:resource');

    // Callback to indicate completion and to return new
    // array of scopes
    cb(null, access_token);
};

Was this helpful?

/

詳しくは、「スコープ」をお読みください。

応答

このフックを実行すると、応答オブジェクトは次のようになります。

{
  "scope": [
    "read:connections",
    "read:resource"
  ]
}

Was this helpful?

/

スクリプト例:アクセストークンにクレームを追加する

この例では、アクセストークンに名前空間のカスタムクレームとその値を追加します。詳細については、「名前空間カスタムクレームを作成する」をお読みください。

以下をクレームとして発行済みトークンに追加できます。

  • 応答オブジェクトのscopeプロパティ

  • 名前空間プロパティ名のあるすべてのプロパティ

拡張ポイントは、その他すべての応答オブジェクトプロパティを無視します。

module.exports = function(client, scope, audience, context, cb) {
    // Claims to be added
    var access_token = {};

    // New claim to add to the token
    access_token['https://example.com/foo'] = 'bar';

    // Callback to indicate completion and to return new claim
    cb(null, access_token);
  };

Was this helpful?

/

応答

このフックを実行すると、応答オブジェクトは次のようになります。

{
  "https://example.com/foo": "bar"
}

Was this helpful?

/

スクリプト例:エラーを発生させる、またはアクセストークンを拒否する

この例では、カスタムのエラーオブジェクトを使用して、OAuth2エラー応答を生成します(詳細については、IETF DatatrackerのOAuth2 RFC、セクション5.2をお読みください)。

コールバック内で次のような単純なJavaScriptエラーが返された場合に、

module.exports = function(client, scope, audience, context, cb) {
    // Callback to indicate completion and to return new claim
    cb(new Error("Unknown error occurred.");
  };

Was this helpful?

/

/oauth/tokenエンドポイントからclient_credentialsの付与を要求すると、Auth0は次のように応答します。

HTTP 500
{ "error": "server_error", "error_description": "Unknown error occurred." }

Was this helpful?

/

しかし、OAuth2エラー応答をさらに制御したい場合は、3種類のカスタムエラーオブジェクトを使用することもできます。

InvalidScopeError

module.exports = function(client, scope, audience, context, cb) {
    const invalidScope = ...; // determine if scope is valid

    if(invalidScope) {
      cb(new InvalidScopeError("Scope is not permitted."));
    }
  };

Was this helpful?

/

そして、/oauth/tokenエンドポイントからclient_credentialsの付与を要求すると、Auth0は次のように応答します。

HTTP 400
{ "error": "invalid_scope", "error_description": "Scope is not permitted." }

Was this helpful?

/

InvalidRequestError

module.exports = function(client, scope, audience, context, cb) {
    const invalidRequest = ...; // determine if request is valid

    if(invalidRequest) {
      cb(new InvalidRequestError("Bad request."));
    }
  };

Was this helpful?

/

/oauth/tokenエンドポイントからclient_credentialsの付与を要求すると、Auth0は次のように応答します。

HTTP 400
{ "error": "invalid_request", "error_description": "Bad request." }

Was this helpful?

/

ServerError

module.exports = function(client, scope, audience, context, cb) {
    callOtherService(function(err, response) {
      if(err) {
        return cb(new ServerError("Error calling remote system: " + err.message));
      }
    });
  };

Was this helpful?

/

そして、/oauth/tokenエンドポイントからclient_credentialsの付与を要求すると、Auth0は次のように応答します。

HTTP 400
{ "error": "server_error", "error_description": "Error calling remote system: ..." }

Was this helpful?

/

もっと詳しく