LOGIN WITH “iAM Smart”

Table of Contents

1. Introduction

This is a general walk-through for getting start iAM Smart APIs development of Login with “iAM Smart” use case. 

Developers of Online Service adopting iAM Smart may find this guide useful when designing and developing application flows for login with “iAM Smart” adopting iAM Smart functions.

In this guide we will provide guides on:

  • Setting up your iAM Smart development environment
  • Authentication
  • User link-up First Time Log in
  • User Registration
  • Request QR Page
  • Callback with authCode to Online Service Server
  • Request accessToken & Tokenised ID

2. User Journey

3. Flow

Please find below the sequence diagram for the whole re-authentication:

4. Authentication

4.1 User Journey

4.2 Click login by “iAM Smart”

Online service shall display the following buttons:

Login with iAM Smart

Usage

The button for user to initiate the authentication flow.

Traditional Chinese

智方便登入

Simplified Chinese

智方便登入

English

Login with iAM Smart

Sample Button for Login with iAM Smart

Traditional Chinese

Simplified Chinese

English

Online services is required to add a link / button, “More info” or “了解更多” in the initiation page. The link / button shall be linked to the “iAM Smart” thematic webpage based on language preference of user.  The initiation page refers to the page that initiates the “iAM Smart” service, which user clicks the “iAM Smart” button to initiate the interaction with “iAM Smart” mobile application. 

Language

Link

English 

https://www.iamsmart.gov.hk/en/

Traditional Chinese 

https://www.iamsmart.gov.hk/tc/

Simplified Chinese

https://www.iamsmart.gov.hk/sc/

4.3 Request QR Page

In this step, a user initiates for using iAM Smart at online service application. Online service redirects the user to a webpage hosted by iAM Smart System. Broker page will be shown on the webpage.

Composing Request URL

Parameter

Type

Presence

Description

clientID

String

Required

Online Service client identifier. The clientID will be assigned to Online Service at the initial registration 

responseType

String

Required

value MUST be set to code

source

String

Required

Request initiator. The supported source values can be found in Appendix B of this specification.

redirectURI

String

Required

callback redirect URI. The value should be URL encoded

scope

String

Required

specify the scope of iAM Smart functions (eidapi_auth, eidapi_formFilling,  eidapi_sign or eidapi_fr) to be requested.  The list of scopes and how to request for multiple scopes are described in Section 5.3. The value should be URL encoded.

ticketID

String

Required

(Conditional)

Required only in anonymous form filling or anonymous signing workflows for getting QR page.

lang

String

Optional

Language to display: en-US, zh-HK, or zh-CN.  If this parameter is not specified, zh-HK will be shown.

state

String

Optional

If state parameter is presented in the request message, the same state value will be returned to Online Service during callback. It is used to prevent the CSRF attack. The value of state is defined by Online Service and it should be a secure random string of any length less than or equal to 36 (UUID string length). Only ASCII letters, numbers, underscore and hyphen are accepted.

brokerPage

Boolean

Optional

If brokerPage is set to true, Universal Link (iOS) / App Link (Android) will be leveraged to open iAM Smart Mobile App.  

This feature is useful for Online Service supporting mobile web version while trigger iAM Smart Mobile App or showing QR page automatically. (i.e. Show QR page without detecting whether iAM Smart Mobile App is installed).

The default value is false.

Your request URL should look something like this:

				
					Get
https://<iAM_Smart_domain>/api/v1/auth/getQR
?clientID=Online Service1
&responseType=code
&source=Android_Chrome
&redirectURI=https%3A%2F%2Frp_domain%2Frp_context%2Fcall_back_endpoint
&scope=eidapi_auth%20eidapi_formFlling
&lang=en-US
&state=eb9b7b8eddd5
				
			

If the brokerPage is set to be true, then the following page will be displayed.

Otherwise, the QR page will be displayed, and client need to use “iAM Smart” app to scan the QR code for authorisation.

4.4 Callback with authCode to Online Service Server

After user confirming the authorisation, “iAM Smart” core system will redirect to Online Service callback URL with authCode.

