Three lines

Uber

Developers

Client Asymmetric Key Authentication

Overview

In this doc we will cover how to interact with Uber OAuth server to obtain access token and how to generate client assertion JWT using asymmetric key authentication method(based on OIDC Core 1.0 specification)

Prerequisite

We assume you have already done the following when you are reading this page

  1. registered an account and created Uber developer application at https://developer.uber.com
  2. requested OAuth scopes for your application(if not please contact your Uber Partner Engineer or Account Executive)
  3. downloaded asymmetric key file from your app’s Setup tab

Generate Access Token - Manual integration

It’s encouraged to conduct manual test before programmatically integrating with your production system. This section provides step-by-step guide to manually generate access token with the asymmetric key.

Example request and response

The example below generates access token with client_credentials grant type. Please refer to Supported Grant Types for more examples for other grant types such as authorization_code, refresh_token, or token_exchange.

# request
curl -X POST "https://auth.uber.com/oauth/v2/token" \
     -d 'scope=${space_delimited_scopes}' \
     -d 'grant_type=client_credentials' \
     -d 'client_assertion=${client_assertion_you_generated}' \
     -d 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer'

# response
{
    "access_token": "${access_token}",
    "token_type": "Bearer",
    "expires_in": "${expiry_in_epoch}",
    "scope": "${scopes_you_requested}"
}

Explanation of the request parameters

  • scope: it’s a list of OAuth scopes granted to your app delimited by space
  • client_assertion: it’s a JWT to authenticate your application, please follow the tutorial below to generate it

How to generate client assertion

header:

  • alg: RS256, String
  • typ: JWT, String
  • kid: key id from key file, String

payload:

  • iss: The client ID of the developer application, String
  • sub: The client ID of the developer application, String
  • aud: auth.uber.com, String
  • jti: A unique identifier for the JWT, String (can be generated from here)
  • exp: The expiration time of the JWT, Int (can be generated from here, make sure use your local time)

get public key from the downloaded key file and convert it to PEM format:

echo "${public_key_from_key_file}" | sed 's/\\n/\n/g'

get private key from the downloaded key file and convert it to PEM format:

echo "${private_key_from_key_file}" | sed 's/\\n/\n/g'

We will use jwt.io to generate client assertion JWT, you are welcome to use any library or tool

jwt_io_guide

IMPORTANT: client assertion is one-time-only, you need to generate a new client assertion each time you call /token endpoint. All you need to do is replace the jti claim with a new random UUID then generate a new client assertion.

Generate Access Token - Programmatic integration

To integrate your backend with Uber OAuth server, please refer to Authorization API and Access Token API.

This section provides code snippets that you can use in programmatic integration, please note that we do NOT provide key file I/O logic because different customers might handle I/O differently.

Golang

expand to see code snippets
import (
	"crypto/rsa"
	"github.com/golang-jwt/jwt"
	"github.com/google/uuid"
)

func GenerateJWT(clientID string, privateKey *rsa.PrivateKey, keyID string) (string, error) {
	claims := jwt.MapClaims{
		"iss": clientID,
		"sub": clientID,
		"aud": "auth.uber.com",
		"jti": uuid.New().String(),
		"exp": time.Now().Add(1 * time.Hour).Unix(),
	}

	token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
	token.Header["kid"] = keyID

	return token.SignedString(privateKey)
}

func LoadPrivateKey(path string) (*rsa.PrivateKey, error) {
	// Implementation to load private key from file
	// ...
}

Java

expand to see code snippets
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.security.interfaces.RSAPrivateKey;
import java.time.Instant;
import java.util.Date;
import java.util.UUID;

public class JWTGenerator {
    public static String generateJWT(String clientId, RSAPrivateKey privateKey, String keyId) {
        Instant now = Instant.now();
        return JWT.create()
                .withKeyId(keyId)
                .withIssuer(clientId)
                .withSubject(clientId)
                .withAudience("auth.uber.com")
                .withJWTId(UUID.randomUUID().toString())
                .withExpiresAt(Date.from(now.plusSeconds(3600)))
                .sign(Algorithm.RSA256(null, privateKey));
    }

    public static RSAPrivateKey loadPrivateKey(String path) throws Exception {
        // Implementation to load private key from file
        // ...
    }
}

Python

expand to see code snippets
import jwt
import uuid
from datetime import datetime, timedelta

