OpenID Connect
OpenID Connect (OIDC) is an identity layer on top of OAuth 2.0. It enables applications to verify the identity of users and obtain basic profile information in an interoperable way.
Process
- Redirect user to MyLogin authorization endpoint (see OAuth Authentication for the URL, parameters, and examples)
- Include the
openidscope in your authorization request (and set it as the default scope in your developer area — see below). Required per OIDC Core §3.1.2.1 - Optionally include a
noncein your authorization request to bind theid_tokento that request – see below. Recommended per OIDC Core §3.1.2.1 - User authenticates and is redirected back with an auth code
- Exchange the code for tokens — POST to the token endpoint with
client_secret_basicauth (HTTP Basic with yourclient_idandclient_secret; see OAuth Token for parameters and examples) - When
openidscope was requested (via request or default), the Token Response (§3.1.3) includes anid_tokenJWT in addition toaccess_tokenandrefresh_token
The openid Scope
To receive an id_token in the token response, the openid scope must be included in the authorization request OIDC Core §3.1.2.1. Without it, the token response contains only access_token and refresh_token.
You can include openid in your scope parameter when redirecting users to the authorization endpoint, as per the standard. We also require you to set it as the default scope in your developer area (Manage developer settings → Credentials → Scopes). That way we know to include the id_token when users launch your app from their dashboards (IdP-initiated flows), where the client does not specify scopes.
The nonce Parameter
The nonce associates your session with the id_token and mitigates replay attacks OIDC Core §3.1.2.1. It is optional in the authorization code flow, but recommended. Send it as a URL parameter on the authorization endpoint.
Generate a fresh value per authorization request, store it against the user's session, and include it as the nonce URL parameter when redirecting to the authorization endpoint. It is treated as a case-sensitive string.
Use a cryptographically secure random value. Sufficient entropy must be present so that the value cannot be guessed OIDC Core §3.1.2.1. This is your responsibility as the client: we pass the value through unmodified and cannot verify how it was generated. At least 32 bytes of randomness is recommended; do not use timestamps, counters, or user identifiers. For example, bin2hex(random_bytes(32)) in PHP or crypto.randomBytes(32).toString('hex') in Node.
Binding the value to the browser session strengthens this further: store a cryptographically random value in an HttpOnly session cookie (or local storage for browser-based clients) and send a cryptographic hash of it as the nonce, then compare the returned claim against the hash of the stored value OIDC Core §15.5.2.
Percent-encode the value when adding it to the query string, as with every other authorization request parameter OIDC Core §13.1. We compare and return the decoded value, so a hex or base64url nonce needs no special handling.
We accept up to 1024 characters, which is well beyond what a securely generated value requires.
We return it unmodified as the nonce claim in the ID token. You must verify it matches the value you sent, and reject the token if it does not OIDC Core §3.1.3.7. If you did not send a nonce, the claim is omitted.
OIDC flow (authorization code)
GET /.well-known/openid-configuration
Discovery §3 Provider Metadata — returns provider metadata including issuer, endpoints, and supported features. The base URL for endpoints such as /.well-known/openid-configuration is the issuer from this Discovery response.
| Field | Description |
|---|---|
issuer |
Identifier for the authorization server. Use this to validate that tokens were issued by MyLogin; it must match the |
authorization_endpoint |
URL for the OAuth authorization endpoint |
token_endpoint |
URL for exchanging auth codes for tokens |
jwks_uri |
|
scopes_supported |
Supported OAuth scopes (includes |
response_types_supported |
Supported response types ( |
subject_types_supported |
Subject identifier type ( |
id_token_signing_alg_values_supported |
ID token signing algorithm ( |
token_endpoint_auth_methods_supported |
Client auth method ( |
claims_supported |
Claims that may be included in the ID token, including MyLogin-specific ones |
service_documentation |
Link to developer documentation |
Example response
{
"issuer": "https://app.mylogin.com",
"authorization_endpoint": "https://app.mylogin.com/oauth/authorize",
"token_endpoint": "https://app.mylogin.com/oauth/token",
"jwks_uri": "https://app.mylogin.com/.well-known/jwks.json",
"scopes_supported": ["openid"],
"response_types_supported": ["code", "id_token"],
"subject_types_supported": ["public"],
"id_token_signing_alg_values_supported": ["RS256"],
"token_endpoint_auth_methods_supported": ["client_secret_basic"],
"claims_supported": ["email", "given_name", "family_name", "nonce", "https://app.mylogin.com/claims/google_email", "https://app.mylogin.com/claims/microsoft_email", "https://app.mylogin.com/claims/wonde_id"],
"service_documentation": "https://app.mylogin.com/developer/docs/oidc"
}
GET /.well-known/jwks.json
RFC 7517 JWK — returns the JSON Web Key Set for validating ID token signatures (RS256). Returns a JSON object with a keys array; each key object has the following fields. Use the kid in the JWT header to select the correct key.
| Field | Description |
|---|---|
kid |
Key ID — unique identifier for the key. Match this with the |
kty |
Key type — family of cryptographic algorithms used with the key ( |
use |
Public key use — how the key is intended to be used ( |
alg |
Algorithm — the cryptographic algorithm used with the key ( |
x5c |
X.509 certificate chain — array of base64-encoded certificates. The first entry is the certificate used for ID token verification. |
n |
RSA public key modulus — base64url-encoded modulus of the RSA public key. |
e |
RSA public key exponent — base64url-encoded exponent of the RSA public key. |
x5t |
X.509 certificate SHA-1 thumbprint — base64url-encoded SHA-1 hash of the DER-encoded certificate. |
x5t#S256 |
X.509 certificate SHA-256 thumbprint — base64url-encoded SHA-256 hash of the DER-encoded certificate (RFC 7638). |
Example response
{
"keys": [
{
"kid": "01kkh1der1aw0en5ysyzcmvy9m",
"kty": "RSA",
"use": "sig",
"alg": "RS256",
"n": "uzWHNM5f-amCjQztc5QTfJfzCC5J4nuW-L_aOxZ4f8J3FrewM2c_dufrnmedsApb0By7WhaHlcqCh_ScAPyJhzkPYLae7bTVro3hok0zDITR8F6SJGL42JAEUk-ILkPI-DONM0-3vzk6Kvfe548tu4czCuqU8BGVOlnp6IqBHhAswNMM78pos_2z0CjPM4tbeXqSTTbNkXRboxjU29vSopcT51koWOgiTf3C7nJUoMWZHZI5HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTzTTqo1SCSH2pooJl9O8at6kkRYsrZWwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG_BwQ",
"e": "AQAB",
"x5c": ["MIIC/zCCAeegAwIBAgIUXz368YFre05YO+310ce1grHV5IkwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0yNjAzMTIxMDAyNDJaFw0yNzAzMTIxMDAyNDJaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7NYc0zl/5qYKNDO1zlBN8l/MILknie5b4v9o7Fnh/wncWt7AzZz925+ueZ52wClvQHLtaFoeVyoKH9JwA/ImHOQ9gtp7ttNWujeGiTTMMhNHwXpIkYvjYkARST4guQ8j4M40zT7e/OToq997njy27hzMK6pTwEZU6WenoioEeECzA0wzvymiz/bPQKM8zi1t5epJNNs2RdFujGNTb29KilxPnWShY6CJN/cLuclSgxZkdkjkeqciE8Ab3K/wcCA2ToIyTYJp1UcOjgjGPFPNNOqjVIJIfamigmX07xq3qSRFiytlbCwqU4UTYtRx7s5udexiKFK0FQOh4FCUYb8HBAgMBAAGjUzBRMB0GA1UdDgQWBBSo06veDdS5Z0eovjLCqDoMmVEQVTAfBgNVHSMEGDAWgBSo06veDdS5Z0eovjLCqDoMmVEQVTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCOPd5pYhXytFMc3t7tlarDDg4GMKd0/d72LiRtjlwhCeRnur0lU3GpfgPV94dQvYBtNTp3e1q8QwGM2V0m9YEoF/p7LZhtX6MWkMgIriAHpn3aM580Armx9BktLBIGYMtedScST0IF+/UYM3gerPA/2NLn3tM+FvekQDopUZ1K33kFjG+V5EbT27JyS2ne/J6HFidIebIHZifuniQKGEwJFEh/6V/j67sgJz9otUUILVaMhoP2015dqyz13NzXIuRBlCSHvWKRzi1gki/JpmTHtbHc59t/ypmN+U90IeaAhmu7196faSGSKnxCFpm/31LV1C3nCazM6GG8Ew7i5gHH"],
"x5t": "K89yXf4wC_3kQ0P-rjfDHCnCFJE",
"x5t#S256": "b5FO_fOn5W6ilziJs9K42lRqeTMiN4_2P6rsqP36414"
}
]
}
ID Token Contents
The ID token is a JWT with three parts: header, payload (claims), and signature. Verify the signature OIDC Core §3.1.3.7 using the public key from the JWKS (jwks_uri from Discovery), selecting the key by the kid in the header.
JWT header RFC 7515 §4:
| Field | Description |
|---|---|
alg |
Signing algorithm — always |
typ |
Type — |
kid |
Key ID — identifies which key in the JWKS was used to sign the token. Use this to select the correct public key for verification. |
Payload (claims) — We return these claims, which are either Required (OIDC Core §2), Standard (OIDC Core §5.1), or Additional (OIDC Core §5.1.2):
| Claim | Description | Availability |
|---|---|---|
iss |
Issuer — |
Always returned |
sub |
Subject — the user's MyLogin ID (e.g. |
Always returned |
aud |
Audience — your app's |
Always returned |
exp |
Expiration — Unix timestamp (seconds since 1970-01-01 UTC). Current time must be before exp — reject if expired OIDC Core §3.1.3.7 |
Always returned |
iat |
Issued at — Unix timestamp (seconds since 1970-01-01 UTC). Reject if in the future (not started yet); may reject if issued too long ago OIDC Core §3.1.3.7 |
Always returned |
nonce |
The |
Only when you sent a |
email |
User's email address OIDC Core §5.1 |
When available — omitted (not null) if not set or not provided by the organisation |
given_name |
User's first name OIDC Core §5.1 |
Always returned |
family_name |
User's last name OIDC Core §5.1 |
Always returned |
type |
User type (e.g. |
Always returned |
https://app.mylogin.com/claims/google_email |
Email address from the user's matched Google account — MyLogin-specific OIDC Core §5.1.2 |
Only when the user has been matched to a Google account — omitted (not null) otherwise |
https://app.mylogin.com/claims/microsoft_email |
Email address from the user's matched Microsoft account — MyLogin-specific OIDC Core §5.1.2 |
Only when the user has been matched to a Microsoft account — omitted (not null) otherwise |
https://app.mylogin.com/claims/wonde_id |
Wonde identifier for this person, from the user's matched Wonde account. Maps to the Wonde API's student/employee endpoint |
Only when the organisation has matched this person's MyLogin user to their Wonde account; omitted (not null) otherwise |
Signature — The token is signed with RS256. Verify OIDC Core §3.1.3.7 using the public key from the JWKS; the kid in the header indicates which key was used.
Example: raw ID token (header.payload.signature)
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjAxa2toMWRlcjFhdzBlbjV5c3l6Y212eTltIn0.eyJpc3MiOiJodHRwczovL2FwcC5teWxvZ2luLmNvbSIsInN1YiI6IkExNDE0MTQxNDE0IiwiYXVkIjoidGhlLWZlbGxvd3NoaXAiLCJleHAiOjE3MzQ1Njc4OTAsImlhdCI6MTczNDUzNDI5MCwiZW1haWwiOiJmcm9kb0BiYWdlbmQuc2hpcmUiLCJnaXZlbl9uYW1lIjoiRnJvZG8iLCJmYW1pbHlfbmFtZSI6IkJhZ2dpbnMiLCJ0eXBlIjoic3R1ZGVudCJ9.KzsQnZtVQAb1thAN14xsqX_uYehYwsK67KFsZkdZzopha78anhgSmdp3xWa7qTXM9ZfXPM_Y0QnlK0uW6idDh12awy_3-bDmchsZW0_7MZuegPOqQrTrvRhYdx7vjOYJmyeenZzsi89-CCvjUH6uk_Sz-9m0ggUAetlzmw0pANqA8Ysl9sFuzY7GGdNHE7mDTC5ebjf4w9atRcd8glEhrU46h_9YlgidDAy-5mZ8uk4HsJWnWvMzChYA6xaqbu7kmufzw1xh4AC9D3IByIQiMrTdfeY_Ni2Gru6b5-kXIJn4kcsa7fbeHG_Gq2eO3R4SFnY6YAmuN4Gfr08C6Ncy-Q
Example: decoding the raw token (PHP)
// JWT = base64url(header).base64url(payload).base64url(signature) // Decode header and payload (base64url → base64, then decode)$parts = explode('.', $rawToken);
$base64urlDecode = function (string $str): string { $decoded = base64_decode(strtr($str, '-_', '+/')); return $decoded !== false ? $decoded : ''; };
$header = json_decode($base64urlDecode($parts[0])); $payload = json_decode($base64urlDecode($parts[1]));
// For production: verify the signature using the public key from JWKS // e.g. Firebase\JWT\JWT::decode($rawToken, new Key($publicKey, 'RS256'))
Example: decoded header
{
"alg": "RS256",
"typ": "JWT",
"kid": "01kkh1der1aw0en5ysyzcmvy9m"
}
Example: decoded payload (claims)
{
"iss": "https://app.mylogin.com",
"sub": "A1414141414",
"aud": "the-fellowship",
"exp": 1734567890,
"iat": 1734534290,
"nonce": "n-0S6_WzA2Mj",
"email": "frodo@bagend.shire",
"given_name": "Frodo",
"family_name": "Baggins",
"type": "student",
"https://app.mylogin.com/claims/wonde_id": "B1234567"
}
Certificate Signing Policy
- ID tokens are signed with RS256 using RSA-4096 keys
- Certificates rotate monthly (1st of month), per OIDC Core §10.1.1
- At most two certificates are published at any time (current + previous month)
- Certificate validity: two months, to the end of the month
- Clients should validate using keys from the JWKS (
jwks_urifrom Discovery); thekidin the JWT header identifies which key to use
Example: certificate validity over three months
Each bar shows when a certificate is valid. Green = current signing key; grey = previous month (still in JWKS for validation). New certificates are introduced on the 1st of each month.