4.4.1 Callback Parameters
ParameterTypePresenceDescription
businessIDString

Required

(Conditional)

businessID will only be returned in anonymous workflows.  businessID is a unique identifier for Online Service to differentiate different request.  Online Service can use the businessID to relate the callback message with the original request.
codeString

Required

(Conditional)

The authorisation code generated by the iAM Smart System. The authorisation code will be expired in 1 minute after issued. Online Service MUST NOT use the authorisation code more than once. 

An error message will be returned if an authorisation code is expired or re-used.

stateStringOptionalIf the state parameter has been presented in the request, the same state value will be returned during callback. It is used to prevent the CSRF attack. The value of state is defined by Online Service and it should be a secure random value. 
error_codeString

Requried

(Conditional)

Return error code when exception.

The callback should look something like this:

				
					GET
https://<call_back_endpoint>
?code=0ad186353c424c64897fcc00445c9ba1
&state=eddd527b6
				
			

4.5 Request accessToken & Tokenised ID

After obtaining the authCode from “iAM Smart” core system, Online Service can request accessToken and Tokenised ID from “iAM Smart” core system with authCode.

4.5.1 Composing Request Body
ParameterTypePresenceDescription
businessIDStringRequiredbusinessID is a unique identifier for Online Service to differentiate different request, Online Service can use the businessID to relate the callback message with the original request. 
stateStringOptionalIf state parameter is present in the request message, the same state value will be returned. It is used to prevent the CSRF attack. The value of state is defined by Online Service and it should be a secure random value.
isPassedStringRequiredRe-authentication result. true – same person, otherwise false.

Upon success you should receive the encrypted response:

				
					POST
https://<iAM_Smart_domain>/api/v1/auth/getToken
// Request Headers
clientID: "edae2e2529ff46228af1e4d18c8405d1"
signatureMethod: "HmacSHA256"
signature: "5X42Y1B7MEd8Mm%2BonwjiQz9VCZkkrntADskXsYntavU%3D"
timestamp: 1557048906183
nonce: "e893647dc4204eb9b7b8eddd527b687c"
// Request Body
{
"code": "xxxa42e76bf4cb0846a68e6d83d6096",
"grantType": "authorization_code"
}
				
			

Encryption

To better protect the data in transit, an additional layer of data encryption will be applied to all APIs POST request (except the one that Online Service request for getting symmetric encryption key)

Info
To encrypt the data, a Content Encryption Key is required, please refer to iAM Smart API Specification 6.3.1.1 or online mockup API. 

In this case we will use a mock-up Content Encryption Key (CEK), please find below a base64-encoded mock CEK:

pvD2Zc1mf7tKVh17JOftmzyTaDyVmcULg92nB9qeEoQ=

You may refer to the pseudo code below for the encryption implementation:

				
					private static final String AES_GCM_NOPADDING = "AES/GCM/NoPadding";
/**
 * AES GCM encryption
 * @param contentByte - Bytes of content to be encrypted
 * @param key - CEK (AES 256)
 * @return
 */
public static String encrypt(byte[] contentByte, byte[] key) {
	SecretKeySpec skeySpec = new SecretKeySpec(key, AES);
	byte[] encrypted = null;
	try {
		SecureRandom secureRandom = new SecureRandom();
		byte[] iv = new byte[12]; 
		// do not reuse iv with the same key
		secureRandom.nextBytes(iv);

		Cipher cipher = Cipher.getInstance(AES_GCM_NOPADDING);
		GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv); 
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec, parameterSpec);
		encrypted = cipher.doFinal(contentByte);
		
		ByteBuffer byteBuffer = ByteBuffer.allocate(
			4 + iv.length + encrypted.length);
		byteBuffer.putInt(iv.length);
		byteBuffer.put(iv);
		byteBuffer.put(encrypted);
		byte[] cipherMessage = byteBuffer.array();
		
		return Base64Util.base64Encode(cipherMessage);
	} catch (NoSuchAlgorithmException | NoSuchPaddingException 
		| InvalidKeyException | InvalidAlgorithmParameterException 
		| IllegalBlockSizeException | BadPaddingException e) {
		log.error("Encryption error: {}", e); 
		throw new IAMSmartException(e);
	}
}
				
			

