Get the correct Access Token for Automated Tests

Hi All,
So I want to create integration tests via Node.js to run locally on my machine and eventually use in an automated pipeline.

We have a Test application (Test Application) Machine to Machine and in the Quick Start, there is an example to get the access token and then use the access token against our APIs.

I have tried the example against both Auth0 Management API and our Dev application.
Both times, the first request returns an access token but when I try the access token against our API the Node.js Express application returns a 400 error.

{
  statusCode: 400,
  error: 'Bad Request',
  message: "Object didn't pass validation for format user-id: XXX@clients",
  errorCode: 'invalid_uri'
}

the User Id doesn’t have auth0|XXX but XXX@clients, I am not sure if that is the issue or not.

Surely the quick start guide should work so I presume I am missing some Auth0 configuration in the Test application?

Please help.

Hey there @jaime1 welcome to the community!

Do you mind sharing the specific quick start you are working off of?

It’s hard to know without looking at the example, but this error does lead me to believe there’s a simple mismatch in what the API is expected and what you’re passing.

Let us know!

Hi!

I am working from here: https://manage.auth0.com/dashboard/us/dev-l2swae8to1esqjyb/applications/3J3pD3kBvPwTMapnLDPZTdM2HyFsKRYr/quickstart

Does that help? Can you access that URL?

Mytaverse Dev (Test Application)
Machine to Machine

Client ID

3J3pD3kBvPwTMapnLDPZTdM2HyFsKRYr

Hi,

Any help?
@tyf ?

Thanks

Hi,

Can someone please respond :slight_smile:

Thanks

1 Like

Hey there @jaime1!

The quickstart section in the m2m application unfortunately doesn’t give me much info - What does the API look like that you are validating the access token against? I just tested a quick Node sample API (below) and the token I received from the quickstart section for my API was validated successfully, allowing me to access the /api/private endpoint.

require('dotenv').config();
const express = require('express');
const { auth } = require('express-oauth2-jwt-bearer');

const app = express();
const port = process.env.PORT || 3000;

// Auth0 JWT validation middleware configuration
const checkJwt = auth({
  audience: process.env.AUDIENCE,
  issuerBaseURL: process.env.DOMAIN,
});

// A protected route that requires a valid JWT
app.get('/api/private', checkJwt, (req, res) => {
  res.status(200).send('Access granted to protected data');
});

// Error handler for unauthorized access
app.use((err, req, res, next) => {
  if (err.name === 'UnauthorizedError') {
    return res.status(401).send('Invalid token');
  }
  next(err);
});

// Start the server
app.listen(port, () => {
  console.log(`Server listening on http://localhost:${port}`);
});

Hi,

So in the integration test, we get the token by doing:

const response = await axios.post(
    `https://${AUTH0_DOMAIN}/oauth/token`,
    {
      client_id: '3J3pD3kBvPwTMapnLDPZTdM2HyFsKRYr',
      client_secret:
        'XXX',
      audience: 'Mytaverse:Dev',
      grant_type: 'client_credentials',
    },
    { headers: { 'content-type': 'application/json' } },
  );

We then use the token to our API. In the API, we have a middleware for auth that we do:

const getKey = (header: any, callback: any) => {
        console.log('header.kid', header.kid);
        jwksRSAClient.getSigningKey(header.kid, (err: any, key: any) => {
          const signingKey = key.publicKey || key.rsaPublicKey;

          callback(null, signingKey);
        });
      };

      token = token.replace('Bearer ', '');

      jwt.verify(token, getKey, function (err: any, decoded: any) {

This passes OK.

The decoded object returns:

decoded {
  iss: 'XXX',
  sub: '3J3pD3kBvPwTMapnLDPZTdM2HyFsKRYr@clients',
  aud: 'Mytaverse:Dev',
  iat: 1715288184,
  exp: 1715291784,
  scope: 'ALL OK',
  gty: 'client-credentials',
  azp: '3J3pD3kBvPwTMapnLDPZTdM2HyFsKRYr'
}

We check to see if this user exists in our DB 3J3pD3kBvPwTMapnLDPZTdM2HyFsKRYr@clients
and it doesn’t so then we then get the M2M token by calling:

const data = await axios.post(`https://${AUTH0_DOMAIN}/oauth/token`, {
      client_id: AUTH0_M2M_API_CLIENT_ID,
      client_secret: AUTH0_M2M_API_CLIENT_SECRET,
      audience: AUTH0_M2M_API_AUDIENCE,
      grant_type: 'client_credentials',
    });

We then call Auth0 using the M2M token:

`https://${AUTH0_DOMAIN}/api/v2/users/${userId}`

And this produces the error:

{
  statusCode: 400,
  error: 'Bad Request',
  message: "Object didn't pass validation for format user-id: 3J3pD3kBvPwTMapnLDPZTdM2HyFsKRYr@clients",
  errorCode: 'invalid_uri'
}

Awesome, thanks for the additional detail!

I’m a bit confused by this step - The sub claim here is that of a M2M app and not a user.

If you are passing a {userID} that looks like 3J3pD3kBvPwTMapnLDPZTdM2HyFsKRYr@clients this won’t work. A user_id should look like {identity provider id}|{unique id in the provider} or facebook|1234567890, auth0|123456, etc.

Hi,

Yes, that is what I don’t understand, the first call:

const response = await axios.post(
    `https://${AUTH0_DOMAIN}/oauth/token`,
    {
      client_id: '3J3pD3kBvPwTMapnLDPZTdM2HyFsKRYr',
      client_secret:
        'XXX',
      audience: 'Mytaverse:Dev',
      grant_type: 'client_credentials',
    },
    { headers: { 'content-type': 'application/json' } },
  );

This gives me `sub: ‘3J3pD3kBvPwTMapnLDPZTdM2HyFsKRYr@clients’,

Which is wrong no? It should be auth0|XXX like my first post stated?
Do I need to create a test user for Mytaverse Dev (Test Application)?
I thought that the application was a User in itself for testing?

OK I think I understand!

The first call is just performing a client credentials exchange and getting you an m2m access token, no user involved at all.

Creating a test user seems to make sense for what you’re doing. Once you create one, you can get this user’s access token using the resource owner password flow (fine for testing). So instead of using the client’s credentials, you’ll use the user’s credentials against the /oauth/token endpoint.

OK perfect, I shall do that.

Is there a way to create the Test User for my app via the Browser/UI or do I have to do it via the API?

Thanks!

1 Like

No worries, I found it

1 Like

Thank you for the help that worked.
Thanks.

1 Like

Awesome! Thanks for confirming and happy to help :slight_smile: