All Collections
Additional Fuel Bank
Galxe ID SDK: A Comprehensive Guide to Integrating Galxe Identity Verification into Your Application
Galxe ID SDK: A Comprehensive Guide to Integrating Galxe Identity Verification into Your Application
Learn how to integrate Galxe ID SDK into your applications for secure and seamless identity verification.
Ashley avatar
Written by Ashley
Updated over a week ago

Galxe ID SDK seamlessly integrates Galxe identity and authentication features into your applications. Empower your users with secure authentication and access to Galxe Passport, a comprehensive digital identity management solution.


Benefits of Galxe ID SDK Integration:

  1. Seamless User Experience: Provide a frictionless login and registration process by enabling users to authenticate with their Galxe Passport credentials, eliminating the need for traditional usernames and passwords.

  2. Enhanced Security: Leverage Galxe ID SDK's robust encryption and security protocols to ensure the utmost protection of user data, establishing a highly secure and trusted identity management solution.

  3. Simplified KYC Processes: Streamline KYC compliance by allowing users to store and manage verified identity documents within Galxe Passport. Integrate Galxe ID SDK to automate and streamline your KYC processes, reducing manual efforts and enhancing operational efficiency.

  4. Access to User-Approved Data: With user consent, authorized partners can request specific user data stored in Galxe Passport, enabling personalized experiences, tailored services, and improved customer engagement.

Note: Galxe ID SDK is currently limited to third-party website integration for user consent. To retrieve user information on Galxe campaigns, integrate the SDK into your website to obtain the necessary permissions. Discover the power of Galxe ID SDK and elevate your app's identity management with Galxe Passport integration.


Access Galxe ID SDK Integration Guide

Note: Make sure to have your Galxe ID SDK application approved before proceeding with the integration.

Getting Started

To get started, please apply by submitting a ticket through our Live Chat - Submit a Ticket - Integration Related and select “Galxe ID SDK Application”.

OAuth

Galxe's OAuth implementation supports the standard authorization code grant type for apps that don't have access to a web browser.

Authorization flow

The request flow to authorize users for your app is as follows:

  • Users are redirected to request their Galxe identity.

  • Users are redirected back to your site by Galxe.

  • Your app accesses the API with the user's access token.


Request a user's Galxe identity

URL

GET https://galxe.com/oauth
REDIRECT
https://galxe.com/oauth?client_id=${CLIENT-ID}&scope=${SCOPE}&redirect_uri=${REDIRCT-URI}&state=${STATE}

Available Scopes:

  • Email

  • Twitter

  • Discord

  • Github

  • EVMAddress

  • SolanaAddress

Parameters

Name

Type

Description

client_id

string

Required. The client ID you received from Galxe when you registered.

scope

string

Required. A space-delimited list of scopes. If not provided, scope defaults to an empty list for users that have not authorized any scopes for the application.

redirect_uri

string

Required. The URL in your application where users will be sent after authorization, also known as callback url.

state

string

Required. An unguessable random string. It is used to protect against cross-site request forgery attacks.

code_challenge

string

PKCE (Proof Key for Code Exchange) is an extension to the Authorization Code flow to prevent CSRF and authorization code injection attacks. PKCE is not a replacement for a client secret, and PKCE is recommended even if a client is using a client secret.

code_challenge_method

string

Encoding method, plain or S256 (sha256), S256 is recommended.

Response

By default, the response will add the following parameter to your redirect_uri:

code=${CODE}&state=${STATE}

Ensure that you replace ${CLIENT-ID}, ${SCOPE}, ${REDIRECT-URI}, and ${STATE} with the appropriate values specific to your application. When the user authorizes the request, they will be redirected to the specified redirect_uri with the authorization code (code) and the state value (state) as query parameters.


To obtain an access token, follow these steps:

  1. After the user accepts your request, Galxe will redirect back to your site with a temporary code and the state you provided.

  2. Extract the temporary code from the code parameter in the redirected URL.

  3. Ensure that the state parameter received matches the state you provided earlier. If they don't match, it may indicate a third party tampering with the request, and you should stop the process.

  4. Exchange the temporary code for an access token by making a request to Galxe's token endpoint.

  5. The access token will be included in the response from the token endpoint.

