Skip to main content

UAE PASS

note

To add UAE PASS as a social sign-in provider, you need a UAE PASS integration account. Visit UAE PASS to register your application. For testing, use the staging credentials sandbox_stage / sandbox_stage.

Follow these steps to add UAE PASS as a social sign-in provider to your project using the Ory CLI or self-hosted Kratos:

  1. Create a Jsonnet code snippet to map the desired claims to the Ory Identity schema.

    UAE PASS doesn't return an id_token. Ory sends requests to UAE PASS's userinfo API and adds the user info to std.extVar('claims'). All UAE PASS-specific attributes are available via claims.rawClaims.

    Basic mapping (email and name):

    local claims = std.extVar('claims');
    {
    identity: {
    traits: {
    [if 'email' in claims then 'email' else null]: claims.email,
    name: {
    first: claims.given_name,
    last: claims.family_name,
    },
    },
    },
    }

    Full mapping (with UAE PASS metadata and verified email):

    local claims = std.extVar('claims');
    local hasRaw = 'rawClaims' in claims;
    local raw = if hasRaw then claims.rawClaims else {};
    local titleCase(s) =
    local words = std.split(s, ' ');
    std.join(' ', [
    if std.length(w) == 0 then ''
    else std.asciiUpper(w[0]) + std.asciiLower(w[1:])
    for w in words
    ]);
    {
    identity: {
    traits: {
    [if 'email' in claims then 'email' else null]: claims.email,
    [if 'mobile' in raw then 'phone'
    else if 'phone_number' in claims then 'phone'
    else null]:
    if 'mobile' in raw then raw.mobile
    else if 'phone_number' in claims then claims.phone_number,
    name: {
    first: titleCase(claims.given_name),
    last: titleCase(claims.family_name),
    },
    },
    verified_addresses: [
    if 'email' in claims then {
    via: 'email',
    value: claims.email,
    verified: true,
    },
    ],
    [if hasRaw then 'metadata_public' else null]: {
    uaepass: {
    [if 'uuid' in raw then 'uuid' else null]: raw.uuid,
    [if 'userType' in raw then 'user_type' else null]: raw.userType,
    [if 'mobile' in raw then 'mobile' else null]: raw.mobile,
    [if 'email' in raw then 'email' else null]: raw.email,
    [if 'firstnameEN' in raw then 'firstname_en' else null]: raw.firstnameEN,
    [if 'lastnameEN' in raw then 'lastname_en' else null]: raw.lastnameEN,
    [if 'firstnameAR' in raw then 'firstname_ar' else null]: raw.firstnameAR,
    [if 'lastnameAR' in raw then 'lastname_ar' else null]: raw.lastnameAR,
    [if 'fullnameEN' in raw then 'fullname_en' else null]: raw.fullnameEN,
    [if 'fullnameAR' in raw then 'fullname_ar' else null]: raw.fullnameAR,
    [if 'nationalityEN' in raw then 'nationality_en' else null]: raw.nationalityEN,
    [if 'nationalityAR' in raw then 'nationality_ar' else null]: raw.nationalityAR,
    [if 'gender' in raw then 'gender' else null]: raw.gender,
    [if 'idn' in raw then 'emirates_id' else null]: raw.idn,
    [if 'idType' in raw then 'id_type' else null]: raw.idType,
    [if 'spuuid' in raw then 'smartpass_uuid' else null]: raw.spuuid,
    [if 'titleEN' in raw then 'title_en' else null]: raw.titleEN,
    [if 'titleAR' in raw then 'title_ar' else null]: raw.titleAR,
    [if 'profileType' in raw then 'profile_type' else null]: raw.profileType,
    [if 'unifiedId' in raw then 'unified_id' else null]: raw.unifiedId,
    },
    },
    },
    }
    info

    UAE PASS returns different attributes depending on the user's account level (SOP):

    LevelNameAvailable Attributes
    SOP1Basicuuid, email, mobile, firstnameEN, lastnameEN, userType
    SOP2AdvancedAll SOP1 + full names (EN/AR), nationality, gender, idn, idType
    SOP3QualifiedAll SOP2 + titleEN/AR, profileType, unifiedId

    All raw attributes are accessible via claims.rawClaims.* in the Jsonnet mapper. Always guard access to rawClaims with 'rawClaims' in claims to avoid runtime errors if the field is not populated.

    UAE PASS returns names in uppercase (e.g., "MOHAMMED ALI"). Use a titleCase helper in your mapper to normalize names before storing them in traits.

danger

Don't save secrets such as API keys, credentials, or personal data directly in Jsonnet code snippets. Jsonnet code snippets used for data mapping aren't stored in an encrypted format in Ory Network.

  1. Encode the Jsonnet snippet with Base64 or host it under an URL accessible to Ory Network.

    cat your-data-mapping.jsonnet | base64
  2. Download the Ory Identities config from your project and save it to a file:

    ## List all available workspaces
    ory list workspaces

    ## List all available projects
    ory list projects --workspace <workspace-id>

    ## Get config
    ory get identity-config --project <project-id> --workspace <workspace-id> --format yaml > identity-config.yaml
  3. Add the social sign-in provider configuration to the downloaded config. Add the Jsonnet snippet with mappings as a Base64 string or provide an URL to the file.

    Staging configuration:

    selfservice:
    methods:
    oidc:
    config:
    providers:
    - id: uaepass # this is `<provider-id>` in the Authorization callback URL. DO NOT CHANGE IT ONCE SET!
    provider: uaepass
    client_id: sandbox_stage
    client_secret: sandbox_stage
    auth_url: https://stg-id.uaepass.ae/idshub/authorize
    token_url: https://stg-id.uaepass.ae/idshub/token
    issuer_url: https://stg-id.uaepass.ae/idshub
    mapper_url: "base64://{YOUR_BASE64_ENCODED_JSONNET_HERE}"
    # Alternatively, use an URL:
    # mapper_url: https://storage.googleapis.com/example-example-prd/example-file
    scope:
    - urn:uae:digitalid:profile:general
    enabled: true

    Production configuration:

    selfservice:
    methods:
    oidc:
    config:
    providers:
    - id: uaepass
    provider: uaepass
    client_id: .... # Replace with your UAE PASS client ID
    client_secret: .... # Replace with your UAE PASS client secret
    auth_url: https://id.uaepass.ae/idshub/authorize
    token_url: https://id.uaepass.ae/idshub/token
    issuer_url: https://id.uaepass.ae/idshub
    mapper_url: "base64://{YOUR_BASE64_ENCODED_JSONNET_HERE}"
    scope:
    - urn:uae:digitalid:profile:general
    enabled: true
    tip

    For visitor integration, add extra scopes to retrieve profileType and unifiedId:

    scope:
    - urn:uae:digitalid:profile:general
    - urn:uae:digitalid:profile:general:profileType
    - urn:uae:digitalid:profile:general:unifiedId
  4. Update the Ory Identities configuration using the file you worked with:

    ory update identity-config --project <project-id> --workspace <workspace-id> --file identity-config.yaml

Configuration reference

The uaepass provider handles the following UAE PASS requirements automatically:

  • No OIDC discovery — UAE PASS doesn't expose .well-known/openid-configuration. Endpoints are configured directly.
  • No openid scope — UAE PASS doesn't support the standard openid scope. Use urn:uae:digitalid:profile:general.
  • acr_values injection — The required urn:safelayer:tws:policies:authentication:level:low parameter is added automatically.
  • client_secret_basic auth — The token endpoint uses HTTP Basic authentication as required by UAE PASS.
  • Userinfo-based claims — UAE PASS doesn't return ID tokens. Claims are fetched from the userinfo endpoint.

Endpoints

EnvironmentAuthorizeTokenUserinfoLogout
Staginghttps://stg-id.uaepass.ae/idshub/authorizehttps://stg-id.uaepass.ae/idshub/tokenhttps://stg-id.uaepass.ae/idshub/userinfohttps://stg-id.uaepass.ae/idshub/logout
Productionhttps://id.uaepass.ae/idshub/authorizehttps://id.uaepass.ae/idshub/tokenhttps://id.uaepass.ae/idshub/userinfohttps://id.uaepass.ae/idshub/logout

Configuration fields

FieldRequiredDescription
providerYesMust be uaepass
client_idYesYour UAE PASS client ID (use sandbox_stage for staging)
client_secretYesYour UAE PASS client secret (use sandbox_stage for staging)
auth_urlNoAuthorization endpoint. Defaults to staging if omitted
token_urlNoToken endpoint. Defaults to staging if omitted
issuer_urlNoBase URL for deriving the userinfo endpoint ({issuer_url}/userinfo). Defaults to staging if omitted
scopeYesMust include urn:uae:digitalid:profile:general
mapper_urlYesPath or Base64-encoded Jsonnet mapper

Available claims

UAE PASS doesn't return an id_token. Ory sends requests to UAE PASS's userinfo API and adds the user info to std.extVar('claims').

Standard claims

These claims are mapped automatically by the provider and available directly on the claims object:

ClaimFieldDescription
claims.subSubjectUUID (preferred) or sub identifier
claims.given_nameGiven NamefirstnameEN from UAE PASS
claims.family_nameFamily NamelastnameEN from UAE PASS
claims.nameFull NamefullnameEN from UAE PASS
claims.emailEmailVerified email
claims.phone_numberPhoneMobile number
claims.genderGenderGender

UAE PASS-specific claims (rawClaims)

These are accessible via claims.rawClaims in the Jsonnet mapper. Availability depends on the user's account level (SOP):

