Attribute matching

The following guide offers a high-level overview of how an ID.me integration for attribute matching functions.

Design overview

1

Policy setup

a. ID.me provides a public key for the encryption of the JSON Web Encryption (JWE) token

b. Customer provides ID.me with the certificate used for signing which enables ID.me to validate the signature

The ID.me policy will be configured to:

  • Require a JWE token on OAuth requests
  • Accept certain attributes in the JWE
  • Match on certain attributes in specific ways as defined by the customer
2

ID.me must receive a JWE in the request URL parameter within the initial ./oauth/authorize call”

If the JWE is invalid (e.g. missing, encryption, signature, payload), the user will be returned to the customer and presented with an error message

3The user will sign in and verify their properties
4ID.me will compare the attributes in the JWE with the user properties and store the matching results
5

The user will be asked to consent to providing the customer with their:

  • Name
  • Date of birth
  • Other data (depending on configuration)
6

ID.me will issue an access_token

If there is a mismatch, ID.me will prevent the user from continuing the flow

7

Customer will use the access_token to request attributes of the user

Customers will not receive a payload if there is a mismatch due to ID.me preventing the user from completing the flow

JWE

Customers send matching attributes as a JWE object in the initial OAuth request.

Payload

Attribute keys in the payload are configured during integration setup. The payload contains the attribute keys and values (in JSON) that will be used for matching.

Key / value pair example
1{
2 “first_name”: “John”,
3 “last_name”: “Doe”
4}
Good match example
1 {
2 "handle": "attributes_match",
3 "name": "Verified attributes match requested attributes",
4 "value": true
5 }

Creation

The JWE will be created by:

1Signing the payload to create a JWS
2Encrypting the JWS using the public key provided by ID.me

When decrypted, the JWE will contain a JWS with a valid signature that can be verified by the public certificate provided by the customer.

JWE
eyJraWQiOiJBYWNSMjZ2RkdWeVFlajFzU3NMcTFCLTVBQTBSa1NfN2xqUGZ0ZURoWlNFIiwiY3R5IjoiSldUIiwiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.s2dgRUICmkTnqSONQxJjXRbUnPxtXEDl_VVI0iv-Kxn2L9R3kir0Prk8tAmwDkHv-M-3gTq4yEv1VRQWsfbiWn9EOjO6C24buLMEyJ1Jx2lUu-KTdMxRI2VbuuyruDYKI7eAp9Xld2icrzGmeHMNjiZ1_jnK5GGe1WfVDWlMh68bNQcN6IT0md6TJWUoP5xxDu_C0SJd_XinSm-WJ2MUPiM_Lcub53o8rJpudEhad7MQXqO16-8M-2mInLiblAs_M17uFYZYp26jq51m0co_LZS9sS0Pe31yzpBq3G51KwGevjN19AuyygXHVY352QzrT0L6__t8o1dhXAa9N1AWCg.H0X_ib45DZbV9iWBJZGrKg.bTXAYJwynvqpFGuckhd5z7VpPsmNJoL9PMC1lY0EVFLaoy3beHVRMm2l5_oMfwzhiR4OocCJfOIwNwoKSP96fIXbHRLOX9lfusMKT7wZGvOr0eLtkr1dULuoDk-P6_9joDZNfn1DhN_nTsQ9k4DVum2r_lPtWnl_Txie1yip-NMLfFTvGP_6ukj4b0U-qMK3NNb2vPwaPPL-ztrcZP2tEQjn8XIoahp0g2Lx7jp4DcvwHxJOA9XGKaAORTd50Wb_YyAPluEUo_d1arigA0_H3th5JHx1QEIvUm1UNSahxOGDc0qSdvOhFNihN7LPzKrMVePyjufb4q202Xu5jJV5BL9X0djPausnRO0jmw5waM47mW1Ohlg9KbNmjHDGwwdSXP8EJD0M3riRRocdEPL-E56mvlRrcaBoVD-AzamU7CbDdMjDxOHjBebnM0da84JtP5L4v-javZkzeIWfdHXxRasB34ijtKIG7nVG1Bv-frbrhwWOV-yiS0dHEJKAZ1jjQXVTnCqP7GFFxccwyvzW9r-jvK_u4kwVz-SdiBedi3ICy8RCPy2clOcgx6aUiRq6Z0B45Gqemoibr_Vo22w-IkvUaXeFkDYtiKHsFRdAWeMFtN0JgYtIjPJ2JEdEj8_00LXfYxvmKxrO-Gr_xSGW9JAa4joZY_kHyJQd0RIkpF-Jx2di35wdZcrk0dFPvCKENbbbgRkMDLHLx84PE1eSqw.vQ7lscwflpLwcaPeX-OiD9nVEyNxHxJKJtC4WHm3gdo
Decrypted payload (JWS)
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IkpPYkJGakozSjNOejdkMHlpWGhLbXotMThyMGlWeXJtUnhDc0ZRTWhWU1UifQ.eyJmbmFtZSI6IlRlc3RGaXJzdCIsImxuYW1lIjoiVGVzdExhc3QiLCJiaXJ0aF9kYXRlIjoiMjAwMC0wMS0wMSJ9.4eu1GukTXbpOJ1lpwSyzZ_SFQwHi4e5xV_S5Hpzoju1Cc81_VxkjNF1eAC5Z7c-8o3qslDou5h36up2iBIrgJPU9hPPMMalReTqRJYDSgSw9EItCxl8dN0OCfHHE61zXz5QDDit-6syB1lb9qsB5bZU-H8_EB--bxbQom9HjdcVdrOiBbFy_IcH_5leGZy8aVoh5Cz9xITewsFcSJuKN-DZ0WQuGswMmimi0jGQxeXiDLqegGFMNjQKeGny6bGX7kzJ1WM8gvIx43Ugr0Nn8Bup7O4SIFR8PyeucADQYXQga1cHOGMyLYZTSv4V2VPRf25ManTonqMyUpWKGpJ0xKL0

The above contains the following JSON payload:

1{"fname"=>"TestFirst", "lname"=>"TestLast", "birth_date"=>"2000-01-01"}

Decoding the JWE/JWS using code or another tool will show the parameters used in this example.

Attribute matching logic

ID.me uses two well-established algorithms which are used by applications to compare two strings for matching purposes.

Jaro-Winkler

The Jaro-Winkler distance algorithm to compare text values, such as names, and determine whether they are likely a match.

How it works

  • Compares two strings and measures similarity based on matching characters and order

  • Gives more weight to characters at the start of the string (useful for names where typos or variations occur)

  • Returns a score between 0 (no similarity) and 1 (exact match)

Our matching rules

  • Score > 0.8 → treated as a match

  • Score < 0.8 → treated as a mismatch

Match scores can be configured per policy and attribute, so if you want to set a threshold higher or lower than the standard configuration, that can be supported

Example
Bob Adam <-> Robert Adams
  • Jaro-Winkler score: 0.819 (81.9%)

  • Result: Match

NYSIIS

The NYSIIS algorithm (New York State Identification and Intelligence System) to match names that sound alike but may be spelled differently.

How it works

  • Converts a name into a phonetic code

  • Applies a set of transformation rules to letters and letter groups

  • Produces a simplified, standardized representation of the name’s pronunciation

Why it’s useful

  • Matches names that have multiple valid spellings

  • Handles variations due to spelling conventions or regional accents

  • Makes it easier to compare names based on sound instead of spelling

Example
"Ashley" <-> "Ashleigh"
"Phoebe" <-> "Febe"
  • Both pairs are reduced to the same phonetic code

  • Result: Match