Remember to handle the expiration of the temporary code, which typically lasts for 10 minutes, and implement appropriate error handling for any issues that may arise during the token exchange process.


To exchange the temporary code for an access token, you can use the following cURL command:

URL

Content-Type:application/x-www-form-urlencoded
POST https://api.galxe.com/oauth/auth/2/token
curl -d 'client_id=${CLIENT-ID}&client_secret=${CLIENT-SECRET}&code=${CODE}&grant_type=authorization_code' -H "Content-Type: application/x-www-form-urlencoded" -X POST https://api.galxe.com/oauth/auth/2/token

Make sure to replace ${CLIENT-ID}, ${CLIENT-SECRET}, and ${CODE} with the actual values provided by Galxe. This command sends a POST request to the specified URL (https://api.galxe.com/oauth/auth/2/token) with the necessary parameters to obtain the access token. The response from the server will contain the access token.

Parameters

Name

Type

Description

client_id

string

Required. The client ID you received from Galxe for your OAuth App.

client_secret

string

Required. The client secret you received from Galxe for your OAuth App.

code

string

Required. The code you received as a response to OAuth Authorize Step.

code_verifier

string

Plain string of code_challenge, only used when requiring code_challenge.

Response

By default, the response takes the following form:

{
"access_token": "OTJLYTIWNMQTYJY1ZC0ZOGQ2LTGYMDITNWQXZWJKNTA4YZAA",
"expires_in": 86400,
"refresh_token": "NGM5OWUXNDKTNTEZOC01NZBMLWEXMGUTMDUYZGJMNZI3YME0",
"scope": "Twitter",
"token_type": "Bearer"
}

Refresh Access Token

URL

Content-Type:application/x-www-form-urlencoded
POST https://api.galxe.com/oauth/auth/2/token
$ curl -d 'grant_type=refresh_token&refresh_token=${REFRESH-TOKEN}&client_id=${CLIENT-ID}&client_secret=${CLIENT-SECRET}' -H "Content-Type:application/x-www-form-urlencoded" -X POST https://api.galxe.com/oauth/auth/2/token

Parameters

Name

Type

Description

refresh_token

string

Required. The token generated when the Galxe App owner enables expiring tokens and issues a new user access token.

grant_type

string

Required. Value must be refresh_token (required by the OAuth specification).

client_id

string

Required. The client ID for Galxe App.

client_secret

string

Required. The client secret for Galxe App.

Response

{
"access_token": "NTLMMJKYMMQTZJZJYI0ZZGFLLWE5NZMTMZAZMDY3YWMWNMI4",
"expires_in": 86400,
"refresh_token": "NGQXZGVJZDCTNTQ4YY01NTEZLTHMNTMTYJZHMWZIYJUZMJE3",
"scope": "Twitter Discord",
"token_type": "Bearer"
}

Get Access Token Detail

URL

Authorization: Bearer ${ACCESS-TOKEN}
GET https://api.galxe.com/oauth/api/2/token
$ curl -H "Authorization: Bearer ${ACCESS-TOKEN}" https://api.galxe.com/oauth/api/2/token

Parameters

Name

Type

Description

access_token

string

Required. Append it to header.

Response

{
"client_id": "client_id",
"expires_at": "2022-08-31 16:00:22.666401 +0800 CST",
"scope": "twitter discord",
}

Use the access token to access the API

URL

Authorization: Bearer ${ACCESS-TOKEN}
GET https://api.galxe.com/oauth/api/2/user
$ curl -H "Authorization: Bearer ${ACCESS-TOKEN}" https://api.galxe.com/oauth/api/2/user?scope=Twitter%20Discord

Parameters

Name

Type

Description

access_token

string

Required. Append it to request header.

scope

string

A space-delimited list of scopes of user data that your APP required. If not set, will set to access token related scope by default.

Response

{
"TwitterUsername": "twitter_username",
"TwitterUserID": "twitter_userid",
"DiscordUsername": "discord_username"
"DiscordUserID": "discord_userid"
}

Passport

Authorized partners of Galxe can request to access user’s encrypted KYC data in their Galxe Passport through strict user consent. This document describes the workflow.

Workflow

Assume an external company, XYZ, wants to access an user’s KYC data stored inside their Galxe Passport. From XYZ’s website, the user will first be redirected to https://galxe.com/passportauth, where they are prompted to connect their wallet and go through the passport decryption flow on the frontend using their own password.

Decrypted data will then be sent as HTTP POST request to XYZ’s endpoint.

For example, upon user decryption, they get the following JSON (this is what will be sent as POST payload to XYZ’s endpoint):

{"body":"{\"owner\":\"0xb85b3D61439a3d70D3DF7913a3A764F352b32C55\",\"plain\":\"eyJldm0tYWRkcmVzcyI6IjB4Yjg1YjNENjE0MzlhM2Q3MEQzREY3OTEzYTNBNzY0RjM1MmIzMkM1NSIsImdvdmVybm1lbnRJRHMiOlt7ImZpcnN0LW5hbWUiOiJBTEVYQU5ERVIgSiIsImxhc3QtbmFtZSI6IlNBTVBMRSIsImJpcnRoZGF0ZSI6IjE5NzctMDctMTciLCJuYXRpb25hbGl0eSI6IiIsImRvY3VtZW50LW51bWJlciI6IiIsInNleCI6Ik1hbGUiLCJjb3VudHJ5LWNvZGUiOiJVUyIsImlkLWNsYXNzIjoiZGwiLCJmcm9udC1waG90by1rZXkiOiJodHRwczovL3dpdGhwZXJzb25hLmNvbS9hcGkvdjEvZmlsZXMvZXlKZmNtRnBiSE1pT25zaWJXVnpjMkZuWlNJNklrSkJhSE5MZDJaYU4wdFNTU0lzSW1WNGNDSTZiblZzYkN3aWNIVnlJam9pWW14dllsOXBaQ0o5ZlE9PS0tZDUzOTg4MzU2NjViODJlYTk4YTE3ZmYyMTRjODhhZjkxN2FhNzUyYy8xNjY2MTYyMjA1NzI2NjI5NzE0LmpwZyIsImJhY2stcGhvdG8ta2V5IjoiaHR0cHM6Ly93aXRocGVyc29uYS5jb20vYXBpL3YxL2ZpbGVzL2V5SmZjbUZwYkhNaU9uc2liV1Z6YzJGblpTSTZJa0pCYUhOTGQyWllOMHRTU1NJc0ltVjRjQ0k2Ym5Wc2JDd2ljSFZ5SWpvaVlteHZZbDlwWkNKOWZRPT0tLWRmNDhiMjBmYTcxMGE4NTg2MmFlMzFjMDNmZmM1YWRmZjA3NzMzOWYvMTY2NjE2MjIwNTcyNjYyOTcxNC5qcGciLCJpZGVudGlmaWNhdGlvbi1udW1iZXIiOiJJMTIzNDU2MiJ9XSwic2VsZmllIjp7ImxlZnQtcGhvdG8ta2V5IjoiaHR0cHM6Ly93aXRocGVyc29uYS5jb20vYXBpL3YxL2ZpbGVzL2V5SmZjbUZwYkhNaU9uc2liV1Z6YzJGblpTSTZJa0pCYUhOTGQyTnhTMkZXU1NJc0ltVjRjQ0k2Ym5Wc2JDd2ljSFZ5SWpvaVlteHZZbDlwWkNKOWZRPT0tLTRhZjRjZjMyODUzZTQ0NDc4NDAwYmY1MDZmM2E2ODc1ZDhkYjYwNzEvbGVmdF9waG90b19wcm9jZXNzZWQuanBnIiwiY2VudGVyLXBob3RvLWtleSI6Imh0dHBzOi8vd2l0aHBlcnNvbmEuY29tL2FwaS92MS9maWxlcy9leUpmY21GcGJITWlPbnNpYldWemMyRm5aU0k2SWtKQmFITkxkMk50UzJGV1NTSXNJbVY0Y0NJNmJuVnNiQ3dpY0hWeUlqb2lZbXh2WWw5cFpDSjlmUT09LS00NmU5NDA3MTRmNDdkZjJlNzdlZjJlY2UyNDZmNTY5YWYxODgzN2I0L2NlbnRlcl9waG90b19wcm9jZXNzZWQuanBnIiwicmlnaHQtcGhvdG8ta2V5IjoiaHR0cHM6Ly93aXRocGVyc29uYS5jb20vYXBpL3YxL2ZpbGVzL2V5SmZjbUZwYkhNaU9uc2liV1Z6YzJGblpTSTZJa0pCYUhOTGQyTnlTMkZXU1NJc0ltVjRjQ0k2Ym5Wc2JDd2ljSFZ5SWpvaVlteHZZbDlwWkNKOWZRPT0tLThjZGExZTEyOTg5Y2Y4MWIxZTVlODZkYjgyNTE5ZWFkZjU4MGFkNTAvcmlnaHRfcGhvdG9fcHJvY2Vzc2VkLmpwZyJ9LCJwYXNzcG9ydC12ZXJzaW9uIjoidjEuMSIsInBlcnNvbmEtaWQiOiJkMzFjMjVkNS0yNThlLTQ0NzgtYWI4Ni00ODI2ZGE0ZTI1OTgifQ==\",\"salt\":\"M-oWdEP9iIvrsr4Im6DiBix4kEWTQkOp\"}","signature":"1r2HXn2bJ/Eiz3+r3l5+wiSZSHivcIHvPKIWHp0WrDRA0VTyulA2syRRFMZTAUdLn5kXPR4z+PBFD44obgVYsgE="}

XYZ can then proceed to decode this data, as well as validate its signatures.

body.plain is a base64 encoded string. Decoding it as follows:

const decodedJson = JSON.parse(decoded.toString());
const bodyJson = JSON.parse(decodedJson.body);
const body = Buffer.from(bodyJson.plain, "base64").toString();
const kycData = JSON.parse(body);
console.log(kycData);

We get:

{
'evm-address': '0xb85b3D61439a3d70D3DF7913a3A764F352b32C55',
governmentIDs: [
{
'first-name': 'ALEXANDER J',
'last-name': 'SAMPLE',
birthdate: '1977-07-17',
nationality: '',
'document-number': '',
sex: 'Male',
'country-code': 'US',
'id-class': 'dl',
'front-photo-key': 'https://withpersona.com/api/v1/files/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2ZaN0tSSSIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--d5398835665b82ea98a17ff214c88af917aa752c/1666162205726629714.jpg',
'back-photo-key': 'https://withpersona.com/api/v1/files/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2ZYN0tSSSIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--df48b20fa710a85862ae31c03ffc5adff077339f/1666162205726629714.jpg',
'identification-number': 'I1234562'
}
],
selfie: {
'left-photo-key': 'https://withpersona.com/api/v1/files/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2NxS2FWSSIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--4af4cf32853e44478400bf506f3a6875d8db6071/left_photo_processed.jpg',
'center-photo-key': 'https://withpersona.com/api/v1/files/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2NtS2FWSSIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--46e940714f47df2e77ef2ece246f569af18837b4/center_photo_processed.jpg',
'right-photo-key': 'https://withpersona.com/api/v1/files/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2NyS2FWSSIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--8cda1e12989cf81b1e5e86db82519eadf580ad50/right_photo_processed.jpg'
},
'passport-version': 'v1.1',
'persona-id': 'd31c25d5-258e-4478-ab86-4826da4e2598'
}

Note that persona photo urls are not publicly accessible. These URLs purely exist for legacy reasons.

Pseudocode to validate signature:

  1. hash = keccak256(body)

  2. signer = recoverSigner(hash, Base64.decode(signature))

For now, signer should match: 0x36066A2d5c8D4A486E0d1EC3FB51b0E242e3Fb75. In future we will release a REST endpoint to verify the validity of signer.


Did this answer your question?