Note

Please note that the pseudo code ONLY aims for reference and shall provide NO SUPPORT for any issue on the pseudo code.

Please find below an example of base64-encoded IV:

vM7EArooK0hCCX8E

If you use the above json and encrypt with the above CEK and IV, concatenated and base64 encoded, you should get the following result:

AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA

Now put it in the value of JSON name/value pair called “content” as the request body:

				
					{"content": "AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA" }
				
			
4.5.2 Composing Common Request Header
ParameterTypePresenceDescription
clientIDStringRequiredOnline Service client identifier. The clientID will be assigned to online service at the initial registration 
signatureMethodStringRequired

signature algorithm:

HmacSHA256 

timestampLongRequired

The timestamp is the request submit time expressed in the number of milliseconds since January 1, 1970 00:00:00 GMT. It is used to prevent replay attack.

The value MUST be a positive integer and equal or greater than the timestamp used in previous requests.

nonceStringRequired

A nonce is a random string, uniquely generated for each request by online service. It is used to prevent replay attack.

A nonce can be an ASCII string of any length less than or equal to 36 (UUID string length) as long as the uniqueness requirement is met.

signatureStringRequiredIt is a signature of the submitted data. Online service uses clientSecret to sign the concatenated string of clientID, signatureMethod, timestamp, nonce, and request body to get the signature. The pseudo code to generate the signature is shown at below.

Online Service uses clientSecret to sign the concatenated string of ClientID, signatureMethod, timestamp, nonce and request body to get the signature.

In this case, we will use the following parameters for signature generation:

clientID: clientID20220817demo 

clientSecret: clientSecret20220817demo 

signatureMethod: HmacSHA256 

timestamp: 1660721425291 

nonce: nonce20220817

The concatenated string of ClientID, signatureMethod, timestamp, nonce and request body should be as follow:

				
					clientID20220817demoHmacSHA2561660721425291nonce20220817{"content": "AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA"}
				
			

You may refer to the pseudo code below for the signature generation:

				
					message = clientID + signatureMethod + timestamp + nonce + request_body
sha256_HMAC = Mac.getInstance("HmacSHA256");
secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
sha256_HMAC.init(secret_key);
hash = Base64.encodeBase64String(sha256_HMAC.doFinal(message.getBytes()));
// If the hash needs to be URL encoded
signature = URLEncoder.encode(hash, "UTF-8")
				
			

With the parameters provided you should get the following result:

17uX5GHbU7x1mz1czXBLifRqOJ%2BwzZG105bj%2FWpuwU0%3D

Now construct the request header with all the parameters:

				
					{ 
"clientID": "clientID20220817demo", 
"signatureMethod": "HmacSHA256", 
"timestamp": 1660721425291, 
"nonce": "nonce20220817", 
"signature": "17uX5GHbU7x1mz1czXBLifRqOJ%2BwzZG105bj%2FWpuwU0%3D" 
}
				
			

The completed request should be like following:

				
					[Post] https://<iAM_Smart_domain>/api/v1/auth/getToken
// Request Header
{ "clientID": "clientID20220817demo", 
"signatureMethod": "HmacSHA256", 
"timestamp": 1660721425291, 
"nonce": "nonce20220817", 
"signature": "17uX5GHbU7x1mz1czXBLifRqOJ%2BwzZG105bj%2FWpuwU0%3D" }

// Request Body
{"content": "AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA" }
				
			

Upon success you should receive the encrypted response:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS",
“secretKey”:"AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA",
"content":"AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA"
}
				
			
Note

Noted the secretKey used for encryption is also provided in the response body, this is for when the request hits the time of updating the CEK, an old CEK is used to

Encrypted the request, in this scenario online service may use the provide secretKey in the request body for decryption.

Decryption

The structure of the encrypted content of response body is the same as the encrypted request body:

4 bytes IV length + IV + ciphertext

To decrypt the encrypted content, you will have to locate the following data:

  • 4 bytes IV length
  • IV
  • ciphertext
  • authTag (if necessary)

You may refer to the pseudo code below for the decryption implementation:

				
					private static final String AES_GCM_NOPADDING = "AES/GCM/NoPadding";
/**
 * AES GCM encryption
 * @param contentByte - Bytes of content to be encrypted
 * @param key - CEK (AES 256)
 * @return
 */
public static String encrypt(byte[] contentByte, byte[] key) {
	SecretKeySpec skeySpec = new SecretKeySpec(key, AES);
	byte[] encrypted = null;
	try {
		SecureRandom secureRandom = new SecureRandom();
		byte[] iv = new byte[12]; 
		// do not reuse iv with the same key
		secureRandom.nextBytes(iv);

		Cipher cipher = Cipher.getInstance(AES_GCM_NOPADDING);
		GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv); 
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec, parameterSpec);
		encrypted = cipher.doFinal(contentByte);
		
		ByteBuffer byteBuffer = ByteBuffer.allocate(
			4 + iv.length + encrypted.length);
		byteBuffer.putInt(iv.length);
		byteBuffer.put(iv);
		byteBuffer.put(encrypted);
		byte[] cipherMessage = byteBuffer.array();
		
		return Base64Util.base64Encode(cipherMessage);
	} catch (NoSuchAlgorithmException | NoSuchPaddingException 
		| InvalidKeyException | InvalidAlgorithmParameterException 
		| IllegalBlockSizeException | BadPaddingException e) {
		log.error("Encryption error: {}", e); 
		throw new IAMSmartException(e);
	}
}
				
			

You should get the following result:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS",
  "content": {
    "accessToken": "0ad186353c424c64897fcc00445c9ba1",
    "tokenType": "Bearer",
    "issueAt": 1557053922938,
    "expiresIn": 14400000, // 4 hours
"openID": "liR14%2BvX%2F5hSum5uf4ERczu0KcDnIJA5BM7FoM1ag9c%3D",
"lastModifiedDate": 1560849218006,
    "userType": "sign",
    "scope": "eidapi_auth eidapi_formFilling"
  }
}
				
			

5. User link-up First Time Log in

After getting the accessToken and tokenisedID from “iAM Smart” core system, Online Service need to check if current tokenisedID is existed in Online Service Database system and it means the link-up process has been done. If it is linked up with “iAM Smart” account, then login successfully. Otherwise, user link-up first time login process

If the Online Service uses the HKID number for user identification, then the following user link-up first time login process can be made as a reference.

5.1 User Journey

5.2 Consent Page for requesting “iAM Smart” profile

Online Service shall display a consent page before requesting the user’s “iAM Smart” profile data. The page shall explain clearly to user why such data is requires during authentication process and avoid requesting more HKIC data items than necessary. In this case, only HKID profile should be requested.

Information for Consent Page
Traditional Chinese授權「智方便」提供個人資料
Simplified Chinese授权「智方便」提供个人资料
EnglishAuthorise “iAM Smart” to provide personal information
Instructions
Traditional Chinese

歡迎你透過「智方便」登入 <你的服務名稱>

這是你首次透過「智方便」登入<你的服務名稱>,系統將要求「智方便」提供以下個人資料,以便為您連結原有帳號/開立新帳號:

– 英文姓名

– 中文姓名

– 出生日期

– 性別

– 身份證號碼

pastedGraphic.png

Simplified Chinese

欢迎你透过「智方便」登入 <你的服务名称>

这是你首次透过「智方便」登入<你的服务名称>,系统将要求「智方便」提供以下个人资料,以便为您连结原有帐号/开立新帐号:

– 英文姓名

– 中文姓名

– 出生日期

– 性别

– 身份证号码

pastedGraphic_1.png

English

Welcome to log in to <Online Service Name> through “iAM Smart”

This is the first time you have logged in to <Online Service Name> through “iAM Smart”. The system will request the following personal information via “iAM Smart” for linking up your existing account or creating a new account:

– English Name

– Chinese Name

