Three lines

Uber

Developers

Dynamic Client Registration

Overview

Dynamic Client Registration (DCR) lets your backend programmatically register a new OAuth application with Uber without using the Developer Dashboard. This is useful when you need to create client credentials on behalf of multiple sub-organizations or partners at scale.

The registered client uses private_key_jwt for token endpoint authentication. You provide a JSON Web Key Set (JWKS) containing your RSA public key; Uber stores it and validates your signed client assertions during token requests.

OAuth 2.0 endpoints

Authorization Host https://auth.uber.com
Token Endpoint https://auth.uber.com/oauth/v2/token
DCR Endpoint https://api.uber.com/oauth/v2/clients

Required Scopes

Two scopes grant access to the DCR endpoint, depending on your integration type:

Scope Grant Type When to use
oauth.dcr Authorization Code Your end user (organization admin) authorizes the registration via an OAuth consent flow
oauth.dcr.b2b Client Credentials Your backend registers clients server-to-server without a user present

Contact your Uber Partner Engineer to request one of these scopes for your application.


Prerequisites
  • A Developer account and application registered at developer.uber.com
  • An RSA-2048 (or stronger) key pair. The JWKS you provide must contain the public key. You retain the private key and use it to sign client assertions when calling the token endpoint as the newly-registered client.

Generate a JWKS

Generate an RSA-2048 key pair locally. Send the public half as a JWKS in the jwks field of the registration request. Keep the private half securely; you’ll use it later to sign client assertions when calling the token endpoint as the registered client.

Golang
expand to see code snippets
import (
    "crypto/rand"
    "crypto/rsa"
    "encoding/base64"
    "encoding/json"
    "math/big"

    "github.com/google/uuid"
)

type jwk struct {
    Kty string `json:"kty"`
    Use string `json:"use"`
    Alg string `json:"alg"`
    Kid string `json:"kid"`
    N   string `json:"n"`
    E   string `json:"e"`
}

type jwks struct {
    Keys []jwk `json:"keys"`
}

// GenerateJWKS returns the JWKS string to send to Uber and the private key
// to retain locally for signing client assertions.
func GenerateJWKS() (string, *rsa.PrivateKey, error) {
    priv, err := rsa.GenerateKey(rand.Reader, 2048)
    if err != nil {
        return "", nil, err
    }
    pub := priv.PublicKey
    set := jwks{Keys: []jwk{{
        Kty: "RSA",
        Use: "sig",
        Alg: "RS256",
        Kid: uuid.New().String(),
        N:   base64.RawURLEncoding.EncodeToString(pub.N.Bytes()),
        E:   base64.RawURLEncoding.EncodeToString(big.NewInt(int64(pub.E)).Bytes()),
    }}}
    b, err := json.Marshal(set)
    if err != nil {
        return "", nil, err
    }
    return string(b), priv, nil
}
Java
expand to see code snippets
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.RSAKey;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;

public class JWKSGenerator {
    // Returns the JWKS JSON to send to Uber. Persist the KeyPair's private key
    // locally for signing client assertions later.
    public static String generateJWKS(KeyPair[] outKeyPair) throws Exception {
        KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
        gen.initialize(2048);
        KeyPair kp = gen.generateKeyPair();
        outKeyPair[0] = kp;

        RSAKey publicJwk = new RSAKey.Builder((RSAPublicKey) kp.getPublic())
                .keyUse(KeyUse.SIGNATURE)
                .algorithm(JWSAlgorithm.RS256)
                .keyID(UUID.randomUUID().toString())
                .build()
                .toPublicJWK();

        return new JWKSet(publicJwk).toString();
    }
}
Python
expand to see code snippets
import json
import uuid
from jwcrypto import jwk

def generate_jwks():
    # Generate an RSA-2048 key as a JWK
    key = jwk.JWK.generate(
        kty="RSA",
        size=2048,
        kid=str(uuid.uuid4()),
        use="sig",
        alg="RS256",
    )

    # Public-only JWKS for the DCR request body
    public_jwks = {"keys": [json.loads(key.export(private_key=False))]}

    # Private key (PEM) to retain locally for client_assertion signing
    private_pem = key.export_to_pem(private_key=True, password=None)

    return json.dumps(public_jwks), private_pem

