Dynamic Client Registration (DCR)#
Dynamic Client Registration is configured at the SDK Layer. When attestation is unavailable or rejected, the SDK uses the configured DCRConfiguration to register a per-device dynamic OAuth client and uses that client for subsequent token requests. For the concept and security trade-offs, see Dynamic Client Registration (DCR) .
Configuration#
DCR fallback requires two things from your app: a DCRConfiguration pointing at the server-side registration endpoint and template client ID, and a non-attestation client authentication method (Secret, MTLS, or Signed JWT). See Client Authentication for the available methods.
let dcrConfiguration = DCRConfiguration(
templateClientId: "dcr-template-client-haapi-ios",
clientRegistrationEndpointUrl: URL(
string: "/oauth/oauth-registration",
relativeTo: baseURL
)!
)
let haapiAccessor = HaapiAccessorBuilder(haapiConfiguration)
.setDCRConfiguration(dcrConfiguration)
.setClientAuthenticationMethod(method: ClientAuthenticationMethodSecret("foo"))
.buildForHaapi() val dcrConfiguration = DcrConfiguration(
templateClientId = "dcr-template-client-haapi-android",
clientRegistrationEndpointUri = URI.create("$baseURLString/oauth/oauth-registration"),
context = applicationContext
)
GlobalScope.launch(Dispatchers.IO + coroutineExceptionHandler) {
val haapiAccessor = HaapiAccessorFactory(haapiConfiguration)
.setDcrConfiguration(dcrConfiguration)
.setClientAuthenticationMethodConfiguration(
ClientAuthenticationMethodConfiguration.Secret(secret = "foo")
)
.createForHaapi(onCoroutineContext = this.coroutineContext)
} DCR is configured per platform by attaching dcrConfiguration to the platform config record. The native bridge selects attestation or DCR at runtime — your JS code does not branch.
import {
createIOSConfiguration,
createAndroidConfiguration,
secretAuthentication,
ApplicationContextOption,
} from 'identityserver.haapi.reactnative.sdk'
const iosConfig = createIOSConfiguration({
clientId: 'haapi-ios-client',
appRedirect: 'app://haapi',
clientAuthenticationMethodConfiguration: secretAuthentication('foo'),
dcrConfiguration: {
templateClientId: 'dcr-template-client-haapi-ios',
clientRegistrationEndpointUrl:
'https://idsvr.example.com/oauth/oauth-registration',
},
})
const androidConfig = createAndroidConfiguration({
clientId: 'haapi-android-client',
appRedirect: 'app://haapi',
clientAuthenticationMethodConfig: secretAuthentication('foo'),
dcrConfiguration: {
templateClientId: 'dcr-template-client-haapi-android',
clientRegistrationEndpointUrl:
'https://idsvr.example.com/oauth/oauth-registration',
contextOption: ApplicationContextOption.Default,
},
})AndroidDcrConfiguration extends the shared DcrConfiguration with contextOption (defaults to ApplicationContextOption.Default); IOSDcrConfiguration adds no extra fields. Both platforms still require a non-noAuthentication client authentication method.
Server-Side Prerequisites#
DCR is a coordinated client-and-server feature. Configure two clients on the Curity Identity Server before the client-side configuration above will work:
- A main HAAPI client with a real authentication method (Secret, MTLS, or Signed JWT). These are the credentials that ship with your app and that the SDK uses to bootstrap the dynamic-registration request. The main client must not use
no-authentication. - A template HAAPI client carrying the
haapicapability. This client defines the shape of the per-device dynamic clients that will be created — capabilities, allowed scopes, token settings. The template client must reference the main client via theauthenticate-client-bysetting, which is how the server ties the registration request (authenticated as the main client) to the template it spawns from.
The OAuth profile must also expose the dynamic-client-registration endpoint (oauth-registration). Its URL goes into the client-side configuration as clientRegistrationEndpointUrl (iOS) or clientRegistrationEndpointUri (Android).
For the full server-side walkthrough, see Implementing HAAPI Attestation Fallback on the Curity resources site.
Runtime Selection#
Configure DCR unconditionally. HaapiAccessorBuilder (iOS) and HaapiAccessorFactory (Android) decide at runtime which path to take — attestation when the device supports it, DCR fallback when it does not. The SDK ignores the DCR configuration on attestation-capable devices, so there is no need to detect device capabilities yourself or branch on them. Ship one configuration that covers both cases.
When configuring DCR, the client authentication method must be set to one of Secret, MTLS, or Signed JWT — not the default None. DCR bootstraps a per-device dynamic client; doing so requires the SDK to authenticate the main client when calling the registration endpoint, and that authentication is what this method provides. Without it, the registration call fails before reaching the server.
How to implement this: DCR (concept) · Attestation and Fallback · How to Configure DCR Fallback · Client Authentication