Management API returns 401 from quickstart sample

When I try to use the “Management API”, I get a 401 complaint using the sample code.

The “GET” request appears to be complaining about the “audience” – yet the sample code for the request doesn’t mention “Audience”.

In the Auth0 documentation, I’m lost in the maze of twisty tiny quickstarts and samples that all look just the same.

I have a tenant. I’ve registered an API. I started with the “get users” call of the Management API.

I’ve got sample code from the official Auth0 quickstart.

Here is the sample code I’m using:

var express = require('express');
var app = express();
var axios = require("axios");

const auth0Audience = process.env.AUTH0_BACKEND_AUDIENCE;
const auth0Domain = process.env.AUTH0_DOMAIN;
const localBackendServicesPort = process.env.LOCAL_BACKEND_AUTHENTICATION_PORT;
const auth0ClientID = process.env.AUTH0_BACKEND_TEST_CLIENT_ID;
const auth0ClientSecret = process.env.AUTH0_BACKEND_TEST_CLIENT_SECRET;

const localToken = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IkNYRWpPVnFyMnZKT1ptejV0RG95diJ9.eyJpc3MiOiJodHRwczovLzAtMC16ZWV0aXgudXMuYXV0aDAuY29tLyIsInN1YiI6Ilk4UHAwSDZjUUVaSDN2VjdZY2x1ZUdiN3k1UndQc0JYQGNsaWVudHMiLCJhdWQiOiJodHRwczovL3plZXRpeC5zZXJ2aWNlcyIsImlhdCI6MTY2NjY0MTU2OCwiZXhwIjoxNjY2NzI3OTY4LCJhenAiOiJZOFBwMEg2Y1FFWkgzdlY3WWNsdWVHYjd5NVJ3UHNCWCIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.tUfQyFob-RfpKvx1Euh5u9GRYfTIWPu33YeKtQ8Dz5Oki2lGULf1n5E7C3mcrRLX9oLlo6bc5S4-IAOssMWChB6EjVUy5huVowTRxzY702Ln9UkbIpksZ5qr8eiuWc60ZxB_IizJWc82Ibl9COvSoR6nQIUD8T0_m0k4EfKcmZ4ikJVQizsbNVcrHFpK9DqCGD0lUTA7R91LW25LZ7fqPLEzH66MKMtyL6U010H-aTRBkD95xXv0xF1cZ9O2W61S93gE3VAT5nBuKClf_EKHMgIlR9mnUoDD2NhzBboKl7cnTILFsywtv19palhZK9enVDlOjo6O6rIIq-RtMFXwfA';

var options = {
  method: 'GET',
  url: 'https://0-0-zeetix.us.auth0.com/api/v2/users',
  params: {q: 'email:"tms@zeetix.com"', search_engine: 'v3'},
  headers: {authorization: `Bearer ${localToken}`}
};

axios.request(options).then(function (response) {
  console.log(response.data);
}).catch(function (error) {
  console.error(error);
});

module.exports = app;

I’ve collected a token with no issues, and for now I’m hard-coding that token in my code while I try to make this work. Here is the nodeJS complaint I get from the above (with hard-coded token):

