---
updatedAt: 2026-08-28T23:29:13.000Z
agentTools:
  projectIndex: https://developer.onetrust.com/onetrust/llms.txt
---

# Age-Based Consent

This page provides context on how to implement an age-based consent solution for the OneTrust MAUI and Unity SDK.

<Callout icon="📘" theme="info">
  This feature is available as of 202608.1.0 and above.&#x20;
</Callout>

## Overview

Age-Based Consent in the OneTrust .NET MAUI SDK helps your application enforce consent rules based on a user's age range. Administrators configure age-range groups in the OneTrust admin console and associate them with specific purposes or purpose groups. The SDK uses this configuration, along with the age range provided by your application, to enforce consent behavior at runtime.

When a user falls within a restricted age range:

* Consent for associated categories is automatically denied.
* The corresponding category toggles in the Preference Centre are hidden or disabled.

This ensures that age-based restrictions are consistently applied without requiring additional UI logic in the app.

## How it works

At a high level:

1. Your .NET MAUI app provides the user's age range.
2. The SDK sends this data to the OneTrust server.
3. The server determines consent restrictions based on your settings in the admin console.
4. When Age-Based Consent restrictions apply, the SDK keeps restricted categories denied and prevents them from being enabled through the public APIs.

## What's Changing

### SDK Updates

* `ICustomConfigurator.GetProfileAgeRange` callback to provide the user's age range.
* `ProfileAgeRange` data model with lower and upper bounds.
* Automatic consent restriction based on age overlap.
* Age range changes logged to the server through the `AGEGATE_RANGE` interaction.

### Server (CMP API) updates

* Accepts and stores user age range data.
* Enforces restrictions by setting `consentToggleStatus = -1` for restricted categories.
* Maintains enforcement across devices for the same user profile.

## Implementation

### 1. Data model: `ProfileAgeRange`

`ProfileAgeRange` represents a user’s age range.

| Property     | Type   | Description |
| ------------ | ------ | ----------- |
| `LowerBound` | `int?` | Minimum age |
| `UpperBound` | `int?` | Maximum age |

```csharp
using OTSDK.Models.AgeGateModels;

// 13-17 years old
var range1 = new ProfileAgeRange(13, 17);

// 18+ (open-ended)
var range2 = new ProfileAgeRange(18, null);

// 0-12 years old
var range3 = new ProfileAgeRange(null, 12);

// Age unknown
ProfileAgeRange unknown = null;
```

<Callout icon="📘" theme="info">
  Note: At least one bound is required. Both values cannot be null at the same time.
</Callout>

Use `LowerBound` and `UpperBound` to represent the user's age range. Each value is optional, but at least one bound must be provided. Use `null` for an open-ended range such as 18+, or for ranges that start from the youngest supported age.

### 2. Set up the age range provider

Implement `ICustomConfigurator` and assign it to `CMPSDK.sharedInstance.CustomConfigurator` before calling `StartSDK`. The SDK invokes `GetProfileAgeRange` during initialization so it can retrieve the user's age range before applying consent restrictions.

```csharp
using System;
using OneTrust;
using OTSDK.Models.AgeGateModels;

public class MainPageViewModel : ICustomConfigurator
{
    public MainPageViewModel()
    {
        CMPSDK.sharedInstance.CustomConfigurator = this;
    }

    public void GetProfileAgeRange(string profileId, Action<ProfileAgeRange> completion)
    {
        // Fetch age range from your user profile system.
        // This can be synchronous or asynchronous.
        var user = GetUserAgeRange(profileId);

        if (user == null)
        {
            completion(null); // Age unknown
            return;
        }

        completion(new ProfileAgeRange(user.Min, user.Max));
    }
}
```

### Sample reference:

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using OneTrust;
using OTSDK.Models.AgeGateModels;

public class OneTrustInitializer : ICustomConfigurator
{
    public async Task InitializeOneTrust()
    {
        // Step 1: Register the age range provider
        CMPSDK.sharedInstance.CustomConfigurator = this;

        // Step 2: Initialize the SDK
        var sdkParams = new Dictionary<string, string>
        {
            { "cdnLocation", "YOUR_CDN_LOCATION" },
            { "domainId", "YOUR_DOMAIN_ID" },
            { "languageCode", "en" },
            { "apiVersion", "YOUR_API_VERSION" }
        };

        var result = await CMPSDK.sharedInstance.StartSDK(sdkParams);

        if (result.hasException)
        {
            Console.WriteLine($"SDK initialization failed: {result.exception}");
        }
        else
        {
            Console.WriteLine("SDK initialized successfully");
        }
    }

