Join our Newsletter — 33% off our NHI Course
Home› Guides› OAuth invalid_client and unauthorized_client Troubleshooting Guide: Fixing Client…
Guide Authorisation

OAuth invalid_client and unauthorized_client Troubleshooting Guide: Fixing Client Authentication and Grant Permission Errors

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 11 November 2026 13 min read
On this page

An invalid_client or unauthorized_client error means the authorisation server rejected the application itself, not the user or the token, and the usual reflex of generating a new secret often adds a credential without fixing the cause. The two errors are different: invalid_client says the client could not be authenticated, while unauthorized_client says the client was recognised but is not allowed to use the grant type it asked for. This guide works from each error to its likely causes by client authentication method (shared secret, signed JWT assertion, mutual TLS) and by grant type, shows where to look, and gives the fix and how to prevent recurrence. It is for developers, identity engineers and platform teams running confidential OAuth clients, service integrations and workloads. Provider behaviour was checked against IETF, Microsoft, Google, Okta and Auth0 documentation on 11 November 2026. Errors about the grant itself are covered in the OAuth invalid_grant Error Troubleshooting Guide.

Key takeaways

  • Separate the two errors before anything else. invalid_client is an authentication failure (wrong, expired or badly sent credential, unknown client). unauthorized_client is a permission failure (grant type not enabled, delegation not authorised). Rotating a secret never fixes the second.
  • Most invalid_client errors are transport mistakes. A secret not URL-encoded before Basic encoding, credentials sent in both header and body, the wrong method for the client's registration, or a request sent to the wrong tenant or endpoint.
  • Assertion failures are claim failures. For private_key_jwt, check aud, iss, sub, exp, jti and the key identifier against what the server expects, character for character.
  • Mutual TLS fails before OAuth sees the request. Check whether the certificate reached the authorisation server at all, through proxies and on the right endpoint alias.
  • Do not fix the error by widening the client. Enabling every grant type, turning a public client into a confidential one, or adding a second long-lived secret creates exposure that outlives the incident.

What the two errors mean

ErrorRFC 6749 s5.2 meaningHTTP statusTypical question to ask
invalid_clientClient authentication failed (unknown client, no client authentication included, or unsupported authentication method)400 or 401; must be 401 with a WWW-Authenticate header if the client authenticated with the Authorization headerDid the server receive a credential it could verify for this client ID?
unauthorized_clientThe authenticated client is not authorised to use this authorisation grant type400Is this client allowed this grant, for this user or tenant?
unsupported_grant_typeThe server does not support the grant type at all400Is the grant_type value spelt and supported?
invalid_grantThe grant or refresh token itself is invalid, expired or revoked400See the invalid_grant guide

Providers add detail. Microsoft Entra places an AADSTS code in error_description; Google returns texts such as "Unauthorized client or scope in request."; Okta and Auth0 return descriptions and record the failure in their logs. Always log the full error body and the provider's request or trace ID, never the secret or assertion.

Triage in five checks

  1. Endpoint and tenant: is the request going to the right token endpoint for the right tenant, environment and authorisation server? Okta custom authorisation servers and the org server have different endpoints; Entra tenants are part of the URL. Entra AADSTS700016 says the application was not found in the directory, often because the request went to the wrong tenant.
  2. Client ID: exact match, no whitespace, correct environment. A staging client ID with a production secret fails as invalid_client.
  3. Registered authentication method: what does the registration say (client_secret_basic, client_secret_post, client_secret_jwt, private_key_jwt, tls_client_auth, self_signed_tls_client_auth, or none for public clients)? Compare with what the client library actually sends. The server's metadata lists what it supports in token_endpoint_auth_methods_supported.
  4. Exactly one method per request: RFC 6749 says a client must not use more than one authentication method in a request. A library that sends Basic credentials and also client_secret in the body can be rejected.
  5. Grant type: is grant_type enabled for this client? If authentication passes and this check fails, the result is unauthorized_client.

invalid_client with shared secrets