AxiosError: Request failed with status code 401
    at settle (/home/tms/backend/authentication/node_modules/axios/dist/node/axios.cjs:1268:12)
    at IncomingMessage.handleStreamEnd (/home/tms/backend/authentication/node_modules/axios/dist/node/axios.cjs:2446:11)
    at IncomingMessage.emit (events.js:412:35)
    at endReadableNT (internal/streams/readable.js:1333:12)
    at processTicksAndRejections (internal/process/task_queues.js:82:21) {
  code: 'ERR_BAD_REQUEST',
  config: {
    transitional: {
      silentJSONParsing: true,
      forcedJSONParsing: true,
      clarifyTimeoutError: false
    },
    adapter: [Function: httpAdapter],
    transformRequest: [ [Function: transformRequest] ],
    transformResponse: [ [Function: transformResponse] ],
    timeout: 0,
    xsrfCookieName: 'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN',
    maxContentLength: -1,
    maxBodyLength: -1,
    env: { FormData: [Function], Blob: null },
    validateStatus: [Function: validateStatus],
    headers: AxiosHeaders {
      authorization: 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IkNYRWpPVnFyMnZKT1ptejV0RG95diJ9.eyJpc3MiOiJodHRwczovLzAtMC16ZWV0aXgudXMuYXV0aDAuY29tLyIsInN1YiI6Ilk4UHAwSDZjUUVaSDN2VjdZY2x1ZUdiN3k1UndQc0JYQGNsaWVudHMiLCJhdWQiOiJodHRwczovL3plZXRpeC5zZXJ2aWNlcyIsImlhdCI6MTY2NjY0MTU2OCwiZXhwIjoxNjY2NzI3OTY4LCJhenAiOiJZOFBwMEg2Y1FFWkgzdlY3WWNsdWVHYjd5NVJ3UHNCWCIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.tUfQyFob-RfpKvx1Euh5u9GRYfTIWPu33YeKtQ8Dz5Oki2lGULf1n5E7C3mcrRLX9oLlo6bc5S4-IAOssMWChB6EjVUy5huVowTRxzY702Ln9UkbIpksZ5qr8eiuWc60ZxB_IizJWc82Ibl9COvSoR6nQIUD8T0_m0k4EfKcmZ4ikJVQizsbNVcrHFpK9DqCGD0lUTA7R91LW25LZ7fqPLEzH66MKMtyL6U010H-aTRBkD95xXv0xF1cZ9O2W61S93gE3VAT5nBuKClf_EKHMgIlR9mnUoDD2NhzBboKl7cnTILFsywtv19palhZK9enVDlOjo6O6rIIq-RtMFXwfA',
      'User-Agent': 'axios/1.1.3',
      'Accept-Encoding': 'gzip, deflate, br',
      [Symbol(defaults)]: [Object]
    },
    method: 'get',
    url: 'https://0-0-zeetix.us.auth0.com/api/v2/users',
    params: { q: 'email:"tms@zeetix.com"', search_engine: 'v3' },
    data: undefined
  },
  request: <ref *1> ClientRequest {
    _events: [Object: null prototype] {
      abort: [Function (anonymous)],
      aborted: [Function (anonymous)],
      connect: [Function (anonymous)],
      error: [Function (anonymous)],
      socket: [Function (anonymous)],
      timeout: [Function (anonymous)],
      prefinish: [Function: requestOnPrefinish]
    },
    _eventsCount: 7,
    _maxListeners: undefined,
    outputData: [],
    outputSize: 0,
    writable: true,
    destroyed: false,
    _last: true,
    chunkedEncoding: false,
    shouldKeepAlive: false,
    _defaultKeepAlive: true,
    useChunkedEncodingByDefault: false,
    sendDate: false,
    _removedConnection: false,
    _removedContLen: false,
    _removedTE: false,
    _contentLength: 0,
    _hasBody: true,
    _trailer: '',
    finished: true,
    _headerSent: true,
    socket: TLSSocket {
      _tlsOptions: [Object],
      _secureEstablished: true,
      _securePending: false,
      _newSessionPending: false,
      _controlReleased: true,
      secureConnecting: false,
      _SNICallback: null,
      servername: '0-0-zeetix.us.auth0.com',
      alpnProtocol: false,
      authorized: true,
      authorizationError: null,
      encrypted: true,
      _events: [Object: null prototype],
      _eventsCount: 10,
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: '0-0-zeetix.us.auth0.com',
      _readableState: [ReadableState],
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: false,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: undefined,
      _server: null,
      ssl: [TLSWrap],
      _requestCert: true,
      _rejectUnauthorized: true,
      parser: null,
      _httpMessage: [Circular *1],
      [Symbol(res)]: [TLSWrap],
      [Symbol(verified)]: true,
      [Symbol(pendingSession)]: null,
      [Symbol(async_id_symbol)]: 5,
      [Symbol(kHandle)]: [TLSWrap],
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(connect-options)]: [Object],
      [Symbol(RequestTimeout)]: undefined
    },
    _header: 'GET /api/v2/users?q=email:%22tms%40zeetix.com%22&search_engine=v3 HTTP/1.1\r\n' +
      'Accept: application/json, text/plain, */*\r\n' +
      'authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IkNYRWpPVnFyMnZKT1ptejV0RG95diJ9.eyJpc3MiOiJodHRwczovLzAtMC16ZWV0aXgudXMuYXV0aDAuY29tLyIsInN1YiI6Ilk4UHAwSDZjUUVaSDN2VjdZY2x1ZUdiN3k1UndQc0JYQGNsaWVudHMiLCJhdWQiOiJodHRwczovL3plZXRpeC5zZXJ2aWNlcyIsImlhdCI6MTY2NjY0MTU2OCwiZXhwIjoxNjY2NzI3OTY4LCJhenAiOiJZOFBwMEg2Y1FFWkgzdlY3WWNsdWVHYjd5NVJ3UHNCWCIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.tUfQyFob-RfpKvx1Euh5u9GRYfTIWPu33YeKtQ8Dz5Oki2lGULf1n5E7C3mcrRLX9oLlo6bc5S4-IAOssMWChB6EjVUy5huVowTRxzY702Ln9UkbIpksZ5qr8eiuWc60ZxB_IizJWc82Ibl9COvSoR6nQIUD8T0_m0k4EfKcmZ4ikJVQizsbNVcrHFpK9DqCGD0lUTA7R91LW25LZ7fqPLEzH66MKMtyL6U010H-aTRBkD95xXv0xF1cZ9O2W61S93gE3VAT5nBuKClf_EKHMgIlR9mnUoDD2NhzBboKl7cnTILFsywtv19palhZK9enVDlOjo6O6rIIq-RtMFXwfA\r\n' +
      'User-Agent: axios/1.1.3\r\n' +
      'Accept-Encoding: gzip, deflate, br\r\n' +
      'Host: 0-0-zeetix.us.auth0.com\r\n' +
      'Connection: close\r\n' +
      '\r\n',
    _keepAliveTimeout: 0,
    _onPendingData: [Function: noopPendingOutput],
    agent: Agent {
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      defaultPort: 443,
      protocol: 'https:',
      options: [Object],
      requests: {},
      sockets: [Object],
      freeSockets: {},
      keepAliveMsecs: 1000,
      keepAlive: false,
      maxSockets: Infinity,
      maxFreeSockets: 256,
      scheduling: 'lifo',
      maxTotalSockets: Infinity,
      totalSocketCount: 1,
      maxCachedSessions: 100,
      _sessionCache: [Object],
      [Symbol(kCapture)]: false
    },
    socketPath: undefined,
    method: 'GET',
    maxHeaderSize: undefined,
    insecureHTTPParser: undefined,
    path: '/api/v2/users?q=email:%22tms%40zeetix.com%22&search_engine=v3',
    _ended: true,
    res: IncomingMessage {
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 4,
      _maxListeners: undefined,
      socket: [TLSSocket],
      httpVersionMajor: 1,
      httpVersionMinor: 1,
      httpVersion: '1.1',
      complete: true,
      headers: [Object],
      rawHeaders: [Array],
      trailers: {},
      rawTrailers: [],
      aborted: false,
      upgrade: false,
      url: '',
      method: null,
      statusCode: 401,
      statusMessage: 'Unauthorized',
      client: [TLSSocket],
      _consuming: false,
      _dumped: false,
      req: [Circular *1],
      responseUrl: 'https://0-0-zeetix.us.auth0.com/api/v2/users?q=email:%22tms%40zeetix.com%22&search_engine=v3',
      redirects: [],
      [Symbol(kCapture)]: false,
      [Symbol(RequestTimeout)]: undefined
    },
    aborted: false,
    timeoutCb: null,
    upgradeOrConnect: false,
    parser: null,
    maxHeadersCount: null,
    reusedSocket: false,
    host: '0-0-zeetix.us.auth0.com',
    protocol: 'https:',
    _redirectable: Writable {
      _writableState: [WritableState],
      _events: [Object: null prototype],
      _eventsCount: 3,
      _maxListeners: undefined,
      _options: [Object],
      _ended: true,
      _ending: true,
      _redirectCount: 0,
      _redirects: [],
      _requestBodyLength: 0,
      _requestBodyBuffers: [],
      _onNativeResponse: [Function (anonymous)],
      _currentRequest: [Circular *1],
      _currentUrl: 'https://0-0-zeetix.us.auth0.com/api/v2/users?q=email:%22tms%40zeetix.com%22&search_engine=v3',
      [Symbol(kCapture)]: false
    },
    [Symbol(kCapture)]: false,
    [Symbol(kNeedDrain)]: false,
    [Symbol(corked)]: 0,
    [Symbol(kOutHeaders)]: [Object: null prototype] {
      accept: [Array],
      authorization: [Array],
      'user-agent': [Array],
      'accept-encoding': [Array],
      host: [Array]
    }
  },
  response: {
    status: 401,
    statusText: 'Unauthorized',
    headers: AxiosHeaders {
      date: 'Mon, 24 Oct 2022 20:48:25 GMT',
      'content-type': 'application/json; charset=utf-8',
      'content-length': '91',
      connection: 'close',
      'cf-ray': '75f592bd695282e4-IAD',
      'cache-control': 'no-cache',
      'strict-transport-security': 'max-age=31536000',
      vary: 'origin, Accept-Encoding',
      'cf-cache-status': 'DYNAMIC',
      'access-control-expose-headers': 'WWW-Authenticate,Server-Authorization',
      'ot-baggage-auth0-request-id': '75f592bd695282e4',
      'ot-tracer-sampled': 'true',
      'ot-tracer-spanid': '65f3591070c9f917',
      'ot-tracer-traceid': '73a61ff961c05c4e',
      traceparent: '00-000000000000000073a61ff961c05c4e-65f3591070c9f917-01',
      tracestate: 'auth0-request-id=75f592bd695282e4,auth0=true',
      'x-content-type-options': 'nosniff',
      server: 'cloudflare',
      'alt-svc': 'h3=":443"; ma=86400, h3-29=":443"; ma=86400',
      [Symbol(defaults)]: null
    },
    config: {
      transitional: [Object],
      adapter: [Function: httpAdapter],
      transformRequest: [Array],
      transformResponse: [Array],
      timeout: 0,
      xsrfCookieName: 'XSRF-TOKEN',
      xsrfHeaderName: 'X-XSRF-TOKEN',
      maxContentLength: -1,
      maxBodyLength: -1,
      env: [Object],
      validateStatus: [Function: validateStatus],
      headers: [AxiosHeaders],
      method: 'get',
      url: 'https://0-0-zeetix.us.auth0.com/api/v2/users',
      params: [Object],
      data: undefined
    },
    request: <ref *1> ClientRequest {
      _events: [Object: null prototype],
      _eventsCount: 7,
      _maxListeners: undefined,
      outputData: [],
      outputSize: 0,
      writable: true,
      destroyed: false,
      _last: true,
      chunkedEncoding: false,
      shouldKeepAlive: false,
      _defaultKeepAlive: true,
      useChunkedEncodingByDefault: false,
      sendDate: false,
      _removedConnection: false,
      _removedContLen: false,
      _removedTE: false,
      _contentLength: 0,
      _hasBody: true,
      _trailer: '',
      finished: true,
      _headerSent: true,
      socket: [TLSSocket],
      _header: 'GET /api/v2/users?q=email:%22tms%40zeetix.com%22&search_engine=v3 HTTP/1.1\r\n' +
        'Accept: application/json, text/plain, */*\r\n' +
        'authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IkNYRWpPVnFyMnZKT1ptejV0RG95diJ9.eyJpc3MiOiJodHRwczovLzAtMC16ZWV0aXgudXMuYXV0aDAuY29tLyIsInN1YiI6Ilk4UHAwSDZjUUVaSDN2VjdZY2x1ZUdiN3k1UndQc0JYQGNsaWVudHMiLCJhdWQiOiJodHRwczovL3plZXRpeC5zZXJ2aWNlcyIsImlhdCI6MTY2NjY0MTU2OCwiZXhwIjoxNjY2NzI3OTY4LCJhenAiOiJZOFBwMEg2Y1FFWkgzdlY3WWNsdWVHYjd5NVJ3UHNCWCIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.tUfQyFob-RfpKvx1Euh5u9GRYfTIWPu33YeKtQ8Dz5Oki2lGULf1n5E7C3mcrRLX9oLlo6bc5S4-IAOssMWChB6EjVUy5huVowTRxzY702Ln9UkbIpksZ5qr8eiuWc60ZxB_IizJWc82Ibl9COvSoR6nQIUD8T0_m0k4EfKcmZ4ikJVQizsbNVcrHFpK9DqCGD0lUTA7R91LW25LZ7fqPLEzH66MKMtyL6U010H-aTRBkD95xXv0xF1cZ9O2W61S93gE3VAT5nBuKClf_EKHMgIlR9mnUoDD2NhzBboKl7cnTILFsywtv19palhZK9enVDlOjo6O6rIIq-RtMFXwfA\r\n' +
        'User-Agent: axios/1.1.3\r\n' +
        'Accept-Encoding: gzip, deflate, br\r\n' +
        'Host: 0-0-zeetix.us.auth0.com\r\n' +
        'Connection: close\r\n' +
        '\r\n',
      _keepAliveTimeout: 0,
      _onPendingData: [Function: noopPendingOutput],
      agent: [Agent],
      socketPath: undefined,
      method: 'GET',
      maxHeaderSize: undefined,
      insecureHTTPParser: undefined,
      path: '/api/v2/users?q=email:%22tms%40zeetix.com%22&search_engine=v3',
      _ended: true,
      res: [IncomingMessage],
      aborted: false,
      timeoutCb: null,
      upgradeOrConnect: false,
      parser: null,
      maxHeadersCount: null,
      reusedSocket: false,
      host: '0-0-zeetix.us.auth0.com',
      protocol: 'https:',
      _redirectable: [Writable],
      [Symbol(kCapture)]: false,
      [Symbol(kNeedDrain)]: false,
      [Symbol(corked)]: 0,
      [Symbol(kOutHeaders)]: [Object: null prototype]
    },
    data: {
      statusCode: 401,
      error: 'Unauthorized',
      message: 'Bad audience: https://zeetix.services'
    }
  }
}

