Sequence Diagram
You need to provide the following information on Krungthai Developer Console to receive the client ID and client secret.
Remarks:
Once registered, you will receive this following information for API integration.
| Scope (For initAuth) | Open API Scope Name | Title (Display on Consent Screen) | Get Customer Profile Object Field | Get Customer Profile Subfield |
|---|---|---|---|---|
|
openid offline |
Anonymous ID | - | - | |
| paotangid.citizen | National ID | เลขบัตรประชาชน | cid | - |
| paotangid.title | Title (TH) | คำนำหน้าชื่อ | title | - |
| paotangid.fullname_th | Full name (TH) | ชื่อ-นามสกุล (ภาษาไทย) | fullNameTh |
- thaiFirstName - thaiMiddleName - thaiLastName |
| paotangid.fullname_en | Full name (EN) | ชื่อ-นามสกุล (ภาษาอังกฤษ) | fullNameEn |
- engFirstName - engMiddleName - engLastName |
| paotangid.gender | Gender | เพศ | gender | - |
| paotangid.birthdate | Date of birth | วัน เดือน ปีเกิด | birthDate | - |
| paotangid.legal_address | Registered address | ที่อยู่ตามบัตรประชาชน | legalAddress |
- address - subDistrict - subDistrictCode - district - districtCode - stateProv - stateProvCode - postalCode - country - phoneNo |
| paotangid.mailing_address | Mailing address | ที่อยู่ปัจจุบัน | mailingAddress |
- address - subDistrict - subDistrictCode - district - districtCode - stateProv - stateProvCode - postalCode - country - phoneNo |
| paotangid.office_address | Work address | ที่อยู่สถานที่ทำงาน | officeAddress |
- officeName - address - subDistrict - subDistrictCode - district - districtCode - stateProv - stateProvCode - postalCode - country - phoneNo - phoneExt |
| paotangid.work_profile | Work profile | ข้อมูลการทํางาน | workProfile |
- occupationCode - occupationValue - occupationGroup - occupationGroupValue - subOccupationGroup - subOccupationGroupDesc - salary - salaryValue |
| paotangid.mobile | Mobile phone number | เบอร์มือถือ | mobileNo | - |
| paotangid.email | Email address | อีเมล | - |
When a user clicks ‘Log in with Paotang’ or any other business logic on your application, your application will redirect to Paotang application. Now, the user is in the process of authorization, you can refer to the flow as shown in the example below.
Your application needs to call ‘Initialize Authentication API’ with the parameters specified below. After that, you will receive a deep link URL from the API response. You can use this URL to launch Paotang application for authentication. Please refer to the API description and example code to open the deep link flow below.
| Parameter | Type | Required | Description |
|---|---|---|---|
| client_id | string | Required | The client ID is obtained once you have created your application in Krungthai Developer Console. |
| redirect_uri | string | Required | The redirect URI is the URI you register for your application. The value provided in this field must match the URI you specify in ‘redirect_uri’ field when creating your application in Krungthai Developer Console. |
| response_type | string | Required | The response type is used to specify the type of response that you desire to get from the Authorization Server during the authentication and authorization process. It indicates how your application expects to receive user identity and access information. You need to specify ‘code’ for using App-to-App flow. |
| scope | array | Required | Permissions requested from the user. Provide each scope as a separate string element of the array—for example: ["openid", "offline"]. The full list of valid values is shown in the About data scope table. |
| state | string | Required | A unique alphanumeric string (minimum 8 characters) or UUID is used to prevent cross-site request forgery. When the response is successful, this value will return to your redirect URL. Your application should generate a unique random value for each login session. |
| acr | string | Optional | The acr value is used to specify required authentication methods during the authentication process.
If you require only PIN authentication, enter 'PIN'. If you require both PIN authentication and facial comparison, enter 'PIN_FACECMP'. |
curl --location --request POST '{{baseUrl_paotangAuth}}/oauth2/app2app/auth' \
--header 'Content-Type: application/json' \
--data-raw '{
"client_id": "{client_id}",
"redirect_uri": "yourapp://{redirect_url}",
"response_type": "code",
"scope": [
"offline",
"openid",
],
"state": "randomstate"
}'
| Parameter | Type | Required | Description |
|---|---|---|---|
| deeplinkURL | string | Required | The deep link URL will direct to Paotang application. You need to build your application to open this URL. |
{
"deeplinkUrl": "{the_deeplink}"
}
| Property | Type | Required | Description |
|---|---|---|---|
| error | string | Required | An error code |
| error_description | string | Required | A description of an error |
| state | string | Required | A unique alphanumeric string or UUID is used to prevent cross-site request forgery. When the response is successful, this value will return to your redirect URL. Your application should generate a unique random value for each login session. The value must not be longer than 8. |
{
"error": "invalid_scope",
"error_description": "The requested scope is invalid, unknown, or malformed. The OAuth 2.0 Client is not allowed to request scope.",
"state": "thisisstate"
}
let urlString: String = unwrapped(deeplinkUrl, with: "")
guard let url = URL(string: urlString) else { return }
UIApplication.shared.open(url)
private fun openBrowserByUrl(deeplinkUrl: String) {
val intent = Intent(Intent.ACTION_VIEW,Uri.parse(deeplinkUrl))
startActivity(intent)
}
Note: CFBundleURLSchemes is your schemes name, for example “appchemename”
User authorization is handled directly by Paotang application.
Applications that support Paotang Authentication don’t have to implement the authorization process themselves.
Developers specify the information they would like to access in the scope parameters, and users are asked to authorize those requests.
When creating your application, you should consider the possibility that users may not be granted the permissions you specify in the initialized authorization.
The consent screen may not always be shown
If the user has already granted the permission, the consent screen will not be displayed.
After the user finishes the authorization process with Paotang application, they will be redirected to your application with an authorization code.
This authentication system will be sent back an authorization code (which will be used to obtain an access token to further access APIs) to your system via redirect URL. So, you need to prepare a redirect URL by enabling deep link in your application with parameters called code. Here are some example steps for preparing this.
Steps
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>$(BUNDLE_ID)</string>
<key>CFBundleURLSchemes</key>
<array>
<string>appschemename</string>
</array>
</dict>
</array>
AndroidManifest.xml adds intent filters for incoming links.
// Example url : appschemename://
// AndroidManifest.xml
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="appschemename" />
</intent-filter>
Once the user has completed the authorization steps, they will receive a redirect URL with these query parameters.
| Parameter | Type | Description |
|---|---|---|
| code | string | An authorization code used to obtain an access token, remains valid for 10 minutes, and can only be used once. |
| state | string | A unique alphanumeric string used to prevent cross-site request forgery. You should verify that the state matches the value of the state parameter given to the authorization URL. |
| scope | string | Permissions requested by the user |
partnerapp://{redirect_url}?code=wDXuLe3HqtS5cEiUd8mgdyGdW03qeVAyofcwF2sdtwg.4bePd6mVmmfOAacp
-iasRWJNGujhI7dR4yhE-IllW8E&scope=openid+offline&state=thisisstate
The user will receive an error response if they decline to grant the permissions requested by your application. Then, they are redirected to the redirect URL with these query parameters.
| Parameter | Type | Required | Description |
|---|---|---|---|
| error | string | Required | An error code |
| error_description | string | Optional | A description of an error |
| state | string | Optional | A unique alphanumeric string used to prevent cross-site request forgery. You should verify that the state matches the value of the state parameter given to the authorization URL. |
scheme://yourapp/{redirect_url}?error=access_denied&error_description=The+resource+owner+denied+the+request.&state=thisisstate
| Error | Description | Note |
|---|---|---|
| invalid_scope |
- The requested scope is invalid, unknown, or malformed. The OAuth 2.0 Client is not allowed to request scope. - The request is missing a required parameter, includes an invalid parameter value, consists of a parameter more than once, or is otherwise malformed. The requested audience ‘hello-world’ has not been whitelisted by the OAuth 2.0 Client. |
Occurs when a scope request is invalid. |
| request_forbidden | The request is not allowed. | Occurs when something about security goes wrong during the process. |
| invalid_client | Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method). The requested OAuth 2.0 Client does not exist. | Occurs when client ID on authentication request is invalid. |
| unsupported_response_type | The client is not allowed to request response type 'code' because the authorization server does not support obtaining a token using this method. | Occurs when response type on authentication request is invalid. |
| invalid_state | The state is missing or does not have enough characters, and is therefore considered to be too weak. Request a parameter ‘state’, consisting of more than 8 characters, to ensure sufficient entropy. | Occurs when state or something about security goes wrong during the process. |
| user_cancel | A user cancels the flow during the process. | Occurs when a user cancels flow by clicking some buttons (e.g., the close button) during the process. |
| unknown_error | An unknown error has occurred. | Occurs when the root cause cannot be specified. |
| invalid_grant | The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, issued to another client, or does not match the redirect URI used in the authorization request. | Occurs when the refresh token expires. |
| service_unavailable | The server cannot process the authentication at the moment. Please try again later. | Occurs when something goes wrong during the process. |
To obtain an access token, ensure that the state parameters received alongside the authorization code from Paotang application matches the one you specify during user authentication and the authorization request.
| Parameter | Type | Required | Description |
|---|---|---|---|
| code | string | Required | A code obtained from redirect URL. |
| grant_type | string | Required | The way an application obtains an access token. You need to specify ‘authorization_code’ for using app-to-app flow. |
| redirect_uri | string | Required | The redirect URI used during initiate authentication request |
| client_id | string | Required | The client ID obtained from creating an application |
| client_secret | string | Required | The client secret obtained from creating an application |
| state | string | Required | The state used during initiate authentication request |
| scope | string | Required | The scopes requested from the user |
curl --location --request POST '{{baseUrl_paotangAuth}}/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'code={your authorization code that obtains an access token}' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'redirect_uri={your redirect url}' \
--data-urlencode 'client_id={your client id}' \
--data-urlencode 'client_secret={your client secret}' \
--data-urlencode 'state={your unique alphanumeric string}'
| Property | Type | Description |
|---|---|---|
| access_token | string | Access token, which remains valid for 1 hour. |
| expires_in | number | The amount of time in seconds until the access token expires. |
| id_token | string | JSON Web Token (JWT) that includes information about the user. This field is returned only if OpenID is specified in the scope. |
| refresh_token | string | A token is used to obtain a new access token, which remains valid until 24 hours after the access token is issued. |
| scope | string | Permissions granted by the user |
| token_type | string | Bearer |
{
"access_token": "_-xO_oggXQwIThjjo8iPm5J2lf8Tsz33zdCGgd-bzBg.h31h1COKfEq4xdJbnuu9en_UQwXTJkV7Gf9aghuL9uY",
"expires_in": 3599,
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzpj...",
"refresh_token": "8EqQaJ3Xp8VX7tfG71m0L2SBEaXRwcXtFYwc34qB4qM.hnSvfnq0xypwIfXciAXgGHp7LcNOlbyddcs-cYVm2L4",
"scope": "offline openid",
"token_type": "Bearer"
}
An ID token is a JSON Web Token (JWT) that contains claims about the authentication of an end-user by an authorization server. It is designed to be consumed by the client application (also known as the relying party) and contains essential information about the user and the authentication event.
An ID token typically has 3 parts, separated by dots (.):
1. Header: This part contains metadata about the token, including the type of token (JWT) and the signing algorithm used.
{
"alg": "RS256",
"typ": "JWT"
}
2. Payload: This part contains the claims, which are statements about an entity. The payload includes standard claims like iss (issuer), sub (subject), aud (audience), exp (expiration time), and other optional claims.
{
"at_hash": "6wMYdxWc64oZvXpn29UggQ",
"aud": [
"6c366ffe-eec5-4921-a71e-441d4d8444e4"
],
"auth_time": 1682010030,
"exp": 1682013728,
"iat": 1682010128,
"iss": "https://paotang-id.devops.krungthai.com/",
"jti": "69974269-621e-4f72-b00b-be8fa330794b",
"rat": 1682010029,
"sid": "e94530bb-211e-48f3-88a8-cd4566848dc2",
"sub": "nvPDZgNvyK5xj61KIoctIqUTXfRzSAA27AKXD7rXGGBgYxEwCwXxI4M9eVcuiehMPUJH9KFJW5TKChP6F0DVpsMr"
}
3. Signature: This part verifies that the token was issued by a trusted source and that it has not been tampered with. It is created by signing the header and payload with the authorization server’s private key.
Upon receiving the ID token, the client application must validate it by following these steps:
1. Verifying the signature: Ensuring the token’s signature is valid and that it was issued by the trusted OP.
2. Checking the claims: Verifying that the token is not expired (exp claim) and that the token is intended for the client (aud claim).
After verifying the token, the sub claim can serves as a unique key (anonymous ID) to identify the user across multiple sessions and interactions with the RP. It allows the RP to recognize the same user across different login sessions.
Once Paotang application has issued access token, the partner is able to use token to obtain the customer profile.
curl --location --request POST '{{baseUrl}}/v1/paotangpass/get-customer-profile' \
--header 'Authorization: Bearer {your access token}'
After a successful request to this service, the response should follow the user’s granted scope for this session.
| Property | Type | Description |
|---|---|---|
| code | string | The response code 0000 means success; otherwise, it means some errors have occurred. |
| message | string | As well as the property 'code', the response code 0000 means success; otherwise, it means some errors have occurred. |
| data | object | The JSON object of a customer profile |
{
"code": "0000",
"message": "",
"data": {
"cid": "1234567890123",
"title": "นาย",
"fullNameTh": {
"thaiFirstName": "วายุ",
"thaiMiddleName": "ชื่อกลางถ้ามี",
"thaiLastName": "มีตัง"
},
"fullNameEn": {
"engFirstName": "Vayu",
"engMiddleName": "Optional",
"engLastName": "Meetang"
},
"gender": "M",
"birthDate": "25400122",
"mobileNo": "0123456789",
"email": "test@example.com",
"workProfile": {
"occupationCode": "1257",
"occupationValue": "กลุ่มเทคโนโลยี",
"occupationGroup": "07",
"occupationGroupValue": "พนักงานบริษัท/ลูกจ้างเอกชน",
"subOccupationGroup": "99",
"subOccupationGroupValue": "อื่นๆ",
"salary": "6",
"salaryValue": "40,001-60,000 บาท"
},
"legalAddress": {
"address": "123",
"subDistrict": "แขวงจอมพล",
"subDistrictCode": "0400",
"district": "เขตจตุจักร",
"districtCode": "1030",
"stateProv": "กรุงเทพมหานคร",
"stateProvCode": "10",
"postalCode": "10900",
"country": "TH",
"phoneNo": "012345678"
},
"mailingAddress": {
"address": "123",
"subDistrict": "แขวงจอมพล",
"subDistrictCode": "0400",
"district": "เขตจตุจักร",
"districtCode": "1030",
"stateProv": "กรุงเทพมหานคร",
"stateProvCode": "10",
"postalCode": "10900",
"country": "TH",
"phoneNo": "012345678"
},
"officeAddress": {
"officeName": "ABC",
"address": "123",
"subDistrict": "แขวงจอมพล",
"subDistrictCode": "0400",
"district": "เขตจตุจักร",
"districtCode": "1030",
"stateProv": "กรุงเทพมหานคร",
"stateProvCode": "10",
"postalCode": "10900",
"country": "TH",
"phoneNo": "012345678",
"phoneExt": "01"
}
}
}