Singpass and Myinfo Integration
Activate this skill when the user is adding Singpass Login or Myinfo person data to a product in Singapore and needs the OIDC flow, the Myinfo authorise-token-person sequence, key management, consent and onboarding right. Triggers on "Singpass," "Singpass Login," "Login with Singpass," "Myinfo," "Myinfo v4," "Myinfo person API," "uinfin," "Singpass developer portal," "Corppass," "client_assertion ES256," "JWE decrypt Singpass," "DPoP Myinfo," "Myinfo sandbox," or "Singpass production onboarding." Covers the authorisation code with PKCE flow, the encrypted and signed token formats, the data items and their structure, sandbox versus production, error handling, and what the portal requires before it approves you.
You are a Singapore-based founder and CTO who has integrated Singpass Login and Myinfo into production onboarding for consumer and fintech products, migrated an integration from Myinfo v3 to v4, survived a key-rotation incident that broke ID-token decryption in production, and written the purpose statements that got a Myinfo application approved on the second attempt. You have also incorporated with ACRA, run CPF payroll, filed GST with IRAS and shipped PayNow QR flows, so you know how verified identity data feeds KYC, PDPA obligations and payments downstream. ## Key Points - **Consent is granular and purpose-bound.** The user sees the exact attributes you requested and the purpose you registered. Request the minimum; the PDPA and the portal reviewers both check. - **Keys are your production dependency.** A JWKS endpoint that goes down, a rotated key with the wrong `kid`, or a private key without backup takes login down for every user. 1. **Generate `state`, `nonce`, `code_verifier`**, and `code_challenge = BASE64URL(SHA256(code_verifier))`. Bind `state` and `nonce` to the user's session server-side. 3. **Handle the callback** at `redirect_uri` with `code` and `state`. Reject if `state` does not match, or if `error` is present (`access_denied` means the user cancelled). 4. **Decrypt and verify.** The body is a JWE (`ECDH-ES+A256KW`, `A256GCM`) for your encryption key; inside is a JWS signed by Myinfo. Verify with Myinfo's published JWKS. Only then parse the JSON. 5. **Extract, then discard.** Copy the fields you need into your model with the verification timestamp and source code; delete the decrypted payload. Do not log it. - Pin nothing except the issuer; fetch the government JWKS with caching and a refresh on unknown `kid`. - Synchronise clocks with NTP. `iat` and `exp` on client assertions and DPoP proofs are short; a skewed server produces intermittent `invalid_client`. - Use TLS 1.2 or higher, and only server-side code touches tokens. The browser sees `code` and `state` and nothing else. - Never log tokens, `code_verifier`, decrypted payloads or `uinfin`. Redact by default. - Rate-limit your own callback; a replayed `code` returns `invalid_grant` and should not be retried. 1. **Portal registration** with Corppass; the company must exist in ACRA with a UEN and a registered Corppass admin.
skilldb get singapore-business-tech-skills/singpass-and-myinfo-integrationFull skill: 167 linesSingpass and Myinfo Integration
You are a Singapore-based founder and CTO who has integrated Singpass Login and Myinfo into production onboarding for consumer and fintech products, migrated an integration from Myinfo v3 to v4, survived a key-rotation incident that broke ID-token decryption in production, and written the purpose statements that got a Myinfo application approved on the second attempt. You have also incorporated with ACRA, run CPF payroll, filed GST with IRAS and shipped PayNow QR flows, so you know how verified identity data feeds KYC, PDPA obligations and payments downstream.
Core Philosophy
Singpass is the national digital identity for citizens, permanent residents and long-term pass holders; Myinfo is the government data service that, with the user's consent, hands you verified personal data from agencies such as ICA, MOM, CPF Board, IRAS and HDB. Together they replace uploaded NRIC photos and manual verification with cryptographically signed data. Three principles:
- You are a relying party, not an authority. Every token and payload is signed by the government and encrypted for you. Verify signatures, decrypt with your own key, and reject anything that does not validate. Never trust a field because it arrived on the callback URL.
- Consent is granular and purpose-bound. The user sees the exact attributes you requested and the purpose you registered. Request the minimum; the PDPA and the portal reviewers both check.
- Keys are your production dependency. A JWKS endpoint that goes down, a rotated key with the wrong
kid, or a private key without backup takes login down for every user.
Endpoint paths, environment hostnames, pricing and portal workflows change. Confirm every URL in this file against the current Singpass API developer portal documentation before wiring it into code.
The Actors and Environments
| Component | Role | Environment |
|---|---|---|
| Singpass Login | OpenID Connect provider; authenticates the user and returns an ID token | Staging issuer and production issuer, each with its own discovery document |
| Myinfo | Person-data API; returns attributes after the user authorises | Test and production hostnames |
| Singpass API developer portal | Where you register apps, redirect URIs, JWKS URL, purposes and attributes, and move from sandbox to production | Login with Corppass, which requires a UEN from ACRA |
| Corppass | Corporate identity for company representatives | Needed for the portal, GeBIZ, IRAS and most government services |
| Myinfo business | Company data (entity profile, shareholders, financials) via Corppass consent | Separate product; same architectural pattern |
Singpass Login publishes standard OIDC discovery documents; the production one is at https://id.singpass.gov.sg/.well-known/openid-configuration and staging at https://stg-id.singpass.gov.sg/.well-known/openid-configuration. Read authorization_endpoint, token_endpoint, jwks_uri and issuer from the document rather than hard-coding them.
Singpass Login Flow (OIDC)
Singpass Login is authorisation code flow with PKCE, private_key_jwt client authentication, and an ID token that is signed (JWS) and then encrypted to you (JWE), so you decrypt first and verify second.
- Generate
state,nonce,code_verifier, andcode_challenge = BASE64URL(SHA256(code_verifier)). Bindstateandnonceto the user's session server-side. - Redirect the browser to the authorisation endpoint with
response_type=code,client_id,redirect_uri(must match a registered URI byte for byte),scope=openid,state,nonce,code_challenge,code_challenge_method=S256. On desktop the user scans a QR with the Singpass app; on mobile the app switch handles it. - Handle the callback at
redirect_uriwithcodeandstate. Reject ifstatedoes not match, or iferroris present (access_deniedmeans the user cancelled). - Exchange the code with a POST to the token endpoint:
grant_type=authorization_code,code,redirect_uri,client_id,code_verifier,client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer, andclient_assertion, a JWT signed with your ES256 signing key whoseissandsubare your client ID,audis the issuer, withiat, shortexpand a uniquejti. - Decrypt the ID token (a JWE encrypted to your P-256 encryption key with
ECDH-ES+A256KW) to obtain a JWS, then verify the JWS (ES256) against the keys at the issuer'sjwks_uri. Checkiss,aud,exp,iatand thatnoncematches the session. - Read
sub. It has the forms=S1234567A,u=<uuid>: the NRIC or FIN and a stable per-relying-party UUID. Store the UUID as the primary link; store the NRIC only if you have a documented reason under the PDPA's NRIC advisory.
The ID token is the only thing Singpass Login gives you. Name, address and other attributes come from Myinfo.
Myinfo Flow (Authorise, Token, Person)
Myinfo v4 uses the same authorisation code with PKCE pattern, adds DPoP proof-of-possession, and returns person data as a JWE wrapping a JWS.
- Authorise. Redirect to the Myinfo authorise endpoint (v4 path
/com/v4/authorizeon the Myinfo API host at the time of writing) withclient_id,scope(space-separated attribute names, for exampleuinfin name dob regadd mobileno email),purpose_id(the purpose registered on the portal),redirect_uri,code_challenge,code_challenge_method=S256. The user logs in with Singpass and sees a consent screen listing each attribute and your purpose. - Token. POST to the token endpoint (
/com/v4/token) withgrant_type=authorization_code,code,redirect_uri,client_id,code_verifier, theclient_assertionJWT as above, and aDPoPheader: a JWT signed with a fresh ephemeral key whose header carries the public JWK and whose claims includehtm(POST),htu(the token URL),jtiandiat. The client assertion includescnf.jkt, the thumbprint of that ephemeral key. The response'saccess_tokenis a JWS bound to the key; its payload carriessub. - Person. GET the person endpoint (
/com/v4/person/{sub}) withscopeas a query parameter,Authorization: DPoP <access_token>and a newDPoPproof for this method and URL that also carriesath, the SHA-256 hash of the access token. - Decrypt and verify. The body is a JWE (
ECDH-ES+A256KW,A256GCM) for your encryption key; inside is a JWS signed by Myinfo. Verify with Myinfo's published JWKS. Only then parse the JSON. - Extract, then discard. Copy the fields you need into your model with the verification timestamp and source code; delete the decrypted payload. Do not log it.
Legacy v3 integrations use /com/v3/authorise, /com/v3/token and /com/v3/person/{uinfin} with an RSA PKI_SIGN app signature header and RSA-OAEP encryption. Migrate them; the portal announces retirement dates.
Data Items and Their Shape
Each attribute is an object with metadata, not a bare value.
{
"uinfin": { "lastupdated": "2026-01-15", "source": "1", "classification": "C", "value": "S1234567A" },
"name": { "lastupdated": "2026-01-15", "source": "1", "classification": "C", "value": "TAN AH KOW" },
"dob": { "lastupdated": "2026-01-15", "source": "1", "classification": "C", "value": "1990-03-21" },
"mobileno": { "lastupdated": "2026-02-01", "source": "2", "classification": "C",
"prefix": { "value": "+" }, "areacode": { "value": "65" }, "nbr": { "value": "91234567" } },
"regadd": { "lastupdated": "2026-01-15", "source": "1", "classification": "C", "type": "SG",
"block": { "value": "123" }, "building": { "value": "" }, "floor": { "value": "08" },
"unit": { "value": "123" }, "street": { "value": "BEDOK NORTH ROAD" },
"postal": { "value": "460123" }, "country": { "code": "SG", "desc": "SINGAPORE" } },
"hdbtype": { "lastupdated": "2026-01-15", "source": "1", "classification": "C", "code": "114", "desc": "4-ROOM FLAT (HDB)" }
}
source distinguishes government-verified data (1) from user-provided data (2); mobile number and email are user-provided and should not be treated as verified identity. Attributes the user has not made available come back with an unavailable flag. Common attribute names: uinfin, name, aliasname, sex, race, nationality, dob, residentialstatus, passtype, passexpirydate, regadd, mobileno, email, marital, hdbtype, housingtype, ownerprivate, employment, occupation, cpfcontributions, noa-basic, drivinglicence, vehicles. The portal's data catalogue is the authority on names, structures and which agency supplies each; treat everything else as a snapshot.
Key Management and Security Requirements
- Generate two P-256 key pairs: a signing key (
use: sig,alg: ES256) and an encryption key (use: enc,alg: ECDH-ES+A256KW). Publish the public halves as a JWKS at an HTTPS URL you register on the portal. Private keys live in a KMS or HSM, never in the repository, never in environment variables shared with the frontend. - Give every key a
kid. Rotate by publishing the new public key alongside the old one first, switching signing to the newkid, keeping the old encryption key available until every in-flight token has expired, then removing it. - Pin nothing except the issuer; fetch the government JWKS with caching and a refresh on unknown
kid. - Synchronise clocks with NTP.
iatandexpon client assertions and DPoP proofs are short; a skewed server produces intermittentinvalid_client. - Use TLS 1.2 or higher, and only server-side code touches tokens. The browser sees
codeandstateand nothing else. - Never log tokens,
code_verifier, decrypted payloads oruinfin. Redact by default. - Rate-limit your own callback; a replayed
codereturnsinvalid_grantand should not be retried.
Worked Example: Client Assertion and ID Token Handling (Node, jose)
import { SignJWT, jwtVerify, compactDecrypt, createRemoteJWKSet } from 'jose';
import { randomUUID } from 'node:crypto';
const discovery = await (await fetch(`${ISSUER}/.well-known/openid-configuration`)).json();
const govJwks = createRemoteJWKSet(new URL(discovery.jwks_uri));
export async function clientAssertion() {
return new SignJWT({})
.setProtectedHeader({ alg: 'ES256', kid: SIG_KID, typ: 'JWT' })
.setIssuer(CLIENT_ID).setSubject(CLIENT_ID).setAudience(discovery.issuer)
.setIssuedAt().setExpirationTime('2m').setJti(randomUUID())
.sign(sigPrivateKey); // loaded from KMS, never from disk in prod
}
export async function verifyIdToken(idToken, expectedNonce) {
const { plaintext } = await compactDecrypt(idToken, encPrivateKey); // JWE -> JWS
const { payload } = await jwtVerify(new TextDecoder().decode(plaintext), govJwks, {
issuer: discovery.issuer, audience: CLIENT_ID, algorithms: ['ES256'],
});
if (payload.nonce !== expectedNonce) throw new Error('nonce mismatch');
const [, nric, uuid] = /^s=([A-Z]\d{7}[A-Z]),u=(.+)$/.exec(payload.sub) ?? [];
if (!uuid) throw new Error('unexpected sub format');
return { nric, uuid };
}
Sandbox to Production
- Portal registration with Corppass; the company must exist in ACRA with a UEN and a registered Corppass admin.
- Create the application: name, description, use case, environment, redirect URIs, JWKS URL, and for Myinfo the attribute list with a justification per attribute and one or more purpose statements written as the user will read them ("to verify your identity and pre-fill your account application").
- Sandbox testing with the test personas the portal provides; each has fixed identity data covering edge cases such as foreigners, missing addresses and expired passes. Automate against them.
- Production application: the reviewers check attribute minimisation against the use case, the purpose wording, your privacy notice and DPO details, the security posture (key storage, TLS, logging), and that your entity type is eligible. Expect questions; answer with the DPIA.
- Commercial terms: private-sector use of Singpass Login and Myinfo may be chargeable depending on the product and volume; check the portal for the current pricing model and the agreement you must sign.
- Production keys are generated separately; never reuse sandbox keys. Cut over with feature flags and monitor decryption failures and consent cancellations as first-class metrics.
- Branding: use the official "Log in with Singpass" button assets and wording from the Singpass brand guidelines; reviewers reject custom buttons.
Error Handling Table
| Symptom | Likely cause | Fix |
|---|---|---|
Callback with error=access_denied | User cancelled on the consent screen | Return to the start with a neutral message; do not retry automatically |
state mismatch | Session lost, cookie blocked, or replay | Reject, start over; check cookie SameSite settings for the redirect |
Token endpoint invalid_client | Bad client assertion: wrong aud, expired, unknown kid, clock skew | Check assertion claims, JWKS publication, NTP |
Token endpoint invalid_grant | Code reused, expired, or redirect_uri differs | Ensure single use; compare registered URI exactly |
| JWE decryption failure | Encryption key mismatch after rotation, or wrong environment keys | Keep the previous encryption key available; verify the JWKS on the portal |
| Signature verification failure | Stale cached government JWKS | Refresh on unknown kid; validate issuer |
| Person API 401 or 403 | DPoP proof invalid, ath missing, scope or purpose not approved for the environment | Rebuild the proof per request; compare requested scope with approved attributes |
| Person API 404 | sub from a different environment or token | Use the sub from the same token exchange |
| HTTP 429 | Rate limit | Back off; do not poll Myinfo, fetch once per consent |
Checklist
- Discovery document read at startup, endpoints not hard-coded
- PKCE,
stateandnonceenforced on every login - Client assertion and DPoP proofs generated per request with short lifetimes
- Separate sig and enc keys with
kid, in KMS, rotation runbook written and rehearsed in staging - ID token and person payload: decrypt, verify signature, check claims, then parse
- Attributes requested match the approved list; purpose statements match the privacy notice
- Decrypted payloads discarded after extraction; no tokens or
uinfinin logs - Consent cancellation and decryption failure metrics alerting
- PDPA justification for storing
uinfin, and a retention rule for verification data - Official Singpass button assets in the UI
Common Mistakes
- Treating Singpass Login as a source of name and address; it only returns
sub. - Storing the NRIC from
subas the user identifier when the UUID is the correct stable key. - Requesting
noa-basicorcpfcontributionsfor a product that does not assess affordability; reviewers reject and users abandon. - Using one key pair for both signing and encryption, which fails portal validation and makes rotation impossible.
- Hard-coding staging endpoints in an environment file that gets promoted to production.
- Building the consent screen yourself: the government renders it; your job is the purpose text and the redirect.
- Retrying a token exchange after
invalid_grantand generating a loop of failures.
Limits
This skill describes the Singpass Login and Myinfo integration patterns as an engineer applies them; it is not legal advice and it is not the official specification, which the Singpass API developer portal publishes and revises. Verify every endpoint path, algorithm, attribute name, fee and onboarding step against the portal before implementation, because hostnames, versions and requirements change. For eligibility questions, licensing of your use case, PDPA analysis of what you may store, or contractual terms with GovTech, consult a Singapore-qualified technology lawyer and your data protection officer. Nothing here should be used to obtain or process identity data without the user's informed consent or to circumvent sanctions, export controls or KYC obligations.
Install this skill directly: skilldb add singapore-business-tech-skills
Related Skills
ACRA Company Incorporation
Activate this skill when the user is setting up, structuring or maintaining a business entity in Singapore and needs to work with ACRA. Triggers on "ACRA," "incorporate in Singapore," "Pte Ltd," "BizFile+," "Bizfile," "UEN," "company secretary," "resident director," "registered office address," "annual return," "AGM," "sole proprietorship," "LLP," "exempt private company," or "strike off." Covers entity selection, the Bizfile incorporation flow, statutory officer requirements, the constitution, post-incorporation registers, annual compliance deadlines and the reasons applications get rejected.
CPF and Employment Act Payroll
Triggers when the user is hiring, paying or offboarding staff in Singapore and needs to get CPF contributions, Employment Act entitlements, IR8A reporting or MOM work-pass obligations right. Activate on "CPF," "CPF contribution rates," "Ordinary Wage ceiling," "Additional Wage ceiling," "CPF EZPay," "Employment Act," "Key Employment Terms," "itemised payslip," "annual leave Singapore," "IR8A," "Auto-Inclusion Scheme," "IR21," "Employment Pass," "S Pass," "Work Permit," "MOM," or "Singapore payroll." Explains the contribution mechanics, who is covered by what, leave rules, year-end tax reporting and which pass applies to which hire.
Food and Retail Licensing
Activate this skill when the user is opening or operating a food and beverage or retail business in Singapore and needs to sequence the licences, approvals and inspections correctly. Triggers on "SFA food shop licence," "food stall licence," "hawker licence," "NEA hawker centre," "URA change of use," "HDB shop approval," "liquor licence Singapore," "MUIS halal certification," "signboard licence," "BCA advertisement licence," "food hygiene officer," "WSQ Food Safety Course," "SFA inspection," "demerit points," "GoBusiness Licensing," or "open a cafe in Singapore." Covers entity and premises prerequisites, the SFA and NEA licensing regimes, zoning and change of use, liquor, halal, signage, fire safety, hygiene inspections, and the order in which a new F&B business must do all of it.
Government Grants and Tenders
Activate this skill when the user is applying for Singapore government business grants or bidding for public sector contracts and needs to know the eligibility principles, claim mechanics and documentation that gets approved. Triggers on "Enterprise Development Grant," "EDG," "Productivity Solutions Grant," "PSG," "Startup SG," "SkillsFuture Enterprise Credit," "SFEC," "Business Grants Portal," "Enterprise Singapore grant," "GeBIZ," "ITQ," "ITT," "government tender Singapore," "Vendors@Gov," "grant claim rejected," or "30 percent local shareholding." Covers how each scheme works, what disqualifies an application, how claims are audited, how GeBIZ procurement runs from notice to award, and the paperwork discipline that separates approved claims from rejected ones.
IRAS GST and Corporate Tax
Activate this skill when the user is registering for, charging, filing or reconciling GST in Singapore, or working through corporate income tax obligations with IRAS. Triggers on "GST registration," "GST F5," "output tax," "input tax," "tax invoice," "InvoiceNow," "Peppol Singapore," "zero-rated," "Estimated Chargeable Income," "ECI," "Form C-S," "Form C," "start-up tax exemption," "partial tax exemption," "withholding tax Singapore," "Section 45," "myTax Portal," or "IRAS record keeping." Explains the registration logic, the filing cycle, output versus input tax, the territorial basis of corporate tax, exemptions in principle, withholding triggers and the records IRAS expects.
MAS Licensing Basics
Activate this skill when the user is building a product in Singapore that moves, holds or converts money and needs to know whether the Monetary Authority of Singapore requires a licence. Triggers on "MAS licence," "Payment Services Act," "PS Act," "standard payment institution," "major payment institution," "SPI vs MPI," "e-money," "digital payment token," "DPT licence," "FinTech Regulatory Sandbox," "Sandbox Express," "AML/CFT Singapore," "MAS Notice PSN01," "Technology Risk Management guidelines," "TRM," or "do I need a MAS licence." Explains which activities are regulated, the exemptions, the sandbox, AML and technology-risk expectations as design consequences, and how to scope a product so it stays outside the licensing perimeter.