/oauth/token grant_type password login "access_denied" with "Unauthorized"

I am trying to call grant_type: password token request in Postman and I am getting the following response.

{
    "error": "access_denied",
    "error_description": "Unauthorized"
}

My request

method: POST

curl --location 'https://<tenant-url>.auth0.com/oauth/token/' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=<username>' \
--data-urlencode 'password=<password>' \
--data-urlencode 'scope=email' \
--data-urlencode 'client_id=<client-id>' \
--data-urlencode 'client_secret=<client-secret>'

Application Settings

  • Application Type: Regular Web Application

  • Advanced Settings > Grant Types: :white_check_mark: Implicit :white_check_mark: Authorization Code :white_check_mark:Refresh Token :white_check_mark: Client Credentials :white_check_mark: Password

  • Authentication Method: Client Secret (Post)

  • Connection: Username-Password-Authentication

Things I double checked

  • Tenant URL

  • Username & Password (checked with Connection Test)

  • Client ID

  • Client Secret

Please kindly tell me what is wrong.

Hi @yehtetlwin and welcome to the Auth0 Community!

Could you please confirm that going into Applications - Application - Connections tab, the Username-Password-Authentication connection is toggled on? I’m asking because a common cause for this error is that the Application doesn’t have access to the database.

Thanks!
Teodor.

Yes, Username-Password-Authentication connection is toggled on in Application > Connection tab.

With futher research

I finally can access token by Basic Authorization with Client ID and Client Secret in Header’s “Authorization” and other params as a form of URL Params.

    const credentials = Buffer.from('<client-id>:<client-secret>').toString(
      'base64'
    )
    const res = await fetch('https://<tenant-url>.auth0.com/oauth/token/', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': `Basic ${credentials}`,
      },
      body: new URLSearchParams({
        grant_type: 'password',
        username: '<username>',
        password: '<password>',
        scope: 'email',
      }),
    })

But I cannot find any tutorial that mentions to use Client ID and Client Secret as Basic Authorization in Header, so I doubt it is a correct way to do it. :thinking:

Can you please confirm it?

Hi again @yehtetlwin!

Yes, using the Authorization header with HTTP Basic authentication is a correct, standard, and often recommended way for a confidential client to authenticate itself when calling the /oauth/token endpoint.
The reason you may not see this method in every tutorial is that some examples simplify the request by putting the client_id and client_secret directly in the request body. Both methods are supported by the OAuth 2.0 specification, but using the Authorization header is generally considered a cleaner and better practice.

Your method is perfectly valid according to the OAuth 2.0 specification (RFC 6749, Section 2.3.1), which defines client authentication for confidential clients.

I wish you a great day!
Teodor.

1 Like

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