I’m mystified by the message at the end. The GET request doesn’t mention the audience at all. The request I use to get the token uses the value for audience copied from the Auth0 dashboard.

Here is the code I use to collect the token:

const auth0Audience = process.env.AUTH0_BACKEND_AUDIENCE;
const auth0Domain = process.env.AUTH0_DOMAIN;
const localBackendServicesPort = process.env.LOCAL_BACKEND_AUTHENTICATION_PORT;
const auth0ClientID = process.env.AUTH0_BACKEND_TEST_CLIENT_ID;
const auth0ClientSecret = process.env.AUTH0_BACKEND_TEST_CLIENT_SECRET;

const axiosTokenOptions = {
  method: 'POST',
  url: `https://${auth0Domain}/oauth/token`,
  data: {client_id: `${auth0ClientID}`, client_secret: `${auth0ClientSecret}`, audience: `${auth0Audience}`, grant_type: `client_credentials`},
  headers: {'content-type': 'application/json'}
};

axios.request(axiosTokenOptions)
  .then(function (response) {
    console.log(response.data);
    auth0TokenSet(response.data.access_token);
  })
  .catch(function (error) {
    console.error(error);
  });

The environment variables contain values harvested from the relevant areas of my Auth0 Tenant settings.

What must I do to collect information about my users from the Auth0 “Management API”?

