# User Consent for Secure ID Verification

Some environments using the Secure ID Verification services will have a requirement to capture user consent for identity data processing. Where the environment does not already manage that consent in another way, the Secure ID Verification service provides a way for that consent to be managed within the service.

If user consent is required, then consent must be explicitly granted before identity verification using personally identifiable information. Consent may also be explicitly withdrawn by the user.

If identity verification is attempted before consent has been provided, in an environment when such consent is required to be managed by the service, the attempt will result in a `ConsentRequiredException` .

It is permissible to provide and withdraw consent to the service even in environments where consent is not required to be managed in this manner, however in this case such consent will not be checked.

## Determine whether User Consent is Required

To determine whether user consent is required to be managed by the Secure ID Verification service in the current environment, create an identityVerificationClient, and query the SDK:

{% tabs %}
{% tab title="Swift" %}

```swift
do {
    let consentRequired = try await identityVerificationClient.isConsentRequiredForVerification()
} catch {
    // Handle error. An error may be thrown if the backend is unable to perform
    // requested operation due to availability or security issues.
    // An error might be also be thrown for unrecoverable circumstances arising
    // from programmatic error or configuration error. For example, if the keychain
    // access entitlement is not set up correctly or basic system resources are
    // unavailable.
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
CoroutineScope(Dispatchers.IO).launch {
    try {
        val consentRequired = identityVerificationClient.isConsentRequiredForVerification()
    } catch (e: SudoIdentityVerificationException) {
        // Handle errors.
    }
}
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
try {
  const consentRequired = await identityVerificationClient.isConsentRequiredForVerification()
}
catch (err) {
  // Handle errors
}
```

{% endtab %}
{% endtabs %}

The `isConsentRequiredForVerification()` API returns a boolean value.

## Determine User Consent Status

To check the consent status of a user, create an identityVerificationClient, and query the SDK:

{% tabs %}
{% tab title="Swift" %}

```swift
do {
    let consentStatus = try await identityVerificationClient.getIdentityDataProcessingConsentStatus()
} catch {
    // Handle error. An error may be thrown if the backend is unable to perform
    // requested operation due to availability or security issues.
    // An error might be also be thrown for unrecoverable circumstances arising
    // from programmatic error or configuration error. For example, if the keychain
    // access entitlement is not set up correctly or basic system resources are
    // unavailable.
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
CoroutineScope(Dispatchers.IO).launch {
    try {
        val consentStatus = identityVerificationClient.getIdentityDataProcessingConsentStatus()
    } catch (e: SudoIdentityVerificationException) {
        // Handle errors.
    }
}
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
try {
  const consentStatus = await identityVerificationClient.getIdentityDataProcessingConsentStatus()
}
catch (err) {
  // Handle errors
}
```

{% endtab %}
{% endtabs %}

&#x20;As well as returning a boolean indicator of the current consent status, the status response also provides the following information about the state of user consent:

* the `consentedAtEpochMs` property, if present, indicates when consent was provided. If consent has not been provided, this value will be empty.
* the `consentWithdrawnAtEpochMs` property, if present, indicates when consent was withdrawn. If consent has not been withdrawn, this value will be empty.
* the `content` property, if present, includes the agreement that the user consented to. If consent has not been provided, this value will be empty.
* the `contentType` property, if present, indicates the content type of the consent agreement provided in `content`. If consent has not been provided, this value will be empty.
* the `language` property, if present, indicates the RFC 5646 language code of the consent agreement provided in `content`. If consent has not been provided, this value will be empty.

## Collect and Provide User Consent

When collecting user consent, create an identity verification client and query the SDK for the consent to be displayed to the user.&#x20;

Provide the user's preferred language - likely from their current system settings - and a content type usable by the application. The service will attempt to provide the consent content in a content type and language most closely matching the preferences, but will fall back to a default which may not match if necessary.

Display the content to the user for agreement. Once agreement has been received, the consent information should be provided back to the SDK for recording.&#x20;

{% tabs %}
{% tab title="Swift" %}