Obtain an Access Token

Acquire an access token carrying either the oauth.dcr or oauth.dcr.b2b scope before calling the DCR endpoint:

Pass the resulting token in the Authorization: Bearer <access_token> header on all requests below.


Register a Client

Call the DCR endpoint with the access token obtained above. The request body is JSON.

Request Details:

  • Method: POST
  • URL: https://api.uber.com/oauth/v2/clients
  • Content-Type: application/json
  • Authorization: Bearer <access_token>

Request Body Parameters:

Parameter Type Required Description
client_name string Yes Display name for the new application
client_description string No Short description of the application
redirect_uris array of strings Yes (for auth-code clients) Allowed redirect URIs for the OAuth consent flow
jwks string (JSON) Yes JSON Web Key Set containing the RSA public key used for private_key_jwt authentication. Minimum 2048-bit modulus.
scope string No Space-delimited list of OAuth scopes to request. Defaults to all scopes approved for your integration if omitted.
privacy_policy_uri string No URL to the application’s privacy policy
webhook_uri string No HTTPS endpoint to receive Uber webhook events for this client
contacts array of strings No Developer email addresses to invite as collaborators on the registered application
organization_uuid string Yes UUID of the organization this client belongs to

Example Request:

curl -X POST 'https://api.uber.com/oauth/v2/clients' \
  -H 'Authorization: Bearer <ACCESS_TOKEN>' \
  -H 'Content-Type: application/json' \
  -d '{
    "client_name": "Ramen XYZ Payment Integration",
    "client_description": "Payment integration for Ramen XYZ partner stores",
    "redirect_uris": ["https://ramen-xyz.com/auth/callback"],
    "jwks": "{\"keys\":[{\"kty\":\"RSA\",\"use\":\"sig\",\"alg\":\"RS256\",\"kid\":\"my-key-1\",\"n\":\"<modulus>\",\"e\":\"AQAB\"}]}",
    "scope": "profile",
    "privacy_policy_uri": "https://ramen-xyz.com/privacy",
    "webhook_uri": "https://ramen-xyz.com/webhooks/uber",
    "contacts": ["dev@ramen-xyz.com"],
    "organization_uuid": "<YOUR_ORGANIZATION_UUID>"
  }'

Response Parameters:

Field Type Description
client_id string Unique identifier for the newly registered application
scope string Space-delimited list of scopes granted to the client
token_endpoint_auth_method string Always private_key_jwt — authenticate token requests by signing a JWT with your RSA private key
webhook_signing_secret string Present only when webhook_uri was provided. HMAC-SHA256 secret used to verify Uber webhook payloads. Store this securely; it will not be returned again.

Example Response:

{
  "client_id": "abc123xyz",
  "scope": "profile",
  "token_endpoint_auth_method": "private_key_jwt",
  "webhook_signing_secret": "a3f8c2...d9e1"
}

Webhook Verification

If you registered a webhook_uri, Uber signs each webhook payload using the webhook_signing_secret returned at registration. Verify the signature to confirm the payload is authentic:

  1. Extract the X-Uber-Signature header from the incoming request.
  2. Compute HMAC-SHA256(webhook_signing_secret, request_body).
  3. Compare your computed value with the header value. Reject the request if they do not match.

Error Handling
HTTP Status Error Description
400 invalid_request Required parameter missing or malformed
400 invalid_redirect_uri One or more redirect_uris are invalid or disallowed
400 invalid_jwks The jwks field could not be parsed, contains no usable RSA signing key, or the key is below the minimum required size (2048 bits)
401 unauthorized Missing or invalid access token
403 forbidden Access token does not carry the required oauth.dcr or oauth.dcr.b2b scope
429 too_many_requests Rate limit exceeded. Back off and retry.
500 server_error Unexpected server error

Next Steps

The registered client authenticates to Uber’s token endpoint using private_key_jwt. For details on building and signing the client_assertion JWT and exchanging it for an access token, see Client Asymmetric Key Authentication.

Uber

Developers
© 2026 Uber Technologies Inc.