Hey there @tms!

What are you setting as the audience in the code you use to request the management token?

Here’s the value of AUTH0_BACKEND_AUDIENCE used in requesting the management token.

$ printenv AUTH0_BACKEND_AUDIENCE
https://zeetix.services
1 Like

Hey @tms thanks for confirming!

That audience needs to be the identifier of your Management API so your_auth0_domain/api/v2. If you navigate to Application → API → Management API in your dashboard and look at the “Test” tab, you’ll see the sequential calls 1. to get the Management API token where your Management API Identifier is used as the audience, and 2. an example call to the management API using the token previously returned.

Some more on the details of obtaining Management API access tokens here:

Keep me posted!

I changed the value of “audience” as per your reply. That resulted in a different complaint:

data: { error: 'access_denied', error_description: 'Unauthorized' }

This lead me down yet another rabbit-hole – what “client_id”/“client_secret” should I be using?

I don’t think I have ANY client! I want an API (of mine) to use the “Auth0 Management API”. I don’t know what “client_id” or “client_secret” even mean in that context.

I apologize for being dense – I’m still confused by the nomenclature and cardinality of the Auth0 entities I need.

On my end, I want at least two services – I’ll call them “services” and “authentication”. These are conventional “node express” services (npx express-generator <service_name>).

When other entities on my system – like the React front-end pushed to a browser – need protected information, they will use the “services” service. It has its own port (7103). That service should only allow calls from authenticated and signed-in users. When a signed-in user chooses to purchase a subscription and become a “subscriber”, the “services” service makes whatever local (to Zeetix) changes are needed. These are things like database changes, calls to third party apps, and so on.