def generate_jwt(client_id, private_key, key_id):
    now = datetime.utcnow()
    payload = {
        "iss": client_id,
        "sub": client_id,
        "aud": "auth.uber.com",
        "jti": str(uuid.uuid4()),
        "exp": int((now + timedelta(hours=1)).timestamp())
    }
    headers = {
        "alg": "RS256",
        "typ": "JWT",
        "kid": key_id
    }
    return jwt.encode(payload, private_key, algorithm="RS256", headers=headers)

def load_private_key(path):
    # Implementation to load private key from file
    # ...

Supported Grant Types

Asymmetric key authentication is supported for these grant types:

  • client_credentials
  • authorization_code
  • refresh_token
  • urn:ietf:params:oauth:grant-type:token-exchange

This section will provide CLI examples for each grant type

Client Credentials

expand to see example
# request
curl -X POST "https://auth.uber.com/oauth/v2/token" \
     -d 'scope=${space_delimited_scopes}' \
     -d 'grant_type=client_credentials' \
     -d 'client_assertion=${client_assertion_you_generated}' \
     -d 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer'

# response
{
    "access_token": "${access_token}",
    "token_type": "Bearer",
    "expires_in": "${expiry_in_epoch}",
    "scope": "${scopes_you_requested}"
}

Authorization Code

expand to see example

firstly call /authorize to get the authorization code

# end user will trigger this request from their browser
https://auth.uber.com/oauth/v2/authorize?client_id=${CLIENT_ID}&response_type=code&redirect_uri=${REDIRECT_URI}&scope=${SPACE_DELIMITED_SCOPES}

# response
HTTP/1.1 302 Found
Location: https://${REDIRECT_URI}?code=${AUTHORIZATION_CODE}

secondly call /token to exchange for access token

# request
curl -X POST "https://auth.uber.com/oauth/v2/token" \
     -d 'scope=${space_delimited_scopes}' \
     -d 'grant_type=authorization_code' \
     -d 'redirect_uri=${REDIRECT_URI}' \
     -d 'code=${AUTHORIZATION_CODE_FROM_ABOVE_STEP}' \
     -d 'client_assertion=${client_assertion_you_generated}' \
     -d 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer'

# response
{
    "access_token": "${access_token}",
    "refresh_token": "${refresh_token}"
    "token_type": "Bearer",
    "expires_in": "${expiry_in_epoch}",
    "scope": "${scopes_you_requested}"
}

Refresh Token

expand to see example

Prerequisite

To integrate with the refresh token flow, you need to obtain refresh token from Authorization Code response

# request
curl -X POST "https://auth.uber.com/oauth/v2/token" \
     -d 'grant_type=refresh_token' \
     -d 'refresh_token=${refresh_token_value}' \
     -d 'client_assertion=${client_assertion_you_generated}' \
     -d 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer'

# response
{
    "access_token": "${access_token}",
    "refresh_token": "${refresh_token}"
    "token_type": "Bearer",
    "expires_in": "${expiry_in_epoch}",
    "scope": "${scopes_you_requested}"
}

Token Exchange

expand to see example
# request
curl -X POST "https://auth.uber.com/oauth/v2/token" \
     -d 'scope=${space_delimited_scopes}' \
     -d 'subject_token=${id_token}' \
     -d 'subject_token_type=urn:ietf:params:oauth:token-type:id_token' \
     -d 'requested_token_type=urn:ietf:params:oauth:token-type:jwt' \
     -d 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
     -d 'client_assertion=${jwt_assertion_you_generated}'

# response
{
    "access_token": "${jwt_token}",
    "token_type": "N_A",
    "issued_token_type": "urn:ietf:params:oauth:token-type:jwt"
}

Error Code

This section covers possible error code and message

expand to see error codes
Type Code Description
unsupported_grant_type 400 grant type is not supported
invalid_grant 400 user has no authorized client for required scopes
invalid_grant 400 code verifier failed verification
invalid_request 400 could not parse token request
invalid_request 400 code cannot be empty
invalid_request 400 missing <claim_name> claim
invalid_request 400 sub claim must be equal to iss claim
invalid_request 400 aud must be auth.uber.com
invalid_request 400 exp claim must be greater than current time
invalid_request 400 public key disabled, kid: <key_id>
invalid_request 400 public key not found, kid: <key_id>
invalid_client 401 client secret, jwt bearer and code verifier cannot be all empty for client authentication
invalid_client 401 client ID is invalid
unauthorized_client 401 the current application environment is mismatched with the OAuth server runtime environment
access_denied 403 client authentication failed because the client_id + jti already used
server_error 500 there was an unexpected error; please try again later

Uber

Developers
© 2025 Uber Technologies Inc.