    public void GetProfileAgeRange(string profileId, Action<ProfileAgeRange> completion)
    {
        var ageRange = GetAgeRangeForProfile(profileId);

        if (ageRange != null)
        {
            completion(new ProfileAgeRange(ageRange.Min, ageRange.Max));
        }
        else
        {
            completion(null);
        }
    }
}
```

## Public APIs

### `ICustomConfigurator.GetProfileAgeRange`

Implement this callback so that the SDK can request the user's age range.

```csharp
void GetProfileAgeRange(string profileId, Action<ProfileAgeRange> completion);
```

| Parameter    | Type                      | Description                                                 |
| ------------ | ------------------------- | ----------------------------------------------------------- |
| `profileId`  | `string`                  | The profile identifier for which the age range is requested |
| `completion` | `Action<ProfileAgeRange>` | Invoke with the age range, or `null` if age is unknown      |

The SDK invokes your implementation during the `StartSDK` initialization.

### `getConsentStatusForCategory`

Returns the consent status for a category.

```csharp
// Get a specific category
int status = CMPSDK.sharedInstance.getConsentStatusForCategory("C0005");
```

| Status | Meaning                                             |
| ------ | --------------------------------------------------- |
| `1`    | Consent given                                       |
| `0`    | Consent denied, including age-restricted categories |
| `-1`   | Invalid or unknown category ID                      |

**Age Gate Impact**

Returns `0` for any purpose linked to a restricted age range.

### `updateConsentValueForCategory`

Updates the consent value for a purpose programmatically.

```csharp
CMPSDK.sharedInstance.updateConsentValueForCategory("C0005", true);
```

With Age-Based Consent-supported SDKs:

* The SDK prevents consent from being enabled for age-restricted purposes.
* Any attempt to set consent to `true` is silently ignored.

Without Age-Based Consent-supported SDKs, including older SDKs:

* The update may succeed locally.
* The CMP API overrides the value to `0` (denied) during the next sync.

## Behavior changes

### Preference Center

* **Restricted users:** If a user's age range overlaps with a configured restricted age group, the consent toggle for associated categories is hidden or disabled and consent is automatically set to `0` (denied). The user cannot provide consent for those categories.
* **Non-restricted users:** If the user's age range does not overlap with any restricted age group, all consent toggles remain visible and interactive. Standard consent behavior applies.

### Age range overlap logic

A user is considered restricted if their age range shares any intersection with a restricted age group. Partial overlap also results in restriction.

**Logic**

```csharp
restricted = (user.LowerBound <= group.UpperBound) &&
             (user.UpperBound >= group.LowerBound)
```

| User age range | Result         | Reason                                  |
| -------------- | -------------- | --------------------------------------- |
| `[0, 18]`      | Restricted     | Possible overlap, such as age 14        |
| `[14, 16]`     | Restricted     | Overlaps with 14–15                     |
| `[10, 12]`     | Restricted     | Fully within restricted range           |
| `[18, 25]`     | Not restricted | No overlap                              |
| `[18, null]`   | Not restricted | Open-ended 18+ range does not intersect |

## Cross-device behavior (Authenticated Consent)

For environments with Cross-Device Consent or Authenticated Consent enabled, age-based restrictions are enforced server-side and persist across devices.

**How It Works**

Once a user's age range is logged for a profile from any device:

* The CMP API server stores the age range.
* All subsequent consent responses for that profile enforce the same restrictions.
* Enforcement applies across devices, sessions, and SDK versions.

## End-to-end flow

1. **Admin configuration:** An admin configures restricted age groups in the OneTrust Admin UI and links purposes or purpose groups to them.
2. **Provider registration:** The app implements `ICustomConfigurator` and assigns `CMPSDK.sharedInstance.CustomConfigurator`.
3. **SDK initialization:** The app calls `StartSDK`.
4. **Age range request:** The SDK internally calls `GetProfileAgeRange` to request the user's age range.
5. **If an age range is provided:**
   * The SDK stores it locally.
   * The SDK logs the `AGEGATE_RANGE` interaction to the CMP API server.
   * The server stores the age range for the profile and enforces restrictions in subsequent responses.
   * The SDK prevents restricted purposes from being enabled in the Preference Center and public APIs.
6. **If&#x20;**`null`**&#x20;is returned (age unknown):**
   * The SDK does not send an age range to the server.
   * The server checks if an age range already exists for this profile from a prior interaction or another device.
   * If found, the server still enforces age-based restrictions.
   * If no age range exists anywhere, no restrictions are applied.
7. **When the user's age changes:** Re-initialize the SDK to re-invoke the provider and refresh restrictions.

## Troubleshooting

If restricted toggles are still visible or consent can still be enabled, verify that:

* `CMPSDK.sharedInstance.CustomConfigurator` is assigned before `StartSDK`.
* `GetProfileAgeRange` returns a valid `ProfileAgeRange`.
* The restricted age group is configured in the OneTrust Admin UI.
* The relevant purpose is linked to that restricted age group.

## Migration guide

### From legacy Age Gate

If you are migrating from the legacy Age Gate prompt to Age-Based Consent:

1. Implement `ICustomConfigurator` with your user's age data.
2. Assign `CMPSDK.sharedInstance.CustomConfigurator` before calling `StartSDK`.
3. The SDK automatically handles consent restrictions based on the provided age range.

```csharp
// Before (Legacy):
await CMPSDK.sharedInstance.StartSDK(sdkParams);

// After (Age-Based Consent):
CMPSDK.sharedInstance.CustomConfigurator = this;
await CMPSDK.sharedInstance.StartSDK(sdkParams);

public void GetProfileAgeRange(string profileId, Action<ProfileAgeRange> completion)
{
    int userAge = GetUserAge(profileId);
    completion(new ProfileAgeRange(userAge, userAge));
}
```

# Sibling pages

* [IAB CCPA US Privacy String](https://developer.onetrust.com/onetrust/docs/iab-ccpa-us-privacy-string-maui-new.md)
* [IAB Transparency and Consent Framework (TCF)](https://developer.onetrust.com/onetrust/docs/iab-tcf-22-maui-new.md)
* [IAB Global Privacy Protocol](https://developer.onetrust.com/onetrust/docs/iab-global-privacy-protocol-maui-new.md)
* [API Reference](https://developer.onetrust.com/onetrust/docs/api-reference-maui-new.md)