I want the “authentication” service to encapsulate access to Auth0. The authentication service has its own port (7203). I think the authentication service interacts with Auth0 to – for example – collect the Auth0 User instances that are currently associated with my domain. I think Zeetix ‘services’ can communicate with the Zeetix ‘authentication’ service to do the right thing when an Auth0 user that is a Zeetix “subscriber” signs in.

In this worldview, there is just one Auth0 “Application” – it is called “Zeetix Data Browser”. It has been working for awhile. It has a client_id, client_secret, and so on. This is the Auth0 entity that the browser interacts with during sign-in and sign-out.

I think this scenario needs two instances of Auth0 “API” – I called one “Zeetix Services API” and the other “Zeetix Authentication API”. I have provisioned each of these. When I navigate to the API screen of my Auth0 Tenant dashboard, I see a total of four API instances listed:

  1. Auth0 Management API
  2. Auth0 Express Sample
  3. Zeetix Services API
  4. Zeetix Authentication API

This all makes sense to me.

The “Applications” tab of the same Auth0 Tenant dashboard has a “Test Application” for each
of these 4 APIs. I’m confused about what any of those “test application” instances do or why I need them.

I’m coding my first exchange between my “authentication” service and the “Auth0 Management API”. This is a machine-to-machine interaction, so there is no “User”. Since the “Zeetix Authentication API” is a machine-to-machine API, it isn’t meaningful to talk about a client_id or client_secret – there is no client.

The “authentication” service needs a token so that it can use the Auth0 Management API to access information about Zeetix users from Auth0.

Here are the questions I’m unable to answer:

  1. Where does the “client_id” and “client_secret” for the “Auth0 Management API” token request come from?

  2. Do I need an Auth0 “Application” instance for each “API” instance that I want to use?

  3. Does my “services” service need to communicate with Auth0 in order to access my “authentication” service, or does “services” instead collect a token from “authentication” for subsequent use.

I’ve already worked through the SPA-API quickstart, but that doesn’t make any calls to the “Auth0 Management API”.

I’m clearly misunderstanding something fundamental here.

I have tried two options for requesting a token while using AUTH0_DOMAIN=0-0-zeetix.us.auth0.com/api/v2/ as the value of `Audience" in the request:

client_id: <clientID of Auth0 Management API (Test Client)>
client_secret:  <clientSecret of Auth0 Management API (Test Client)>

and

client_id: <clientID of Zeetix Authentication API (Test Client)>
client_secret:  <clientSecret of Zeetix Authentication API (Test Client)>

Each results in the same token request failure:

{
   error: "access_denied",
   error_description: "Service not enabled within domain: 0-0-zeetix.us.auth0.com/api/v2/",
}

I have turned on all the settings I can find in the tenant dashboard.

Where I stand at the moment is:

  • I am unable to get a token with an audience of AUTH0_DOMAIN=0-0-zeetix.us.auth0.com/api/v2/
  • When I use a token I can get, it fails with
    {
      statusCode: 401,
      error: 'Unauthorized',
      message: 'Bad audience: https://zeetix.authentication'
    }
    

This is what I mean by going in circles.

Update:

I attempted to use the alternative (suggested in the docs) of installing the “auth0” npm component and then either “AuthenticationClient” or ManagementClient" from that component.

I get the same error:

$ yarn start
    Debugger listening on ws://127.0.0.1:53397/0811cc4b-40fa-46ee-954e-19f522caf376
    For help, see: https://nodejs.org/en/docs/inspector
    Debugger attached.
    yarn run v1.22.19
    $ node ./bin/www
    Debugger listening on ws://127.0.0.1:53476/4fc50bb5-630d-486c-b3f3-278a089630ee
    For help, see: https://nodejs.org/en/docs/inspector
    Debugger attached.
    access_denied: {"error":"access_denied","error_description":"Service not enabled within domain: 0-0-zeetix.us.auth0.com/api/v2/"}
        at /home/tms/backend/authentication/node_modules/rest-facade/src/Client.js:402:25
        at Request.callback (/home/tms/backend/authentication/node_modules/superagent/lib/node/index.js:905:3)
        at /home/tms/backend/authentication/node_modules/superagent/lib/node/index.js:1126:20
        at IncomingMessage.<anonymous> (/home/tms/backend/authentication/node_modules/superagent/lib/node/parsers/json.js:22:7)
        at IncomingMessage.emit (events.js:412:35)
        at endReadableNT (internal/streams/readable.js:1333:12)
        at processTicksAndRejections (internal/process/task_queues.js:82:21) {
      statusCode: 403,
      requestInfo: {
        method: 'post',
        url: 'https://0-0-zeetix.us.auth0.com/oauth/token'
      },
      originalError: Error: Forbidden
          at Request.callback (/home/tms/backend/authentication/node_modules/superagent/lib/node/index.js:883:15)
          at /home/tms/backend/authentication/node_modules/superagent/lib/node/index.js:1126:20
          at IncomingMessage.<anonymous> (/home/tms/backend/authentication/node_modules/superagent/lib/node/parsers/json.js:22:7)
          at IncomingMessage.emit (events.js:412:35)
          at endReadableNT (internal/streams/readable.js:1333:12)
          at processTicksAndRejections (internal/process/task_queues.js:82:21) {
        status: 403,
        response: Response {
          _events: [Object: null prototype] {},
          _eventsCount: 0,
          _maxListeners: undefined,
          res: [IncomingMessage],
          request: [Request],
          req: [ClientRequest],
          text: '{"error":"access_denied","error_description":"Service not enabled within domain: 0-0-zeetix.us.auth0.com/api/v2/"}',
          body: [Object],
          files: undefined,
          buffered: true,
          headers: [Object],
          header: [Object],
          statusCode: 403,
          status: 403,
          statusType: 4,
          info: false,
          ok: false,
          redirect: false,
          clientError: true,
          serverError: false,
          error: [Error],
          created: false,
          accepted: false,
          noContent: false,
          badRequest: false,
          unauthorized: false,
          notAcceptable: false,
          forbidden: true,
          notFound: false,
          unprocessableEntity: false,
          type: 'application/json',
          links: {},
          setEncoding: [Function: bound ],
          redirects: [],
          pipe: [Function (anonymous)],
          [Symbol(kCapture)]: false
        }
      }
    }

This complaint:

"Service not enabled within domain: 0-0-zeetix.us.auth0.com/api/v2/"

suggests that I need to do more in the tenant dashboard. I don’t know what more to do. I’ve turned on every toggle I can find and none of it seems to matter.

I have finally gotten a round-trip to work.

The first step is to get the token as per Applications->API->Test with the “Auth0 Management API (Test Application)” selected (from the dropdown) as the application to test.

This uses the client_id and client_secret of the Auth0 Management API test application.

With this token in-hand, I then used the recipe from Get Management API Access Tokens for Production (provided by @tyf upthread).

Scrolling that link down, I see the vital new information – the url passed in the request that uses the token just collected.

Here is the axios code fragment that finally worked for me:

var axios = require("axios");

const options = { 
  method: "GET",
  url: `https://${auth0Domain}/api/v2/users`,
  headers: {'authorization': `Bearer ${localToken}`}
};

axios(options)
  .then(response => {
    console.log(response.data);
  })
  .catch(error => {
    console.log(error);
  });

I still need to do further experimentation to discover the permutations of client_id/client_secret, audience, and subsequent url that work.

At least I’m finally able to collect users using the “Auth0 Management API”.

1 Like

Hey @tms I apologize for the delayed response on this one, and wanted to thank you for sharing your progress with the community :pray:

Just to clarify a couple things - Outside of some limited scopes afforded to SPA/Public apps, the management API needs to be accessed by a server-side (private) application. Some more on the differences between private and public applications can be found here.

The management API can also be accessed via extensibility features like Actions, as outlined in this FAQ:

Another common use case is to proxy calls to the management APi:

Hope this helps at least provide some clarity!

1 Like

At least for now, I think I’m good.

A stumbling block for me has been the need to have an “Application” – in my case generated by Auth0 with name “Zeetix Authentication API (Test Application)” – in order to use the “API” that I have spun up (“Zeetix Authentication API”).

Be that as it may, the “Token Endpoint Authentication Method” of that Application is already “Post”, so it should be able to access the Management API.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.