More Extensible Machine-to-Machine Flow

Feature: More Extensible Machine-to-machine Flow

Description: Currently actions can only be implemented for use after the provided client_id and client_secret have been validated by the “Auth0 Authorization Server”. Enabling actions to be implemented at an earlier point in the M2M flow would allow for the implementation of more complex M2M flows.

Use-case: I’m currently developing a proof-of-concept application that is hosted as an AWS Lambda, and requires the use of the Auth0 Management API. Implementing this securely requires storing the client_secret within something like AWS Secrets Manager, meaning when making a request to the Auth0 Management API the Lambda needs to retrieve the secret from AWS Secrets Manager, then contacting the Auth0 Authentication API to get an access token, and then actually making the request to the Auth0 Management API.

For a serverless application, this is a decent amount of overhead, so I have attempted to create an action that would supplement the M2M flow allowing for the Lambda to supply AWS IAM credentials and have them validated instead (somewhat similar to MongoDB Atlas).

However, when supplying AWS IAM credentials in place of the normal client_id and client_secret is invalidated before the action can run.

Here’s an example of the action’s implementation:

const { STSClient, GetCallerIdentityCommand } = require("@aws-sdk/client-sts");

const allowedArns = ["arn:aws:iam::<AWS account id>:<user | role>/<name>"];

/**
* Handler that will be called during the execution of a Client Credentials exchange.
*
* @param {Event} event - Details about client credentials grant request.
* @param {CredentialsExchangeAPI} api - Interface whose methods can be used to change the behavior of client credentials grant.
*/
exports.onExecuteCredentialsExchange = async (event, api) => {
  const body = event.request.body;
  const clientId = body["client_id"];
  const clientSecret = body["client_secret"];
  const iamAuth = body["method"] === "aws";

  if(clientId && clientSecret && iamAuth){
    const client = new STSClient({
      region: "<AWS region>",
      credentials: {
        accessKeyId: clientId,
        secretAccessKey: clientSecret
      }
    });

    let success = false;

    try{
      const result = await client.send(new GetCallerIdentityCommand({}))
      success = allowedArns.includes(result.Arn);
    }
    catch{
      success = false;
    }

    if(!success){
      api.access.deny("invalid_request", "AWS IAM credentials invalid");
    }
  }
};

Hi @jaegerJosh,

Welcome to the Auth0 Community!

Thanks for the thorough feature request!

1 Like