Introduction

After successfully completing the OIDC authorization code flow and obtaining an access token, calling the UserInfo endpoint may return 401 Unauthorized. This is unexpected because the token was just obtained. The issue typically involves missing openid scope, token type mismatches (opaque vs JWT), audience configuration, or the access token being intended for a different resource server.

Symptoms

  • UserInfo endpoint returns:
  • `
  • HTTP/1.1 401 Unauthorized
  • WWW-Authenticate: Bearer error="invalid_token",
  • error_description="The access token is invalid or expired"
  • `
  • Or:
  • `
  • HTTP/1.1 401 Unauthorized
  • WWW-Authenticate: Bearer error="insufficient_scope",
  • error_description="The request requires higher privileges"
  • `
  • Token introspection shows the token is valid but UserInfo still rejects it
  • Works in Postman but fails in application code

Common Causes

  • Access token does not include openid scope in the authorization request
  • Token is a JWT meant for a different audience (API resource)
  • Access token expired between token exchange and UserInfo call
  • UserInfo endpoint URL is incorrect (wrong issuer or base path)
  • Bearer token not properly formatted in Authorization header
  • IdP requires specific claims in the token for UserInfo access

Step-by-Step Fix

# Check the 'scope' claim includes 'openid' # Check 'aud' matches your client_id # Check 'exp' is not in the past ```

Prevention

  • Always include openid scope in the authorization request
  • Store the UserInfo endpoint URL from .well-known/openid-configuration
  • Call UserInfo immediately after token exchange before token expiration
  • Validate token claims (scope, aud, exp) before making UserInfo calls
  • Use OIDC SDK libraries that handle token validation automatically
  • Log the full UserInfo response and headers for debugging in production