```swift
do {
    let preferredLanguage = "en-US" // provide the user's current language
    let preferredContentType = "text/plain" // provide the application's preferred content type
    let input = IdentityDataProcessingConsentContentInput(
        preferredContentType: preferredContentType, 
        preferredLanguage: preferredLanguage)
    let consentContent = try await 
        identityVerificationClient.getIdentityDataProcessingConsentContent(
            input:input
        )
    // display consent content to the user to grant their consent
} catch {
    // Handle error. 
}

do {
    // provide consent input based on response of consent content above
    let content = consentContent.content
    let contentType = consentContent.contentType
    let language = consentContent.language
    let input = IdentityDataProcessingConsentInput(
        content: content, 
        contentType: contentType, 
        language: language
    )
    let provideConsentResult = try await 
        identityVerificationClient.provideIdentityDataProcessingConsent(
            input:input
        )
    
} catch {
    // Handle error. 
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
CoroutineScope(Dispatchers.IO).launch {
    try {
        val preferredLanguage = "en-US" // provide the user's current language
        val preferredContentType = "text/plain" // provide the application's preferred content type
        val consentContent = identityVerificationClient.getIdentityDataProcessingConsentContent(
            IdentityDataProcessingConsentContentInput(
                preferredContentType = preferredContentType, 
                preferredLanguage = preferredLanguage
            )
        )
    // display consent content to the user to grant their consent
    } catch (e: SudoIdentityVerificationException) {
        // Handle errors.
    }
}

CoroutineScope(Dispatchers.IO).launch {
    try {
        // provide consent input based on response of consent content above
        var content = consentContent.content
        var contentType = consentContent.contentType
        var language = consentContent.language
        var provideConsentResult = identityVerificationClient.provideIdentityDataProcessingConsent(
            IdentityDataProcessingConsentInput(
                content: content, 
                contentType: contentType,
                language: language
            )
        )
    } catch (e: SudoIdentityVerificationException) {
        // Handle errors.
    }
}
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
try {
    const preferredLanguage = "en-US" // provide the user's current language
    const preferredContentType = "text/plain" // provide the application's preferred content type
    const consentContent = await 
        identityVerificationClient.getIdentityDataProcessingConsentContent({ 
            preferredContentType: preferredContentType, 
            preferredLanguage: preferredLanguage
        })
    // display consent content to the user to grant their consent
  }
catch (err) {
  // Handle errors
}

try {
    // provide consent input based on response of consent content above
    let content = consentContent.content
    let contentType = consentContent.contentType
    let language = consentContent.language
    let provideConsentResult = await 
        identityVerificationClient.provideIdentityDataProcessingConsent({
            content: content, 
            contentType: contentType,
            language: language
        })
} catch (err) {
    // Handle errors 
}
```

{% endtab %}
{% endtabs %}

## Withdraw User Consent

To withdraw the consent status of a user, create an identityVerificationClient, and invoke the SDK:

{% tabs %}
{% tab title="Swift" %}

```swift
do {
    let withdrawStatus = try await identityVerificationClient.withdrawIdentityDataProcessingConsent()
} catch {
    // Handle error. An error may be thrown if the backend is unable to perform
    // requested operation due to availability or security issues.
    // An error might be also be thrown for unrecoverable circumstances arising
    // from programmatic error or configuration error. For example, if the keychain
    // access entitlement is not set up correctly or basic system resources are
    // unavailable.
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
CoroutineScope(Dispatchers.IO).launch {
    try {
        val withdrawStatus = identityVerificationClient.withdrawIdentityDataProcessingConsent()
    } catch (e: SudoIdentityVerificationException) {
        // Handle errors.
    }
}
```

{% endtab %}

{% tab title="TypeScript" %}

```typescript
try {
  const withdrawStatus = await identityVerificationClient.withdrawIdentityDataProcessingConsent()
}
catch (err) {
  // Handle errors
}
```

{% endtab %}
{% endtabs %}

Withdrawing of consent does not invalidate any previously verified identity, but it does prevent further secure ID verification for that user.
