Checklist
Describe the problem you'd like to have solved
With useDPoP: true, react-native-auth0 already uses a native DPoP keypair, but the library does not expose APIs to reuse that keypair for additional application-level cryptographic operations.
For our backend flow, DPoP validation is already in place and already gives the expected guarantees:
- request binding and replay protections via claims such as
htu, htm, jti, ath
- nonce handling when required by the resource server
- token/key binding via
cnf thumbprint (the access token is tied to that DPoP key)
After this standard DPoP validation, we also need to validate additional request data (for example, request body integrity) using the same cryptographic identity represented by the DPoP keypair.
Today this is not possible with official APIs, so apps cannot reliably reuse the native Auth0-managed keypair for those additional checks.
Describe the ideal solution
Expose native cryptographic APIs that reuse the same DPoP identity managed by Auth0 native SDKs:
getDPoPPublicKey()
signWithDPoPPrivateKey(payload: string | Uint8Array)
encrypt(payload: string | Uint8Array, recipientJwk?: Record<string, unknown>)
decrypt(ciphertext: string | Uint8Array)
Security expectation:
- private keys and key material must never be exported to JavaScript
- only native cryptographic operations should be exposed
- key usage must remain restricted to secure platform storage (iOS Keychain/Secure Enclave and Android Keystore)
Expected server-side validation order in the signature flow:
- validate
Authorization token
- validate
DPoP proof
- extract
jwk from validated DPoP
- validate
x-body-signature against request body with that jwk
Alternatives and current workarounds
Current workaround is patching node_modules to add custom native bridge methods on iOS and Android.
This is fragile and expensive to maintain over upgrades, and it can diverge from official Auth0 DPoP behavior over time.
Alternative of creating a second keypair outside Auth0 is also undesirable because it breaks the single cryptographic identity model already established by DPoP + cnf.
Additional context
Example API usage (body signature + DPoP):
import Auth0 from 'react-native-auth0';
const auth0 = new Auth0({
domain: 'YOUR_DOMAIN',
clientId: 'YOUR_CLIENT_ID',
useDPoP: true,
});
const method = 'POST';
const path = '/method-with-signed-payload';
const body = JSON.stringify({ data: 'information-to-be-signed' });
const dpopHeaders = /* regular getDPoPHeaders() creation */;
const bodySignature = await auth0.signWithDPoPPrivateKey(body);
await fetch(`https://api.example.com${path}`, {
method,
headers: {
'content-type': 'application/json',
'x-body-signature': bodySignature,
...dpopHeaders,
},
body,
});
Example API usage (encrypt/decrypt):
const statePlaintext = JSON.stringify({ data: 'sensitive-client-state' });
// Option A: encrypt to self
const encryptedState = await auth0.encrypt(statePlaintext);
// Option B: encrypt to an explicit recipient JWK
// const recipientJwk = { kty: 'EC', crv: 'P-256', x: '...', y: '...' };
// const encryptedState = await auth0.encrypt(statePlaintext, recipientJwk);
await fetch('https://api.example.com/state', {
method: 'PUT',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ state: encryptedState }),
});
const response = await fetch('https://api.example.com/state', { method: 'GET' });
const { state } = await response.json();
const decryptedState = await auth0.decrypt(state);
The server stores encrypted state but cannot read plaintext content in this model.
Platform expectations:
- iOS: use the same key material managed by Auth0.swift DPoP internals.
- Android: use the same key material managed by Auth0.Android DPoP internals.
- If keypair does not exist yet, return a clear, typed error (or document bootstrap requirement clearly).
- For encrypt/decrypt APIs, use secure device-bound keys managed in native keystore/keychain.
Error handling suggestion:
- keypair not found
- keychain/keystore access failure
- signing failure
- invalid payload input
- encryption/decryption failure
Checklist
Describe the problem you'd like to have solved
With
useDPoP: true,react-native-auth0already uses a native DPoP keypair, but the library does not expose APIs to reuse that keypair for additional application-level cryptographic operations.For our backend flow, DPoP validation is already in place and already gives the expected guarantees:
htu,htm,jti,athcnfthumbprint (the access token is tied to that DPoP key)After this standard DPoP validation, we also need to validate additional request data (for example, request body integrity) using the same cryptographic identity represented by the DPoP keypair.
Today this is not possible with official APIs, so apps cannot reliably reuse the native Auth0-managed keypair for those additional checks.
Describe the ideal solution
Expose native cryptographic APIs that reuse the same DPoP identity managed by Auth0 native SDKs:
getDPoPPublicKey()signWithDPoPPrivateKey(payload: string | Uint8Array)encrypt(payload: string | Uint8Array, recipientJwk?: Record<string, unknown>)decrypt(ciphertext: string | Uint8Array)Security expectation:
Expected server-side validation order in the signature flow:
AuthorizationtokenDPoPproofjwkfrom validatedDPoPx-body-signatureagainst request body with thatjwkAlternatives and current workarounds
Current workaround is patching
node_modulesto add custom native bridge methods on iOS and Android.This is fragile and expensive to maintain over upgrades, and it can diverge from official Auth0 DPoP behavior over time.
Alternative of creating a second keypair outside Auth0 is also undesirable because it breaks the single cryptographic identity model already established by DPoP +
cnf.Additional context
Example API usage (body signature + DPoP):
Example API usage (encrypt/decrypt):
The server stores encrypted state but cannot read plaintext content in this model.
Platform expectations:
Error handling suggestion: