Tutorial 2: End-to-end Integration with Myinfo v4 APIs
This tutorial will call the APIs from your server-based (or running from localhost) application. Myinfo uses OAuth 2.1 for our Authentication and Authorisation flow. For a brief overview of the end to end flow, please refer to our Overview
1. Download & Setup Sample Client Application
1.1 Install Node.js and NPM
In order for the demo application to run, you will need to Install Node.js and NPM. Follow the instructions given by the links below depending on your OS.
1.2 Download the sample client application
Please download the sample client application from our Github.
1.3 Run NPM install
Run the following command in the folder where you unzipped the application:
npm install
1.4 Start the Application
Execute the following command to start the application:
npm start
1.5 Access the Application on Your Browser
You should be able to access the sample application via the following URL:
http://localhost:3001
2. Authorize API
Click on the "Retrieve Myinfo" button on the sample application.
This calls the /authorize API below (with some additional parameters):
client_id
unique ID for your application. For our sample application, this is STG2-MYINFO-SELF-TEST
scope
space separated list of attributes requested. Possible attributes are listed in the Person object definition in the API specifications.
purpose_id
purpose_id should have a corresponding pre-registered purpose(s) description as part of the setup. Purpose description refers to what the user will see in the consent page
code_challenge
Value resulting from performing Base64 encoding of a SHA256 hash of code_verifier (cryptographic random value generate on server side.) Refer to the section on Proof Key for Code Exchange (PKCE) for more information (Reference : PKCE)
code_challenge_method
Hashing method used in producing code_challenge. Only supports 'S256'
redirect_uri
your callback URL for Myinfo to return with the authorisation code. For our sample application the callback url is http://localhost:3001/callback
response_type
Response type for authorisation code flow - must be "code".
2.1 Code Example for Authorize API
With reference to views/html/index.html in the sample application code:
The index.html is the frontend(client side) code.
function callAuthorizeApi() {
//Call backend server to generate code challenge
$.ajax({
url: "/generateCodeChallenge",
data: {},
type: "POST",
success: function (code_challenge) {
//Redirect to authorize url after generating code challenge
var authorizeUrl = authApiUrl + "?client_id=" + clientId +
"&scope=" + scope +
"&purpose_id=" + purpose_id +
"&code_challenge=" + code_challenge +
"&code_challenge_method=" + method +
"&response_type=code" +
"&redirect_uri=" + redirectUrl;
window.location = authorizeUrl;
},
error: function (result) {
alert("ERROR:" + JSON.stringify(result.responseJSON.error));
}
});
}
This code example above triggers the /authorize API.
2.2 Login with MockPass
Select the test ID and login using MockPass:
NRIC: 60050408A
You may also use test personas found in the Personas.
The /authorize
API endpoint triggers the MockPass login and shows the consent page after successful login.
2.3 Consent Page
Once you have successfully logged into MockPass, a consent page similar to the one below will be shown:

2.4 Retrieve Authorization Code
If you have followed the steps above correctly, our system should return you an authorization code by invoking your callback URL.
You should now see something like this in your browser URL dialog:
http://localhost:3001/callback?code=e2369168-52da-421a-b70f-03f64e779c4b
Notice that the query string parameter value of code above is the authorization code(authcode). We will use this authorization code(authcode) in the next /token
API call.
In the example above, the authorization code(authcode) is e2369168-52da-421a-b70f-03f64e779c4b.
The /token
API and /person
API calls should be invoked automatically by the sample app once you have finished the consent page.
We will look at the code for these 2 APIs in the following sections.
3. Token API
Now that you have the authcode
, you can invoke the /token
API to get the access_token
.
3.1 Request
Request Parameters:
Method: POST
Content-Type: application/x-www-form-urlencoded
Agent: HTTP client
Response Type: json
i) Headers:
DPoP
DPoP Proof (JWT) containing the client's ephemeral public signing key that can be used to prove legit possession of the access_token issued. (Reference: DPoP flow)
Sample header of the Token API request:
POST https://test.api.myinfo.gov.sg/com/v4/token HTTP 1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImp3ayI6eyJrdHkiOiJFQyIsImtpZCI6Ik0yT0pWVGRmaVV3OUMxSFFrTzF2VGlqTFhHT3lwY0Z1VDV3ZDQtNVdkekUiLCJjcnYiOiJQLTI1NiIsIngiOiJuOTJ0THQyUk5vQmdCM2piT2txNjF3bF8zM1VTUzA4dFMtR1I3ZGUwTWYwIiwieSI6IjNyaUcxamNFWThCTFpkUjhmc2VBa1hBLVJvSW92X3g5Q19iRzNKWFZVcTQiLCJ1c2UiOiJzaWciLCJhbGciOiJFUzI1NiJ9LCJhbGciOiJFUzI1NiJ9.eyJodHUiOiJodHRwczovL3NpdC5hcGkubXlpbmZvLmdvdi5zZy9jb20vdjQvdG9rZW4iLCJodG0iOiJQT1NUIiwianRpIjoiYldEWTZhVENuQUdLV3RDVWpZTFZJVm1vRW1CNFhhcmVwc0JEODVHQyIsImlhdCI6MTY2MjcxNDk5OCwiZXhwIjoxNjYyNzE1MTE4fQ.yOsoD-q7DPlgI_cnRVmjXcBraSxD5riCVmc8kaEoxGstTipFdTZIvnMs6EYs8oSFUYv4OVWcYm5MKLrJNLdtew
code
The authcode given by the Authorize API. (Reference: Authorize)
grant_type
Default: "authorization_code" Grant type for getting token (default "authorization_code")
client_id
Unique ID for your application.
redirect_uri
Application's callback URL.
client_assertion
The assertion being used to authenticate the client. (Reference: Client Assertion)
client_assertion_type
Default: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" The format of the assertion, which is defined to be 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
code_verifier
Cryptographic random string generated and kept secret on server-side, it's corresponding to code_challenge sent in the Authorize API (Reference: PKCE)
Sample body of the /token API request in application/x-www-form-urlencoded:
Copy to clipboard
body : 'code=KhtDB67e2DrPgB3wpLjUsDfppHsBB42A9Crsx2b0
&grant_type=authorization_code
&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fcallback
&client_id=STG2-MYINFO-SELF-TEST
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6ImFRUHlaNzJOTTA0M0U0S0Vpb2FIV3ppeHQwb3dWOTlnQzlrUkszODhXb1EifQ.eyJzdWIiOiJTVEcyLU1ZSU5GTy1TRUxGLVRFU1QiLCJqdGkiOiJtZzBNcFl0dkcyQTRUOWFRZkxON0o3OEY3dVltUmZJVmVyRUhIUFpaIiwiYXVkIjoiaHR0cHM6Ly9zaXQuYXBpLm15aW5mby5nb3Yuc2cvY29tL3Y0L3Rva2VuIiwiaXNzIjoiU1RHMi1NWUlORk8tU0VMRi1URVNUIiwiaWF0IjoxNjYyNzE0OTk4LCJleHAiOjE2NjI3MTUyOTgsImNuZiI6eyJqa3QiOiJNMk9KVlRkZmlVdzlDMUhRa08xdlRpakxYR095cGNGdVQ1d2Q0LTVXZHpFIn19.OlluOi2RkwAavibqhGrDL4m6m91IlM_vnfu-4CY0pmkSbUDcKS_NBlggNrTNcc_wnbFBSqMYNo2V4Geh9Ucc6g
&code_verifier=Av6ktmeC1UsjHY677P-zf5Vk2x94W38Zu4pl4qhbeok'
The sample application will then send the constructed request to the /token API
Sample Code: With reference to myinfo-connector/index.js in our sample sample client application connector
index.js is the backend (server side) code.
callTokenAPI = async function (authCode, privateSigningKey, codeVerifier, sessionPopKeyPair) {
let cacheCtl = "no-cache";
let contentType = "application/x-www-form-urlencoded";
let method = constant.HTTP_METHOD.POST;
let clientAssertionType = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
let jktThumbprint = await this.securityHelper.generateJwkThumbprint(sessionPopKeyPair.publicKey)
let strParams;
// assemble params for Token API
strParams = `grant_type=authorization_code` +
"&code=" + authCode +
"&redirect_uri=" + CONFIG.REDIRECT_URL +
"&client_id=" + CONFIG.CLIENT_ID +
"&code_verifier=" + codeVerifier +
"&client_assertion_type=" + clientAssertionType +
"&client_assertion=" + await this.securityHelper.generateClientAssertion(CONFIG.TOKEN_URL, CONFIG.CLIENT_ID, privateSigningKey, jktThumbprint);
let params = querystring.parse(strParams);
let dPoP= await this.securityHelper.generateDpop(CONFIG.TOKEN_URL, null, null,constant.HTTP_METHOD.POST, sessionPopKeyPair);
// assemble headers for Token API
let strHeaders = `Content-Type=${contentType}&Cache-Control=${cacheCtl}&DPoP=${dPoP}`;
let headers = querystring.parse(strHeaders);
// invoke Token API
let tokenURL = (CONFIG.USE_PROXY && CONFIG.USE_PROXY == "Y") ? CONFIG.PROXY_TOKEN_URL : CONFIG.TOKEN_URL;
let parsedTokenUrl = urlParser.parse(tokenURL);
let tokenDomain = parsedTokenUrl.hostname;
let tokenRequestPath = parsedTokenUrl.path;
let accessToken = await requestHandler.getHttpsResponse(tokenDomain, tokenRequestPath, headers, method, params);
return accessToken;
};
The code example above creates the request to call the /token API.
[HTTP POST]
https://test.api.myinfo.gov.sg/com/v4/token
3.2 Response
Response Type: application/json
access_token
The resulting access token for the code flow
token_type
Describes how the token can be used. (e.g. DPoP)
expires_in
Expiry of access token (in seconds)
refresh_token
Refresh token that can be used to exchange for another access token. Only available if client is configured to receive refresh token.
client_assertion
The assertion being used to authenticate the client. (Reference: Client Assertion)
scope
Scopes requested, separated by space
Sample response from Token API in application/json:
Copy to clipboard
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IkFGTW5uS1JXVGFCWUVoTmZFQjZpUTVFckMxeXFHVnlaY2hIOEE3bmxfeU0ifQ.eyJzdWIiOiI5MTUyNjdmMC01OTM5LTAyMzAtNzhlNy1iOGNkYmFhYjg1MTgiLCJqdGkiOiJvMkZaVUpmSFZWVjA3aFpLTFZrc2Yxd0RBYnNUUUtWblFXM3RjZDI5Iiwic2NvcGUiOiJ1aW5maW4gbmFtZSBzZXggcmFjZSBuYXRpb25hbGl0eSBkb2IgZW1haWwgbW9iaWxlbm8gcmVnYWRkIGhvdXNpbmd0eXBlIGhkYnR5cGUiLCJleHBpcmVzX2luIjoxODAwLCJhdWQiOiJodHRwczovL3Rlc3QuYXBpLm15aW5mby5nb3Yuc2cvY29tL3Y0L3BlcnNvbiIsInJlYWxtIjoibXlpbmZvLWNvbSIsImlzcyI6Imh0dHBzOi8vdGVzdC5hcGkubXlpbmZvLmdvdi5zZy9zZXJ2aWNlYXV0aC9teWluZm8tY29tIiwiY2xpZW50Ijp7ImNsaWVudF9pZCI6IlNURzItTVlJTkZPLVNFTEYtVEVTVCIsImNsaWVudF9uYW1lIjoiTXlJbmZvIFNlbGYgVGVzdCBBcHAgR0NDIiwiZW50aXR5X3VlbiI6IlQxNkdCMDAwMkciLCJlbnRpdHlfbmFtZSI6IkdvdlRlY2gifSwiY25mIjp7ImprdCI6ImhHdHN1S3h3UmFMOE1NeDVqVjVUYUluSWpqOFNLS3N3VEVOOGcxaU9FY1EifSwiZXBrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ1c2UiOiJlbmMiLCJraWQiOiI3VGt5TWFqV0JYUlo3aVpmZ3lQUGZmMmdMMzloMlh0ZkpEemNzNXRjZXJNIiwieCI6Ik5mSXhKdWRCTzFfWEQ0RG5oa1ZLUG9uSHV4MExHMTJPM0QtWjJOZnN1RUUiLCJ5IjoiMkhHNmV5SmNFRUJWWlVwMVlsRjU3TFdNbEFJbXlTdU41d1FjZUVybW85OCIsImFsZyI6IkVDREgtRVMrQTI1NktXIn0sImlhdCI6MTY2NzIwMTY4OCwibmJmIjoxNjY3MjAxNjg4LCJleHAiOjE2NjcyMDM0ODh9.0CMpP4Whxk11XTMxg1fz6Srw2HkPiY-t2Tydb8ouQVpCwMNe6DW3Mu6KBdOo00ipa7Nlhw375zwmWAIT-8-3CQ",
"token_type": "DPoP",
"expires_in": 1799,
"refresh_token": "bsAJGkONZJJjs0cR11ZQzGHzxLKwDoEwaApy0krW",
"scope": "uinfin name sex race nationality dob email mobileno regadd housingtype hdbtype"
}
Notice the response contains an access_token, which is in the JWT (JSON Web Token) format. (Reference: JWT)
The access_token can be verified using Myinfo JWK URI and decoded.(Reference: JWS)
You should see the decoded access_token in the onscreen logs that looks like this:
Copy to clipboard
{
"sub": "915267f0-5939-0230-78e7-b8cdbaab8518",
"jti": "o2FZUJfHVVV07hZKLVksf1wDAbsTQKVnQW3tcd29",
"scope": "uinfin name sex race nationality dob email mobileno regadd housingtype hdbtype",
"expires_in": 1800,
"aud": "https://test.api.myinfo.gov.sg/com/v4/person",
"realm": "myinfo-com",
"iss": "https://test.api.myinfo.gov.sg/serviceauth/myinfo-com",
"client": {
"client_id": "STG2-MYINFO-SELF-TEST",
"client_name": "MyInfo Self Test App GCC",
"entity_uen": "T16GB0002G",
"entity_name": "GovTech"
},
"cnf": { "jkt": "hGtsuKxwRaL8MMx5jV5TaInIjj8SKKswTEN8g1iOEcQ" },
"epk": {
"kty": "EC",
"crv": "P-256",
"use": "enc",
"kid": "7TkyMajWBXRZ7iZfgyPPff2gL39h2XtfJDzcs5tcerM",
"x": "NfIxJudBO1_XD4DnhkVKPonHux0LG12O3D-Z2NfsuEE",
"y": "2HG6eyJcEEBVZUp1YlF57LWMlAImySuN5wQceErmo98",
"alg": "ECDH-ES+A256KW"
},
"iat": 1667201688,
"nbf": 1667201688,
"exp": 1667203488
}
This access_token is a representation of the permissions that was given by the user when he/she clicked on "I Agree" on the consent page.
Notice the sub attribute in the JSON token is the identifier of the person who logged in via MockPass. We will use this identifier for the /person API call next.
4. Person API
Now that you have the access_token, you can invoke the /person API to get the Person data.
This API call is essentially the same as the one in our Tutorial 1, except that you will need to provide a valid access_token, or else we will reject your API request call.
4.1 Request
Request Parameters:
Method: GET
Agent: HTTP client
Response Type: json
i) Header:
Authorization
Include the access_token (JWT) from /Token API in this header prefixed with 'DPoP'.
DPoP
Include the generated Demonstration of Proof of Possession token. (Reference: DPoP)
ii) Path Parameters:
sub
Identifier of user obtained from 'sub' attribute in access_token.
Example: 915267f0-5939-0230-78e7-b8cdbaab8518
iii) Query parameters:
scope
Space separated list of scopes requested.
Example: scope=name nationality
iii) Sample Code:
With reference to myinfo-connector/index.js in our sample client application connector code:
Copy to clipboard
callPersonAPI = async function (sub, accessToken, sessionPopKeyPair) {
let urlLink;
urlLink = CONFIG.PERSON_URL + "/" + sub;
let cacheCtl = "no-cache";
let method = constant.HTTP_METHOD.GET;
// assemble params for Person API
let strParams ="scope=" + encodeURIComponent(CONFIG.SCOPE);
// assemble headers for Person API
let strHeaders = "Cache-Control=" + cacheCtl;
let headers = querystring.parse(strHeaders);
let decodedToken = await this.securityHelper.verifyJWS(accessToken, CONFIG.AUTHORIZE_JWKS_URL);
let ath = this.securityHelper.base64URLEncode(this.securityHelper.sha256(accessToken))
let dpopToken = await this.securityHelper.generateDpopProof(urlLink, method, sessionPopKeyPair, ath);
headers["dpop"] = dpopToken;
headers["Authorization"] = "DPoP " + accessToken;
logger.info("Authorization Header for MyInfo Person API: ", JSON.stringify(headers));
// invoke person API
let personURL = (CONFIG.USE_PROXY && CONFIG.USE_PROXY == "Y") ? CONFIG.PROXY_PERSON_URL : CONFIG.PERSON_URL;
let parsedUrl = urlParser.parse(personURL);
let domain = parsedUrl.hostname;
let requestPath = parsedUrl.path + "/" + sub + "?" + strParams;
//invoking https to do GET call
let personData = await requestHandler.getHttpsResponse(domain, requestPath, headers, method, null);
return personData;
};
The code example above creates the request to call the /person API:
Copy to clipboard
[HTTP GET]
https://test.api.myinfo.gov.sg/com/v4/person/915267f0-5939-0230-78e7-b8cdbaab8518?scope=uinfin%20name%20sex%20race%20nationality%20dob%20email%20mobileno%20regadd%20housingtype%20hdbtype
4.1.1 Providing the Access Token in the Request Header STEP 1: The access_token should be provided in the header of your /person API request under "Authorization" with Prefix "DPoP"
Copy to clipboard
{
"Authorization": "DPoP eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IkFGTW5uS1JXVGFCWUVoTmZFQjZpUTVFckMxeXFHVnlaY2hIOEE3bmxfeU0ifQ.eyJzdWIiOiI5MTUyNjdmMC01OTM5LTAyMzAtNzhlNy1iOGNkYmFhYjg1MTgiLCJqdGkiOiJvMkZaVUpmSFZWVjA3aFpLTFZrc2Yxd0RBYnNUUUtWblFXM3RjZDI5Iiwic2NvcGUiOiJ1aW5maW4gbmFtZSBzZXggcmFjZSBuYXRpb25hbGl0eSBkb2IgZW1haWwgbW9iaWxlbm8gcmVnYWRkIGhvdXNpbmd0eXBlIGhkYnR5cGUiLCJleHBpcmVzX2luIjoxODAwLCJhdWQiOiJodHRwczovL3Rlc3QuYXBpLm15aW5mby5nb3Yuc2cvY29tL3Y0L3BlcnNvbiIsInJlYWxtIjoibXlpbmZvLWNvbSIsImlzcyI6Imh0dHBzOi8vdGVzdC5hcGkubXlpbmZvLmdvdi5zZy9zZXJ2aWNlYXV0aC9teWluZm8tY29tIiwiY2xpZW50Ijp7ImNsaWVudF9pZCI6IlNURzItTVlJTkZPLVNFTEYtVEVTVCIsImNsaWVudF9uYW1lIjoiTXlJbmZvIFNlbGYgVGVzdCBBcHAgR0NDIiwiZW50aXR5X3VlbiI6IlQxNkdCMDAwMkciLCJlbnRpdHlfbmFtZSI6IkdvdlRlY2gifSwiY25mIjp7ImprdCI6ImhHdHN1S3h3UmFMOE1NeDVqVjVUYUluSWpqOFNLS3N3VEVOOGcxaU9FY1EifSwiZXBrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ1c2UiOiJlbmMiLCJraWQiOiI3VGt5TWFqV0JYUlo3aVpmZ3lQUGZmMmdMMzloMlh0ZkpEemNzNXRjZXJNIiwieCI6Ik5mSXhKdWRCTzFfWEQ0RG5oa1ZLUG9uSHV4MExHMTJPM0QtWjJOZnN1RUUiLCJ5IjoiMkhHNmV5SmNFRUJWWlVwMVlsRjU3TFdNbEFJbXlTdU41d1FjZUVybW85OCIsImFsZyI6IkVDREgtRVMrQTI1NktXIn0sImlhdCI6MTY2NzIwMTY4OCwibmJmIjoxNjY3MjAxNjg4LCJleHAiOjE2NjcyMDM0ODh9.0CMpP4Whxk11XTMxg1fz6Srw2HkPiY-t2Tydb8ouQVpCwMNe6DW3Mu6KBdOo00ipa7Nlhw375zwmWAIT-8-3CQ"
}
STEP 2 The DPoP proof JWT should be provided in the header of your /person API request under "DPoP"
Copy to clipboard
{
"DPoP": "eyJ0eXAiOiJkcG9wK2p3dCIsImp3ayI6eyJrdHkiOiJFQyIsImtpZCI6ImhHdHN1S3h3UmFMOE1NeDVqVjVUYUluSWpqOFNLS3N3VEVOOGcxaU9FY1EiLCJjcnYiOiJQLTI1NiIsIngiOiJMX0F3SklGeDZWUEk1RklIZFBwSnppLVZFNGdkUlhCU3Zld3ktTmhySFFFIiwieSI6IjF0czFnZENpTWhjUHI1WkJPSjNaSHdBY0YtUkJPVVd6MjJGX296SGRjbk0iLCJ1c2UiOiJzaWciLCJhbGciOiJFUzI1NiJ9LCJhbGciOiJFUzI1NiJ9.eyJodHUiOiJodHRwczovL3Rlc3QuYXBpLm15aW5mby5nb3Yuc2cvY29tL3Y0L3BlcnNvbi85MTUyNjdmMC01OTM5LTAyMzAtNzhlNy1iOGNkYmFhYjg1MTgiLCJodG0iOiJHRVQiLCJqdGkiOiJxc21vU21BVzF6WmtCTHNBUEZUWU8xNFQ1Ukl3eWxHQXFueHdCb3ViIiwiaWF0IjoxNjY3MjAxNjg5LCJleHAiOjE2NjcyMDE4MDksImF0aCI6InNGdjVQYnhGbXJKQ3BFY1pQYzA0aXNfWTdfOXJUMkk3Z2ZMVlNtMHI4djAifQ.MoMtWxT7igolVcGPY7qe15kyi5DxAz1XaJKlvip3b4H0E7RzwL38UE9u6nv3afMgGxQkOhWHU8tZigxlfk3lg"
}
STEP 3 Combine both "Authorization" and "DPoP" into the header of your /person API request, and you should see something like this in the onscreen logs:
Copy to clipboard
{
"Cache-Control": "no-cache",
"Authorization": "DPoP eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IkFGTW5uS1JXVGFCWUVoTmZFQjZpUTVFckMxeXFHVnlaY2hIOEE3bmxfeU0ifQ.eyJzdWIiOiI5MTUyNjdmMC01OTM5LTAyMzAtNzhlNy1iOGNkYmFhYjg1MTgiLCJqdGkiOiJvMkZaVUpmSFZWVjA3aFpLTFZrc2Yxd0RBYnNUUUtWblFXM3RjZDI5Iiwic2NvcGUiOiJ1aW5maW4gbmFtZSBzZXggcmFjZSBuYXRpb25hbGl0eSBkb2IgZW1haWwgbW9iaWxlbm8gcmVnYWRkIGhvdXNpbmd0eXBlIGhkYnR5cGUiLCJleHBpcmVzX2luIjoxODAwLCJhdWQiOiJodHRwczovL3Rlc3QuYXBpLm15aW5mby5nb3Yuc2cvY29tL3Y0L3BlcnNvbiIsInJlYWxtIjoibXlpbmZvLWNvbSIsImlzcyI6Imh0dHBzOi8vdGVzdC5hcGkubXlpbmZvLmdvdi5zZy9zZXJ2aWNlYXV0aC9teWluZm8tY29tIiwiY2xpZW50Ijp7ImNsaWVudF9pZCI6IlNURzItTVlJTkZPLVNFTEYtVEVTVCIsImNsaWVudF9uYW1lIjoiTXlJbmZvIFNlbGYgVGVzdCBBcHAgR0NDIiwiZW50aXR5X3VlbiI6IlQxNkdCMDAwMkciLCJlbnRpdHlfbmFtZSI6IkdvdlRlY2gifSwiY25mIjp7ImprdCI6ImhHdHN1S3h3UmFMOE1NeDVqVjVUYUluSWpqOFNLS3N3VEVOOGcxaU9FY1EifSwiZXBrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ1c2UiOiJlbmMiLCJraWQiOiI3VGt5TWFqV0JYUlo3aVpmZ3lQUGZmMmdMMzloMlh0ZkpEemNzNXRjZXJNIiwieCI6Ik5mSXhKdWRCTzFfWEQ0RG5oa1ZLUG9uSHV4MExHMTJPM0QtWjJOZnN1RUUiLCJ5IjoiMkhHNmV5SmNFRUJWWlVwMVlsRjU3TFdNbEFJbXlTdU41d1FjZUVybW85OCIsImFsZyI6IkVDREgtRVMrQTI1NktXIn0sImlhdCI6MTY2NzIwMTY4OCwibmJmIjoxNjY3MjAxNjg4LCJleHAiOjE2NjcyMDM0ODh9.0CMpP4Whxk11XTMxg1fz6Srw2HkPiY-t2Tydb8ouQVpCwMNe6DW3Mu6KBdOo00ipa7Nlhw375zwmWAIT-8-3CQ",
"DPoP": "eyJ0eXAiOiJkcG9wK2p3dCIsImp3ayI6eyJrdHkiOiJFQyIsImtpZCI6ImhHdHN1S3h3UmFMOE1NeDVqVjVUYUluSWpqOFNLS3N3VEVOOGcxaU9FY1EiLCJjcnYiOiJQLTI1NiIsIngiOiJMX0F3SklGeDZWUEk1RklIZFBwSnppLVZFNGdkUlhCU3Zld3ktTmhySFFFIiwieSI6IjF0czFnZENpTWhjUHI1WkJPSjNaSHdBY0YtUkJPVVd6MjJGX296SGRjbk0iLCJ1c2UiOiJzaWciLCJhbGciOiJFUzI1NiJ9LCJhbGciOiJFUzI1NiJ9.eyJodHUiOiJodHRwczovL3Rlc3QuYXBpLm15aW5mby5nb3Yuc2cvY29tL3Y0L3BlcnNvbi85MTUyNjdmMC01OTM5LTAyMzAtNzhlNy1iOGNkYmFhYjg1MTgiLCJodG0iOiJHRVQiLCJqdGkiOiJxc21vU21BVzF6WmtCTHNBUEZUWU8xNFQ1Ukl3eWxHQXFueHdCb3ViIiwiaWF0IjoxNjY3MjAxNjg5LCJleHAiOjE2NjcyMDE4MDksImF0aCI6InNGdjVQYnhGbXJKQ3BFY1pQYzA0aXNfWTdfOXJUMkk3Z2ZMVlNtMHI4djAifQ.MoMtWxT7igolVcGPY7qe15kyi5DxAz1XaJKlvip3b4H0E7RzwL38UE9u6nv3afMgGxQkOhWHU8tZigxlfk3lg"
}
Once this is ready, you may call our /person API and receive the JWE response of the data, which requires decoding and decrypting in the next step.
4.2 Response
Response Type: application/json
Copy to clipboard
eyJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiRUNESC1FUytBMjU2S1ciLCJraWQiOiI3VGt5TWFqV0JYUlo3aVpmZ3lQUGZmMmdMMzloMlh0ZkpEemNzNXRjZXJNIiwiZXBrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoibUVaMHhpRmQ4SV9nbERTVDRYWHZaUTgwN2E4X1lpN0ZaYkxmdnhZUEtJZyIsInkiOiJoNEEtOV9tYndJeVQ3UlVnVzNBVV9fQjg2TFYyWUhTWFlZN1l6ekEtX2NjIn19.-tkyW9doM-nvfi5iLIX30livPwFb4Ocpj_sH9lf3EBT_665a4obEiQ.YInOs5ZA_wA0kfAA.ESz3K9C-K7BUtifjT-sLlam7sddzAmpfW0QeF5oDrDYOLJXwgwCYbZCwXP7BBkI0TbccTdatQja76Vs2Y-OWsSDS-AOvg46HWUmUkSnzQAREJ_fxPGhDhDLvmBwLl4Y64zVOHDwZFC9dfnJAH8_2ezM03kqatw1gjs5gmipaicdoGZNA3doy33J6W2uAnjl6eunw47ABlu1PKdizumYnISZjPYWxIGLI3BMSfQSo9arvXT9R7sodhmVMb_KlRG9tnbqazvXwjafRs4B9moT7a2pTNts2hVKZ72Oknl-YpED4pkmx7IoV8CUHU0JIrtAnD_fkZlAl1zUSYtJgy7EXJ11T-UktkBWGzXswQQm913YV0ZYiwBkK80exOoGq-40YTDcFnhAqAJQW3N7Ro2nX4Mk4ujBxtxB-j25rtYmIG1-lU0MPepTzFrTLupzrslkPHyfW8a5LystczDLPH7ryCYUAKw1ex87Wbf784mmkd62QfxLjAhvK3fHh0MA_naOBoIzX89o7B2EjAZ015YJvsIKRPb2JM-Y1_Ll5mFmxttMk17ItjDfcxCqQE9dU_4_X3Z8A6LW0HOSMjrIop-9WvmWKCK3DzpgWw_x4H7dlbTPsOKM7cVnP8_LqNMSmmxjskJeBZ4XMOG9G273RvrZbgA8POS0zESTvkrwULTwPFr4fsfDP8t82WWBzsuwuXXNqE_BE-McfoyZJZ-a6iWbMyp8b3CSrLj5neCYHQSGJ14ZJagfOoz8BgTzqJxUoeQdg6K14bdP2Wdwu32q207al7riw35tFU45WFy8lUuIKURsznadUeyG1GzBJ6Rl7zjVmFmtGReawCbGrFLZDxkHl6520YbDVHqnjHbBX4vnneoISdx3YhSHdd08rHNSOPPOrbpv22bWsLCr-6PKZzzM9XG4J4oloDxwMZgwJ-fmExlCwRml9aywlEArbs0UqLdjC9mtngNb4Sw1kNhUleVzXRD3qkKZj1Zzzei-oHN-LEz9hWVMtAdy-bpuq8eVYt437Td2IQnCMQ-f3hA8FqaASLVlfjrbNm0GwRQpki3s6hA2FlUEXlE3RGyOYB9Z9jyf8AB1WQ9QfWpOPUNKlf8pmqS7f-Ym0EVabTFtTT-QNHXWo5CAQ1RZ7K_sxmiLSiMsE-V6V7DFjq0b7bXPiCFbKAyJW21gC_t_G8Shg7nzXtxKY2YEOCFMOjn-RsnQAWYlJZ9sCpiL3PoueLdK2ouAq9KebqpP-syM8jlwTh6ZrL8k_InYCSZAWvCRdqf85hu4qoKxTFd7biVpeJQ1fQb9sLGHihSMx3_kOOsS-OUctuVy_nElcuFaVy4vGk6bjDetED8egwwQZn3oRtbrQeye0filIYw_hcJyXzwNzGKUox7C8aIV6-Mi4x0fJTQPPJrJyEU4fSJC9auGOi75CWPQOf-Kd8GOpr8vLQ8FULaPB3S1zVfhXN7q08Qcp_MolotPPFfBhn7VMM7ai5JG4vhB-oti3gsih4xaIDiYK98Nitqp_OnY34keiEjzxWL8PQJugTyXiGuM6Gft-Xu07OrOzYC-CqtX7QOUhLSSQefP1HhyvuSAocCvgWQ2Q7EydphmlCJAgzlIwXtePcQ-YKqM_bbJ5TZmD_of4T9-Ab-VwNdgcor_Ro1rq3c6zbzTsKxaJ1SeHRSzIfyfz854TbZd4PiJwERYp4dSt-I-sPW21h90CJXCujS--2QzgVeOkSHlUI94dkl54-ahiKd8UlnU_N24_uVsiVYpqkh2Ouce8uy9FRQAL6ZRh5bOC78GWKQEyMvMDWEZl8myrlSiKWm4OFH65hiBZx6uoNIramaMKQNVZOMFLiTUCOoqJc_Xk-LrNzh7FNdfzP9NgbqfPdwKwVeuy4lWLttYOq2UHXVIU_u4aHEjkUuGVO0O2Fz_Ig_pIyTSIQGkhTC7MQjzWfMTuUCPphh4x7bO74VzqprsN35TxxOVvD9iTpDZ-kg5fJ53j2f5G413q8JmCMHhf3rqX7N8bPTHXlkvHoeCMwc7TMyU4ugJOzxQgMqoO78iWHhr4PxriotwB3vvnvzMsg4fVPRzwUWiD_adBhWB_ZZOnoxQHftb9fmcIP6DGyNne11_4VsuIPmifdSDixBVV6AOk39hkQDbBMQctGPat2TXVo8kl3vg_sgqkTDobccEWT5YnQ3XRpQCrD7V9Z5P9u64_rSeFxz1dBLFHe39sytwFtJT-NzhDAN_5UWyNln5uS-R5WtNARjP5b7W50oQntUql1smZiH3o-xqittFs-QoPeH94D5qtLUpK-XF1fWFJrNaL_GhVBkH0S56fYGfceDs-JZ73AePN5lNbFBVLVuA55QMzBHM_Y8k7zcu6cWIRa15z3UdariVcGXsaurFfTYpP0ABmKtJPbBotEEBWb-N7gvdXuH25MLpEXtqjh6GLXcuRMwIUeQ9mcQKFjh2tJF0jf4kEnMsVs9XtK8pO47owp0TAR1iLre80ryuLcbaSoj_Cm4T5IJORuURKftjfQsoC9NMpPLV8dJrBT0hjv2QgZrQmjyZ1lZwZa1cjVy2_o72epuJsdSgf_aSJ1Pq7ucHnr9WnOmvlwU0IWQ.bjsOSR3XIMI6WMNkJ2gCqg
The response payload from our /person API (for test and production environments) is first signed, then encrypted:
Signing is done using the JWS (JSON Web Signature) format
Encryption is done using the JWE (JSON Web Encryption) Compact Serialization format
Encryption protects the data at rest, while a signed payload means, if necessary, you can pass this signed payload to a 3rd party where they can verify the payload's integrity with our public JWKS.
4.2.1 Decrypt & Verify the Person Response To read the payload, you have to perform the following steps in order:
STEP 1: Decrypt the payload with your application's private key (Reference: JWE)
STEP 2: Validate the decrypted payload signature with Myinfo public key (JWKS URI) (Reference: JWS)
After the above steps, your application can extract the payload in JSON format.
After which, you should see the response as below in the logs.
Copy to clipboard
{
"uinfin": {
"lastupdated": "2022-10-27",
"source": "1",
"classification": "C",
"value": "S6005048A"
},
"name": {
"lastupdated": "2022-10-27",
"source": "1",
"classification": "C",
"value": "ANDY LAU"
},
"sex": {
"lastupdated": "2022-10-27",
"code": "M",
"source": "1",
"classification": "C",
"desc": "MALE"
},
"race": {
"lastupdated": "2022-10-27",
"code": "CN",
"source": "1",
"classification": "C",
"desc": "CHINESE"
},
"nationality": {
"lastupdated": "2022-10-27",
"code": "SG",
"source": "1",
"classification": "C",
"desc": "SINGAPORE CITIZEN"
},
"dob": {
"lastupdated": "2022-10-27",
"source": "1",
"classification": "C",
"value": "1988-10-06"
},
"email": {
"lastupdated": "2022-10-27",
"source": "4",
"classification": "C",
"value": ""
},
"mobileno": {
"lastupdated": "2022-10-27",
"source": "4",
"classification": "C",
"areacode": { "value": "" },
"prefix": { "value": "" },
"nbr": { "value": "" }
},
"regadd": {
"country": { "code": "SG", "desc": "SINGAPORE" },
"unit": { "value": "10" },
"street": { "value": "ANCHORVALE DRIVE" },
"lastupdated": "2022-10-27",
"block": { "value": "319" },
"source": "1",
"postal": { "value": "542319" },
"classification": "C",
"floor": { "value": "38" },
"type": "SG",
"building": { "value": "" }
},
"housingtype": {
"lastupdated": "2022-10-27",
"code": "",
"source": "1",
"classification": "C",
"desc": ""
},
"hdbtype": {
"lastupdated": "2022-10-27",
"code": "115",
"source": "1",
"classification": "C",
"desc": "5-ROOM FLAT (HDB)"
}
}
Once you have decrypted the JWE and verified the JWS, you will get the Person JSON data format and use this data to pre-fill your application form.
Summary
You've successfully used the OAuth2.1 process to get the Person data from the Myinfo test environment. You are now ready to use the same method to integrate your application with Myinfo Production APIs.
Last updated
Was this helpful?