CauseHow to confirmFixPrevent
Secret not encoded correctly for BasicFails only for secrets containing characters such as +, /, = or %; works with client_secret_postRFC 6749 s2.3.1: form-urlencode the client ID and secret, then Base64-encode id:secretUse a maintained OAuth library rather than hand-built headers
Wrong method for the registrationRegistration says client_secret_basic, client posts the secret in the body, or the reverseAlign client and registrationDeclare the method explicitly in client configuration
Secret expiredEntra AADSTS7000222 "The provided client secret keys are expired"Issue a new secret through the normal rotation processAlert on expiry ahead of time; prefer certificate or federated credentials
Secret wrong or staleEntra AADSTS7000215 "Invalid client secret is provided" or AADSTS70002; a deployment still holds the old value after rotationCheck which version the running workload loaded; restart after secret updates where the app caches itOverlap old and new secrets during rotation; read from a secrets manager at runtime
Secret identifier copied instead of valueThe stored string looks like a GUID; the portal shows the value only once at creationCreate a new secret and store its valueWrite the value straight into the secrets manager at creation
Credential missingEntra AADSTS7000218 "The request body must contain the following parameter: 'client_assertion' or 'client_secret'."Send the credential; check environment variable injectionFail fast at start-up when credentials are absent
Public client sending a secretEntra AADSTS700025 "Client is public so neither 'client_assertion' nor 'client_secret' should be presented."Remove the credential, or register a confidential client for server-side useDo not embed secrets in mobile, desktop or browser apps
Client disabledEntra AADSTS7000112 "The application is disabled."; Google disabled_client "The OAuth client was disabled."Find out who disabled it and why before re-enablingTreat disablement as a possible security action

Entra-specific service principal errors are covered in more depth in the Entra Service Principal Sign-In Errors Guide (AADSTS7000215, 7000222, 700016).

invalid_client with JWT assertions

With private_key_jwt (or client_secret_jwt), the client sends client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer and a signed JWT in client_assertion. RFC 7523 section 3.2 requires an invalid client JWT to produce invalid_client. Decode the assertion locally (it contains no secret, but treat it as sensitive until it expires) and check:

FieldWhat the server expectsCommon fault
iss and subBoth equal the client ID (RFC 7523; Okta and Entra state the same)Service account email or object ID used instead of the client ID
audThe authorisation server; Entra documents https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token; Okta requires the full URLIssuer URL instead of token endpoint, wrong tenant, trailing slash, v1 versus v2 endpoint
exp, nbf, iatShort lifetime: Okta rejects exp more than one hour ahead or in the past and iat after receipt; Microsoft recommends exp 5 to 10 minutes after nbf at mostClock skew on the signing host; assertion cached and reused past expiry
jtiUnique; Okta allows single use only when presentLibrary reuses a cached assertion across requests or retries
Header kid, x5t#S256, algIdentifies a key registered for the client; Entra documents PS256 and the certificate's SHA-256 thumbprintCertificate rotated on the client but not uploaded, or the old one removed first; Entra AADSTS700027 "Client assertion failed signature validation"
HMAC secret (client_secret_jwt)Okta requires at least 32 charactersOkta returns "The client secret is too short to verify a JWT HMAC."

Design guidance for this method is in the JWT Client Authentication (private_key_jwt) Guide.

invalid_client with mutual TLS

RFC 8705 (Standards Track, February 2020) defines two methods. With tls_client_auth the server validates the certificate chain and matches exactly one registered subject value: tls_client_auth_subject_dn or one of the SAN parameters (_san_dns, _san_uri, _san_ip, _san_email). With self_signed_tls_client_auth the server only checks the certificate against the client's registered jwks or jwks_uri. A missing or non-matching certificate returns invalid_client.

  • Certificate never arrived: a load balancer or API gateway terminated TLS and did not forward the certificate. Check the authorisation server's logs for the presented certificate, not the client's.
  • Wrong endpoint: if the server's metadata publishes mtls_endpoint_aliases, mTLS clients must use those endpoints. Calling the conventional token endpoint gets no certificate request.
  • Subject mismatch: renewed certificate with a different DN ordering or SAN than registered. Compare the exact string.
  • Chain not trusted: intermediate missing or issued by a CA the server does not trust for client authentication.
  • Token later rejected at the API: certificate-bound tokens carry cnf with x5t#S256; a resource server seeing a different certificate returns 401 invalid_token, not invalid_client.

See the mTLS Guide for certificate design.

unauthorized_client: causes and fixes

CauseEvidenceFix
Grant type not enabled on the clientAuth0 and Okta store allowed grants per application (Auth0 grant_types); the request uses one not in the listEnable only the grant the use case needs
Public client asking for client credentialsAuth0: public applications (token_endpoint_auth_method none) cannot use client_credentialsRegister a separate confidential client for the server workload; do not convert the public one
Google domain-wide delegation not authorised"Unauthorized client or scope in request."Authorise the service account's client ID and scopes in the Admin console; Google says allow up to 24 hours
Delegation registered the wrong way"Client is unauthorized to retrieve access tokens using this method"; authorised by email address or via a groupRe-add using the numeric client ID
Third-party or restricted app typeAuth0 third-party applications only support authorisation code with PKCE, refresh token and client credentials (confidential only)Use a supported grant
Client not present or not consented in the tenantEntra AADSTS700016 (UnauthorizedClient_DoesNotMatchRequest)Correct the tenant or have an administrator add and consent to the application

Choosing the client authentication method

Some errors go away permanently with a better method. Use this when the fix is a redesign rather than a correction.