– Gender

– HKID number 

pastedGraphic_2.png

5.3 Require Profile

Composing Request Body and Request Header

Parameter

Type

Presence

Description

businessID

String

Required

businessID is a unique identifier for Online Service to differentiate different request. It should be ASCII string with length less than or equal to 36 chars.

accessToken

String

Required

accessToken value

openID

String

Required

Tokenised ID value

source

String

Required

Request initiator. The supported source values can be found in Appendix B of this specification.

redirectURI

String

Required

callback URI.

state

String

Optional

If state parameter is presented in the request message, the same state value will be returned to Online Service during callback. It is used to prevent the CSRF attack. The value of state is defined by Online Service and it should be a secure random string of any length less than or equal to 36 (UUID string length). Only ASCII letters, numbers, underscore and hyphen are accepted.

profileFields

Array

Required

Specify the profile fields to be requested. The available profileFields are as follows:

profileFields Description

idNo ID number

enName English name

chName Chinese name

birthDate Date of birth

gender gender

Your request body should look something like this:

				
					// How to generate shared common parameters is described in 4.5.2
POST  
https://<iAM_Smart_domain>/api/v1/auth/profile/initiateRequest
// Request Headers
clientID: "edae2e2529ff46228af1e4d18c8405d1"
signatureMethod: "HmacSHA256"
signature: "5X42Y1B7MEd8Mm%2BonwjiQz9VCZkkrntADskXsYntavU%3D"
timestamp: 1557048906183
nonce: "e893647dc4204eb9b7b8eddd527b687c"
// Request Body
{
 "businessID": "bbb8aae57c104cda40c93843ad5e6db8",
"accessToken": "xxxa42e76bf4cb0846a68e6d83d6096",
"openID": "liR14%2BvX%2F5hSum5uf4ERczu0KcDnIJA5BM7FoM1ag9c%3D",
"source": "Android_Chrome",
"redirectURI": "https://<rp_domain>/<rp_context>/<call_back_endpoint>",
"state": "eddd527b6",
" profileFields": ["idNo", "enName"]
}
				
			

Encryption

As an additional layer of data encryption will be applied to all APIs POST request, please follow section 4.5.1.1 to construct the encrypted request header and request body.

Upon success you should receive the encrypted response:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS",
“secretKey”:"AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA",
"content":"AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA"
}
				
			

Note

Noted the secretKey used for encryption is also provided in the response body, this is for when the request hits the time of updating the CEK, an old CEK is used to encrypt the request, in this scenario online service may use the provided secretKey in the request body for decryption.

Decryption

Please refer to section 4.5.2.1 for decryption of the content data, and you should get the following result:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS",
  "content": {
    "authByQR": true
  }
}
				
			

5.4 Instruction Page for requesting “iAM Smart” Profile

After Online Service sends the getting “iAM Smart” profile data request to “iAM Smart” system, Online Service is required to instruct to open the “iAM Smart” app in his/her mobile phone. Please refer to the table below for different scenarios.

 

Same Device

Different Device

Information

Traditional Chinese

授權「智方便」提供個人資料

Simplified Chinese

授权「智方便」提供个人资料

English

Authorise “iAM Smart” to provide personal information

Instructions

Traditional Chinese

請按照以下步驟:

  1. 開啟你手機上的「智方便」應用程式
  2. 點擊「繼續授權」
  3. 點擊「確定」以完成授權

請按照以下步驟:

  1. 開啟你手機上的「智方便」應用程式

  1. 點擊「繼續授權」
  2. 點擊「確定」以完成授權

Simplified Chinese

请按照以下步骤:

  1. 开启你手机上的「智方便」应用程式
  2. 点击「继续授权」
  3. 点击「确定」以完成授权

请按照以下步骤:

  1. 开启你手机上的「智方便」应用程式

  1. 点击「继续授权」
  2. 点击「确定」以完成授权

English

Please follow the steps below:

  1. Open “iAM Smart” mobile app in your mobile device
  2. Tap on “To authorise”
  3. Tap on “OK” to confirm the authorisation 