ClaimSOP LevelDescription
claims.rawClaims.uuidAllUAE PASS unique user identifier
claims.rawClaims.userTypeAllAccount type: SOP1, SOP2, or SOP3
claims.rawClaims.mobileAllVerified phone number
claims.rawClaims.emailAllVerified email
claims.rawClaims.firstnameENAllGiven name (English)
claims.rawClaims.lastnameENAllFamily name (English)
claims.rawClaims.firstnameARSOP2+Given name (Arabic)
claims.rawClaims.lastnameARSOP2+Family name (Arabic)
claims.rawClaims.fullnameENSOP2+Full name (English)
claims.rawClaims.fullnameARSOP2+Full name (Arabic)
claims.rawClaims.nationalityENSOP2+Nationality (English)
claims.rawClaims.nationalityARSOP2+Nationality (Arabic)
claims.rawClaims.genderSOP2+Gender
claims.rawClaims.idnSOP2+Emirates ID number (citizens/residents only)
claims.rawClaims.idTypeSOP2+ID type
claims.rawClaims.spuuidSOP2+SmartPass UUID (SmartPass-verified accounts only)
claims.rawClaims.titleENSOP2+Title (English)
claims.rawClaims.titleARSOP2+Title (Arabic)
claims.rawClaims.profileTypeSOP3 (Visitors)1 (Citizen/Resident) or 2 (Visitor)
claims.rawClaims.unifiedIdSOP3 (Visitors)Unified user ID
caution

The idn (Emirates ID) attribute is not returned for Visitor profiles. It is only available for Citizens and Residents with SOP2 or SOP3 accounts.

User account types (SOP levels)

UAE PASS supports three account levels, known as Standard Operating Procedures (SOPs). The account level determines which attributes are returned in the userinfo response.

LevelNameVerification MethodAvailable Attributes
SOP1BasicEmail + Mobile OTP only. Account is unverified.uuid, email, mobile, firstnameEN, lastnameEN, userType
SOP2AdvancedEmirates ID + PIN, or migrated from SmartPass/Dubai ID. Account is verified.All SOP1 + fullnameEN/AR, firstnameAR, lastnameAR, nationalityEN/AR, gender, idn, idType, spuuid, titleEN/AR
SOP3QualifiedEmirates ID + Biometrics (face or fingerprint). Account is verified.All SOP2 + profileType, unifiedId
info

SOP2 and SOP3 accounts have access to digital signature capabilities. SOP1 accounts only support authentication — they cannot use digital signature or data/document sharing features.

Visitor accounts

Visitors (non-Citizens/non-Residents) have a different attribute set. Visitors only support SOP1 and SOP3 levels. To retrieve visitor-specific attributes, add extra scopes to your configuration:

scope:
- urn:uae:digitalid:profile:general
- urn:uae:digitalid:profile:general:profileType
- urn:uae:digitalid:profile:general:unifiedId

You can distinguish visitor profiles from citizen/resident profiles using the profileType claim:

  • profileType = 1 → Citizen or Resident
  • profileType = 2 → Visitor

Build and deploy

The uaepass provider requires a custom build of Ory Kratos from the fork with UAE PASS support. This is necessary because the provider is not yet part of the upstream Ory Kratos distribution.

# Clone the fork
git clone https://github.com/baytii/kratos.git
cd kratos

# Build the custom Docker image
docker build -t your-registry/kratos:latest-uaepass .

# Push to your registry
docker push your-registry/kratos:latest-uaepass

Then reference this image in your docker-compose.yml or Kubernetes deployment:

# docker-compose.yml
services:
kratos:
image: your-registry/kratos:latest-uaepass
# ... rest of your config

Staging testing

Follow these steps to test your UAE PASS integration in the staging environment:

  1. Create a staging account: Set up a UAE PASS staging account at docs.uaepass.ae. Staging accounts can be created from any location — there are no geographic restrictions.
  2. Use staging credentials: client_id: sandbox_stage, client_secret: sandbox_stage.
  3. Upgrade your account (optional): The staging account starts as SOP1 (basic). To test SOP2/SOP3 attributes, upgrade via the self-care portal.
  4. Run a POC: Follow the POC guide to verify the authentication flow end-to-end.
note

UAE PASS APIs are publicly accessible — both staging and production endpoints work from overseas. There are currently no charges for integrating with UAE PASS.

Troubleshooting

When you add a social sign-in provider, you can encounter common problems such as:

  • Redirect URI mismatch
  • Redirect loops during registration
  • Domain verification issues

To troubleshoot those issues, read Social sign-in troubleshooting.

UAE PASS-specific issues

  • No attributes returned: Check the user's SOP level. SOP1 accounts return only basic attributes (uuid, email, mobile, firstnameEN, lastnameEN). Upgrade the staging account to SOP3 for full attribute testing.
  • Missing idn for visitors: The Emirates ID (idn) attribute is not returned for Visitor profiles. This is expected behavior.
  • Logout redirect issues: UAE PASS only accepts a state parameter in the logout URL. To pass additional parameters, Base64-encode them into the state parameter:
    https://stg-id.uaepass.ae/idshub/logout?redirect_uri=https://your-app.com/logout&state={base64_encoded_query_string}

Credits

This provider was developed by GBYTE TECH and is available under the Apache 2.0 license.