MethodTypical errorsBest forTrade-off
client_secret_basic / _postEncoding, expiry, stale secretSmall estates, low-risk integrationsShared secret can leak and be replayed; needs rotation
private_key_jwtClaim and clock errors, key rolloverMost server workloads; recommended over secretsKey management and clock discipline required
tls_client_auth / self_signed_tls_client_authProxy termination, subject mismatchHigh-assurance and regulated APIs; certificate-bound tokensInfrastructure must pass certificates end to end
Workload identity federationTrust and claim mismatchesCloud and CI workloads with a platform-issued identityDepends on platform support; see the Multi-Cloud Workload Identity Troubleshooting Guide

Small organisations can stay on well-managed secrets with expiry alerts; larger estates should move server workloads to asymmetric or federated credentials so the commonest invalid_client causes disappear.

Diagnosis workflow, testing and rollback

  1. Capture: endpoint, client ID, grant_type, authentication method used, response status, WWW-Authenticate header and full error body. Redact secrets and assertions.
  2. Read the server log: Entra sign-in logs for service principals, Okta System Log, Auth0 tenant logs, Google Cloud audit logs. They usually state which check failed.
  3. Classify: authentication (invalid_client) or permission (unauthorized_client).
  4. Reproduce against a non-production client with the same settings using the same library version.
  5. Change one thing: for credential issues, add the new credential alongside the old, deploy, confirm, then remove the old. Rolling back is then just pointing at the previous credential.
  6. Clean up: delete any extra secrets or grant types added during troubleshooting.

Where identity fits

An OAuth client is a non-human identity, and every secret or certificate added to it is another way in. Credentials created in a hurry to clear an outage are often never removed, which is exactly the kind of extra cloud credential attackers add for persistence (MITRE ATT&CK T1098.001). The Microsoft Midnight Blizzard breach shows how a forgotten test tenant and an OAuth app opened executive mailboxes. Give each client an owner, keep credentials in a secrets manager, and alert on new credentials; see How to Detect new credentials added to an app registration and the Client ID and Client Secret Guide.

Detection and measurement

  • invalid_client rate per client ID: a burst after a deployment or rotation, or a steady trickle from an unknown source IP (possible credential guessing or a leaked client ID).
  • unauthorized_client events: each one is either a misconfiguration or a client attempting a grant it should not use; review all.
  • Credentials per client: clients with more than two active secrets or certificates.
  • Days to expiry: secrets and certificates expiring within 30 days, with owner notified.
  • Share of clients on asymmetric or federated credentials: trending up across the estate.

Common failure patterns

  • New secret for every error: credentials pile up and none are removed.
  • Enabling every grant type: clears unauthorized_client and lets the client obtain tokens in ways nobody reviewed.
  • Converting a public client to confidential: to use client credentials from a browser or mobile app, which then ships the secret to every user.
  • Removing the old certificate first: a rollover that breaks every instance still signing with the old key.
  • Secrets in configuration files: copied between environments, so a staging secret meets a production client ID (and the file itself is a target, ATT&CK T1552.001).

Framework mapping

FrameworkReferenceRelevance
NIST SP 800-53 Rev. 5IA-9 Service Identification and Authentication; IA-5 Authenticator Management; AU-6 Audit Record ReviewAuthenticating clients, managing their secrets and keys, reviewing failures
NIST CSF 2.0PR.AA-01; PR.AA-03Managing and authenticating service identities
ISO/IEC 27001:2022A.5.17 Authentication information; A.8.5 Secure authenticationSecret handling and authentication method strength
MITRE ATT&CKT1098.001 Additional Cloud Credentials; T1552.001 Credentials In Files; T1078.004 Cloud AccountsAbuse of extra, stored or stolen client credentials
IETFRFC 6749 s2.3 and s5.2; RFC 7523 s3.2; RFC 8705Where the errors and methods are defined

Practitioner checklist

  • Distinguish authentication failure from grant permission failure before changing anything.
  • Confirm endpoint, tenant and client ID match the environment.
  • Send exactly one client authentication method, matching the registration.
  • URL-encode client ID and secret before Base64 for Basic authentication.
  • Decode and check iss, sub, aud, exp, jti and key ID on every assertion failure.
  • Confirm the client certificate reaches the authorisation server and the mTLS endpoint alias is used.
  • Enable only the grant types each client needs.
  • Rotate with overlap and remove any credentials added during troubleshooting.
  • Alert on new client credentials and on expiry within 30 days.
  • Move server workloads from shared secrets to private_key_jwt, mTLS or federation.

Standards and references

Related NHI Mgmt Group resources: OAuth invalid_grant Error Troubleshooting Guide · Machine-to-Machine OAuth (Client Credentials) Guide · JWT Client Authentication (private_key_jwt) Guide · Azure Entra Client Secrets Security Guide · OAuth 2.0 and OpenID Connect Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 11 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org