Please follow the steps below:

  1. Open “iAM Smart” mobile app in your mobile device

  1. Tap on  “To authorise”
  2. Tap on “OK” to confirm the authorisation 

Example

Remark: The font colour of step 1 above must be green (#2B7366) for consistency with “iAM Smart”. 

5.5 Callback to Receive iAM Smart Profile

After client authorizing the getting profile request, “iAM Smart” core system will redirect to Online Service callback URL with “iAM Smart” profile data.

Callback Parameters

Parameter TypePresenceDescription
businessID StringRequiredbusinessID is a unique identifier for Online Service to differentiate different request.  Online Service can use the businessID to relate the callback message with the original request.
state StringOptionalIf the state parameter has been present in the request message, the exact value of state will be returned. It is used to prevent the CSRF attack. The value of state is defined by Online Service and it should be a secure random value.
idNo JSON ObjectOptionalID number
enName JSON ObjectOptionalEnglish name
chName JSON ObjectOptionalChinese name
birthDate StringOptionalDate of birth
gender StringOptionalgender
chNameVerified StringOptionalImmD characters code point will be returned to Online Service if Chinese name verified.

Upon success you should receive the encrypted response:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS",
“secretKey”:"AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA",
"content":"AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA"
}
				
			

Note

Noted the secretKey used for encryption is also provided in the response body, this is for when the request hits the time of updating the CEK, an old CEK is used to encrypt the request, in this scenario online service may use the provided secretKey in the request body for decryption.

Decryption

Please refer to section 4.5.2.1 for decryption of the content data, and you should get the following result:

				
					POST 
https://<rp_domain>/<rp_context>/<call_back_endpoint>
// Callback Body
{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS",
  "content": {
    "businessID": "3e47be25-66a6-43fb-89f6-7e2dd138aff8",
"state": "unesidkd",
    "idNo": {
        "Identification": "A123456",
        "CheckDigit": "A"
    },
    "enName": {
        "UnstructuredName": "SAN, Chi Nan"
    },
    "chName": {
        "ChineseName": "申智能"
},
"birthDate": "19960000",
"gender": "M",
"chNameVerified": "申智能"
  }
}
				
			

After successfully getting the HKID from “iAM Smart” profile, Online Service then should handle the HKID matching process, if it is matched, then should bind the Online Service account with “iAM Smart” account by the tokenisedID. After binding successfully, the user link-up first time log in successfully page should be displayed.

Note

For each Online Service, each user will have a unique tokenisedID. When it comes to another Online Service, the tokenisedID will be different.

6. User Registration

If the user cannot be matched with HKID which means that current user is not a user in Online Service system, then the user registration process should be processed.

The following scenario can be made as a reference when the Online Service use “iAM Smart” Form Filling function to fill the input for personal data of the user. (eg. Name, Gender, Email, Phone Number and so on.)

6.1 User Journey

6.2 Flow

Please find below the sequence diagram of the whole form filling process:

6.3 Click “iAM Smart” Button in initiation page

Online Service shall display one of the following button depends on the scenario:

Form Filling button 

Usage

The button for user to initiate the authorisation flow.

With “iAM Smart” profile

No

Yes

(For user verification purpose)

Button Description

Traditional Chinese

智方便填表通

智方便個人資料

Simplified Chinese

智方便填表通

智方便个人资料

English

Form Filling with iAM Smart e-ME

Personal Data from iAM Smart

Sample Button

Traditional Chinese

Simplified Chinese

English

Tip

Please note that the request shall be initiated after the user clicked the “Form Filling with iAM Smart e-Me” or “Personal Data from iAM Smart” button.

Without profileFields

With profileFields

If only eMeFields is required in this request, online service shall use “Form Filling with iAM Smart e-ME” and no consent page is required

Online Service shall display a consent page before calling the API for form filling to get the “iAM Smart” profile data. The page shall clearly explain to user why such data are required for the business operations (e.g. account activation, account creation, etc.) and avoid requesting more HKIC data items than necessary.

For Content page and More info link, please refer to section 1.3 and section 1.4.

