Get X-Token / Login API
X-Token is a header that should be filled with JWT token generated from user login.
Most API request in OpenSSO will require X-Token header.
You can get X-Token in three different ways.
Get Access Token
Since version 1.5.0, you have to get an Access-Token before requesting login activity.
You need to have SSO Key, by create your SSO inside menu My SSO.
See picture below

| Method | Endpoint | Header | Body |
|---|---|---|---|
| GET | http://localhost:3000/api/oauth/request_token | Content-Type: application/json, Access-Key: {{YOUR_SSO_KEY}} |
Example output response
{
"message": "Access token successfully generated!",
"statusCode": 200,
"success": true,
"access_token": "=Ng=zY3MzNzOjMmY2YzdmYjODNGRxxhNhN5NjZjQGRiZmMkNDYTNmExQ1OxOTxxx"
}
SSO Keyhave no expiring time, but you can't use it again if its status disabled or removed (regenerated) fromMy SSOmenu.Access-Tokenhave its expiring time, just request only once then you can use it multiple times up to 1 hour.
1. Login Normal
Get X-Token
Get X-Token via login normal.
| Method | Endpoint | Header | Body |
|---|---|---|---|
| POST | http://localhost:3000/api/user/login | Content-Type: application/json, Access-Token: {{YOUR_ACCESS_TOKEN}} | {"username": "", "password": ""} |
Example output response
{
"message": "Login user success!",
"statusCode": 200,
"success": true,
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiI1ZDM3NDk5Yi0xM2ZjLTQzZmItOWE3Yi1kZGI3Nzc1N2FjOTMiLCJ1bm0iOiJhYWxmaWFubiIsIm5hbWUiOiJhYWxmaWFubiIsIm1haWwiOiJhYWxmaWFubkBnbWFpbC5jb20iLCJyb2xlIjoiYWRtaW4iLCJncmF2YXRhciI6Imh0dHBzOi8vZ3JhdmF0YXIuY29tL2F2YXRhci82ZDdiZDI0MWEyNjc5ZDc1NTc4OTQwMjY4MWQyNWVjMSIsImhhc2giOiJVeHlNVGJqb0cxcHBoWnpNVE1UUSIsImlhdCI6MTY3Mjc3NDg3MCwiZXhwIjoxNjcyODAzNjcwfQ.I1OZASUEtLOBYcaKLHesbsIfywQmB00e1mQO2QTroGmPQtlA84mqwUDYbAiOhS0micIilMlSaIYk0_QdwVABCWNqJlREU0BeQkrKE64tuJ4WHY7lbTvklPOA0k-j6JBZpqp-D0qw8F8-zN6iYq0vyuBHZ6vfRe-0i-B96FiijKZKPkG3KPmXnY0HJtx4GPxhigaUvLb2rRN4eV8Am--2XnbAWpRqecuI5LM6b2oFG-ZoOfNm0LLNe2TJCaKUXBFvoAIZnwAk_l0HZmu-wtiCjkmcjQ5aOO1mrZTONAckvfVFWjK4bx4IFXFeLUVZPOJA3_z9PzH--AoYzjQkYL_q8Q",
"expire": 1672803670000
}
Handling 2FA/MFA
If one of 2FA is activated, then the response output will be
{
"message": "OTP Required!",
"statusCode": 400,
"error": "Bad Request",
"required": [
"x-ga-otp"
]
}
If multiple 2FA is activated (MFA), then the response output will be
{
"message": "OTP Required!",
"statusCode": 400,
"error": "Bad Request",
"required": [
"x-email-otp",
"x-ga-otp"
]
}
- x-email-otp is required header to verify the otp code from email.
- x-ga-otp is required header to verify the otp code from authenticator app.
- ga is short from Global Authenticator which means you can use Google Authenticator, Microsoft Authenticator, Authy, etc.
Second Request To Verify 2FA
Once you got the otp code, then you can hit again with required header and otp code.
| Method | Endpoint | Header | Body |
|---|---|---|---|
| POST | http://localhost:3000/api/user/login | Content-Type: application/json,x-email-otp: 123456 | {"username": "", "password": ""} |
The success output response still the same
{
"message": "Login user success!",
"statusCode": 200,
"success": true,
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiI1ZDM3NDk5Yi0xM2ZjLTQzZmItOWE3Yi1kZGI3Nzc1N2FjOTMiLCJ1bm0iOiJhYWxmaWFubiIsIm5hbWUiOiJhYWxmaWFubiIsIm1haWwiOiJhYWxmaWFubkBnbWFpbC5jb20iLCJyb2xlIjoiYWRtaW4iLCJncmF2YXRhciI6Imh0dHBzOi8vZ3JhdmF0YXIuY29tL2F2YXRhci82ZDdiZDI0MWEyNjc5ZDc1NTc4OTQwMjY4MWQyNWVjMSIsImhhc2giOiJVeHlNVGJqb0cxcHBoWnpNVE1UUSIsImlhdCI6MTY3Mjc3NDg3MCwiZXhwIjoxNjcyODAzNjcwfQ.I1OZASUEtLOBYcaKLHesbsIfywQmB00e1mQO2QTroGmPQtlA84mqwUDYbAiOhS0micIilMlSaIYk0_QdwVABCWNqJlREU0BeQkrKE64tuJ4WHY7lbTvklPOA0k-j6JBZpqp-D0qw8F8-zN6iYq0vyuBHZ6vfRe-0i-B96FiijKZKPkG3KPmXnY0HJtx4GPxhigaUvLb2rRN4eV8Am--2XnbAWpRqecuI5LM6b2oFG-ZoOfNm0LLNe2TJCaKUXBFvoAIZnwAk_l0HZmu-wtiCjkmcjQ5aOO1mrZTONAckvfVFWjK4bx4IFXFeLUVZPOJA3_z9PzH--AoYzjQkYL_q8Q",
"expire": 1672803670000
}
2. Login via Oauth
User who already registered using oauth Google or Apple, they will need this API to let them sign-in.
- This method will auto register new user if an username or email not exists inside OpenSSO.
- You should follow the oauth flow Google and Apple or bad person could spamming your application.
- If you're not sure or don't understanding how the oauth Google and Apple works, you better use
Login via SSO Login Page.
Get X-Token
Once you have the access-token, you can use it to request X-Token.
If you don't have it, please read again at here
| Method | Endpoint | Header | Body |
|---|---|---|---|
| POST | http://localhost:3000/api/oauth/google | Content-Type: application/json, Access-Token: {{YOUR_ACCESS_TOKEN}} | {"username":"yourusername", "email":"[email protected]","gravatar":""} |
Apple
| Method | Endpoint | Header | Body |
|---|---|---|---|
| POST | http://localhost:3000/api/oauth/apple | Content-Type: application/json, Access-Token: {{YOUR_ACCESS_TOKEN}} | {"username":"yourusername", "email":"[email protected]"} |
Example output response
{
"message": "Oauth google success!",
"statusCode": 200,
"success": true,
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJiOGEwMzlmNy1jZjUyLTQ0MDktODU3OS01Yzc0Yjk3MzI2MDMiLCJ1bm0iOiJhYWxmaWFubiIsIm5hbWUiOiIiLCJtYWlsIjoiYWFsZmlhbm5AZ21haWwuY29tIiwiem9uZSI6IiIsInJvbGUiOiJtZW1iZXIiLCJncmF2YXRhciI6Imh0dHBzOi8vZ3JhdmF0YXIuY29tL2F2YXRhci82ZDdiZDI0MWEyNjc5ZDc1NTc4OTQwMjY4MWQyNWVjMSIsImhhc2giOiJBPT1RNE82TlRaWElXMWlwdFoyTUROalEiLCJpYXQiOjE2OTA0MzQ4MTEsImV4cCI6MTY5MDQ2MzYxMX0.XPTmCkJn85e26vgtnMdU5yLi6TGcBu0ct_MpVniJw8dB6yrxn3cNZm9luNJnSh7rWNLZV40jOYS0FbOxMMxfpF-n9uNUhoMnWqwd9pO3VERDuXOlhXVeWhHRHfn87JV2w_mlI6ZFfA3t3WjT5D8cydzs1Hf1Y8l726mVwrXMxJgV0W8TTIz1BiEPEnsFTX4V_fS5IdStz_8rz43q7keeUgBZ0qlGULjQpYGI_6xIKqsY1AP2rrQ9BJ57QL71aoULAJ5Uu7eTCicnO77pRJO-Hi2xFoZpIabsAZfOyd01hTnk3htsolIDY-_dB1_t5Hruullu89oNAWcgK_bChXzLuw",
"expire": 1690463611000
}
Handling 2FA/MFA
If one of 2FA is activated, then the response output will be
{
"message": "OTP Required!",
"statusCode": 400,
"error": "Bad Request",
"required": [
"x-ga-otp"
]
}
If multiple 2FA is activated (MFA), then the response output will be
{
"message": "OTP Required!",
"statusCode": 400,
"error": "Bad Request",
"required": [
"x-email-otp",
"x-ga-otp"
]
}
- x-email-otp is required header to verify the otp code from email.
- x-ga-otp is required header to verify the otp code from authenticator app.
- ga is short from Global Authenticator which means you can use Google Authenticator, Microsoft Authenticator, Authy, etc.
Second Request To Verify 2FA
Once you got the otp code, then you can hit again with required header and otp code.
| Method | Endpoint | Header | Body |
|---|---|---|---|
| POST | http://localhost:3000/api/oauth/google | Content-Type: application/json, Access-Token: {{YOUR_ACCESS_TOKEN}}, x-email-otp: 123456 | {"username":"yourusername", "email":"[email protected]","gravatar":""} |
Apple
| Method | Endpoint | Header | Body |
|---|---|---|---|
| POST | http://localhost:3000/api/oauth/apple | Content-Type: application/json, Access-Token: {{YOUR_ACCESS_TOKEN}}, x-ga-otp: 123456 | {"username":"yourusername", "email":"[email protected]"} |
The success output response still the same
{
"message": "Oauth google success!",
"statusCode": 200,
"success": true,
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJiOGEwMzlmNy1jZjUyLTQ0MDktODU3OS01Yzc0Yjk3MzI2MDMiLCJ1bm0iOiJhYWxmaWFubiIsIm5hbWUiOiIiLCJtYWlsIjoiYWFsZmlhbm5AZ21haWwuY29tIiwiem9uZSI6IiIsInJvbGUiOiJtZW1iZXIiLCJncmF2YXRhciI6Imh0dHBzOi8vZ3JhdmF0YXIuY29tL2F2YXRhci82ZDdiZDI0MWEyNjc5ZDc1NTc4OTQwMjY4MWQyNWVjMSIsImhhc2giOiJBPT1RNE82TlRaWElXMWlwdFoyTUROalEiLCJpYXQiOjE2OTA0MzQ4MTEsImV4cCI6MTY5MDQ2MzYxMX0.XPTmCkJn85e26vgtnMdU5yLi6TGcBu0ct_MpVniJw8dB6yrxn3cNZm9luNJnSh7rWNLZV40jOYS0FbOxMMxfpF-n9uNUhoMnWqwd9pO3VERDuXOlhXVeWhHRHfn87JV2w_mlI6ZFfA3t3WjT5D8cydzs1Hf1Y8l726mVwrXMxJgV0W8TTIz1BiEPEnsFTX4V_fS5IdStz_8rz43q7keeUgBZ0qlGULjQpYGI_6xIKqsY1AP2rrQ9BJ57QL71aoULAJ5Uu7eTCicnO77pRJO-Hi2xFoZpIabsAZfOyd01hTnk3htsolIDY-_dB1_t5Hruullu89oNAWcgK_bChXzLuw",
"expire": 1690463611000
}
3. Login via SSO Login Page
The simpler and safer is just use SSO Login Page to get the X-Token. But there is some tricky because Google Login Button can't displayed in Android WebView as default.