6.4 Submit “Request Form Filling” with access token, tokenized ID

6.4.1 Composing Request Body

Parameter

Type

Presence

Description

businessID

String

Required

businessID is a unique identifier for Online Service to differentiate different request. It should be ASCII string with length less than or equal to 36 chars. 

accessToken

String

Required

accessToken value

openID

String

Required

Tokenised ID value

source

String

Required

Request initiator. The supported source values can be found in Appendix B of this specification.

redirectURI

String

Required

callback URI.

state

String

Optional

If state parameter is presented in the request message, the same state value will be returned to Online Service during callback. It is used to prevent the CSRF attack. The value of state is defined by Online Service and it should be a secure random string of any length less than or equal to 36 (UUID string length). Only ASCII letters, numbers, underscore and hyphen are accepted.

formName

String

Optional

The name of the form should be encoded in Unicode. The maximun length can be found in part C of the Appendix in this specification.

formNum

String

Optional

The number of the form should be encoded in Unicode. The maximun length can be found in part C of the Appendix in this specification.

formDesc

String

Optional

The description of the form should beencoded in Unicode. The maximun length can be found in part C of the Appendix in this specification.

eMEFields

Array

Required

(Conditional)

Specify the e-ME fields to be requested. If eMEFields and the following profileFields are not provided or are empty arrays, the HTTP code 200 with error code D20002 (empty parameter {eMEFields,profileFields}) will be returned.

The available eMEFields are as follows:

eMEFields Description

idNo ID number

prefix prefix

enName English name

chName Chinese name

birthDate Date of birth

gender gender

maritalStatus marital status

homeTelNumber home telephone number

officeTelNumber office telephone number

mobileNumber mobile number

emailAddress email address

residentialAddress residential address

postalAddress postal address

educationLevel education level

addressDocInfo provider name, retrieval date, owner name and  address information related to an e-bill 

addressDocFile e-bill from an address data provider

profileFields

Array

Required

(Conditional)

Specify the profile fields to be requested. If profileFields and the above eMEFields are not provided or are empty arrays, the HTTP code 200 with error code D20002 (empty parameter {eMEFields,profileFields}) will be returned.

The available profileFields are as follows:

profileFields Description

idNo ID number

enName English name

chName Chinese name

birthDate Date of birth

gender gender

You request body should look something like this:

				
					https://<iAM_Smart_domain>/api/v2/account/formFilling/initiateRequest
// Request Headers
clientID: "edae2e2529ff46228af1e4d18c8405d1"
signatureMethod: "HmacSHA256"
signature: "5X42Y1B7MEd8Mm%2BonwjiQz9VCZkkrntADskXsYntavU%3D"
timestamp: 1557048906183
nonce: "e893647dc4204eb9b7b8eddd527b687c"
// Request Body
{
 "businessID": "bbb8aae57c104cda40c93843ad5e6db8",
"accessToken": "xxxa42e76bf4cb0846a68e6d83d6096",
"openID": "liR14%2BvX%2F5hSum5uf4ERczu0KcDnIJA5BM7FoM1ag9c%3D",
"source": "Android_Chrome",
"redirectURI": "https://<rp_domain>/<rp_context>/<call_back_endpoint>",
"state": "eddd527b6", 
"formName": "Example Account Registration Form",
 "formNum": "APP0001",
 "formDesc": "Example form description",
 "profileFields": ["idNo", "enName", "gender", "chName", "birthDate"],
 "eMEFields": ["mobileNumber", " emailAddress", "addressDocInfo"]
}
				
			
6.4.2 Encryption

As an additional layer of data encryption will be applied to all APIs POST request, please follow section 4.5.1.1 to construct the encrypted request header and request body.

Upon success you should receive the encrypted response:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS",
“secretKey”:"AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA",
"content":"AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA"
}
				
			

Note

Noted the secretKey used for encryption is also provided in the response body, this is for when the request hits the time of updating the CEK, an old CEK is used to encrypt the request, in this scenario online service may use the provided secretKey in the request body for decryption.

6.4.3 Decryption

Please refer to section 1.2 for decryption of the content data, and you should get the following result:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS",
  "content": {
    "authByQR": true
  }
}
				
			
6.4.4 Acknowledge Form Filling request
6.4.5 Callback with authorized Form Filling Result

After user confirming the authorisation, “iAM Smart” core system will redirect to Online Service callback URL with authCode.

Callback Parameters

Parameter

Type

Presence

Description

businessID

String

Required

businessID is a unique identifier for Online Service to differentiate different request. Online Service can use the businessID to relate the callback message with the original request.

state

String

Optional

If the state parameter has been present in the request message, the exact value of state will be returned. It is used to prevent the CSRF attack. The value of state is defined by Online Service and it should be a secure random value.

idNo

JSON Object

Optional

HKIC number

prefix

String

Optional

prefix

enName

JSON Object

Optional

English name

chName

JSON Object

Optional

Chinese name

birthDate

String

Optional

Date of birth

gender

String

Optional

gender

maritalStatus

String

Optional

marital status

homeTelNumber

JSON Object

Optional

home telephone number

officeTelNumber

JSON Object

Optional

office telephone number

mobileNumber

JSON Object

Optional

mobile number

emailAddress

String

Optional

email address

residentialAddress

JSON Object

Optional

residential address

postalAddress

JSON Object

Optional

postal address

educationLevel

String

Optional

education level

chNameVerified

String

Optional

ImmD characters code point will be returned to Online Service if Chinese name verified.

addressDocInfo

JSON Object

Optional

the data related to the obtained e-bill, including the provider name, retrieval date, owner name, service address and postal address. The sub-field lastRetrievalDate refers to the date and time at which iAM Smart obtained the e-bill. The schema of sub-fields is given in Appendix A.

addressDocFile

JSON Object

Optional

the e-bill obtained from an address data provider. Sub-fields include the PDF e-bill file (docFile), the SHA256 hash (docHash) and the bill date of the e-bill (billDate). The schema of sub-fields is given in Appendix A.

Upon success you should receive the encrypted response:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS",
“secretKey”:"AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA",
"content":"AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA"
}
				
			
Note
Noted the secretKey used for encryption is also provided in the response body, this is for when the request hits the time of updating the CEK, an old CEK is used to encrypt the request, in this scenario online service may use the provided secretKey in the request body for decryption.

Decryption

Please refer to section 1.2 for decryption of the content data, and you should get the following result:

				
					POST 
https://<rp_domain>/<rp_context>/<call_back_endpoint>
// Callback Body
{
    "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
    "code": "D00000",
    "message": "SUCCESS",
"content": {
    "businessID": "2YotnFZFEjr1zCsicMWpAA",
        "idNo": {
            "Identification": "A123456",
            "CheckDigit": "A"
        },
        "prefix": "Mr",
        "enName": {
            "UnstructuredName": "SAN, Chi Nan"
        },
        "chName": {
            "ChineseName": "申智能"
        },
        "chNameVerified": "申智能",
        // May be 19960000 or 19960100
        "birthDate": "19960128",
        "gender": "M",
        "maritalStatus": "S",
        "homeTelNumber": {
            "CountryCode": "852",
            "SubscriberNumber": "98765432"
        },
        "officeTelNumber": {
            "CountryCode": "1",
            "SubscriberNumber": "123456"
        },
        "mobileNumber": {
            "CountryCode": "1",
            "SubscriberNumber": "98765432"
        },
				
			
6.4.6 Display/Fill the form Filling request

When an online service adopts “iAM Smart” form filling, the fields filled with data from “iAM Smart” shall be marked with a tag of “iAM Smart”*.

The fields filled with data from “iAM Smart” profile shall not be editable.

The “iAM Smart” tag for the field filled with data from “iAM Smart” or “e-ME” shall be removed once the user modifies the filled data in the form.

without profileFields

With profileFields

  

After successfully getting all the information needed to create Online Service account, Online Service then can help the client to create the account and auto link up with iAM Smart account. Online Service should pop up the page to remind client account has been created successfully and client can use “iAM Smart” for future login.