🔐 Dokumentasi OAuth2 Brainxiex

📌 Overview

Brainxiex OAuth2 Provider memungkinkan aplikasi pihak ketiga menggunakan akun Brainxiex untuk autentikasi user, mirip dengan Google Sign-In atau Facebook Login.

OAuth2 Provider adalah sistem autentikasi terstandar yang digunakan oleh Google, Facebook, GitHub, dan platform besar lainnya.

✨ Fitur Utama

Authorization Code Flow

Standar OAuth2 untuk aplikasi web dengan keamanan maksimal

PKCE Support

Keamanan tambahan untuk mobile apps dan Single Page Applications

Refresh Token

Auto-renew access token tanpa user login ulang

User Consent

User approval untuk setiap aplikasi yang mengakses data

🚀 Getting Started

1. Register Aplikasi

  1. Login ke Brainxiex Dashboard
  2. Buka menu OAuth2 Apps
  3. Klik Create New App
  4. Isi form:
    • Application Name: Nama aplikasi Anda
    • Redirect URIs: URL callback (satu per baris)
    • Scopes: Permissions (profile, email, whatsapp)
  5. Klik Create
Important: Jangan pernah membagikan Client Secret secara publik! Client Secret HANYA digunakan di server-side.

2. Available Endpoints

Endpoint Description
/oauth2/authorize Authorization endpoint untuk user login
/api/oauth2/token Token endpoint untuk exchange code/token
/api/oauth2/userinfo User info endpoint untuk mendapatkan data user

🔄 OAuth2 Flow

Redirect User to Authorization Endpoint

Redirect user ke halaman authorization Brainxiex dengan parameter yang diperlukan.

const clientId = 'your_client_id';
const redirectUri = 'https://your-app.com/callback';
const scope = 'profile email';
const state = 'random_state_string';

// Optional: PKCE for additional security
const codeVerifier = generateRandomString(43);
const codeChallenge = base64UrlEncode(sha256(codeVerifier));

const authUrl = new URL('https://brainxiex.com/oauth2/authorize');
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('client_id', clientId);
authUrl.searchParams.set('redirect_uri', redirectUri);
authUrl.searchParams.set('scope', scope);
authUrl.searchParams.set('state', state);
authUrl.searchParams.set('code_challenge', codeChallenge);
authUrl.searchParams.set('code_challenge_method', 'S256');

// Redirect user to authUrl
window.location.href = authUrl.toString();

User Authorizes

User akan diarahkan ke halaman login Brainxiex dan melihat halaman consent yang menampilkan:

  • Nama aplikasi Anda
  • Permissions yang diminta (scopes)
  • Tombol "Authorize" dan "Deny"

Exchange Code for Access Token

Setelah user menyetujui, exchange authorization code untuk access token.

const code = 'authorization_code_from_callback';
const codeVerifier = 'same_code_verifier_from_step_1';

const response = await fetch('https://brainxiex.com/api/oauth2/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: code,
    client_id: clientId,
    client_secret: clientSecret,
    redirect_uri: redirectUri,
    code_verifier: codeVerifier
  })
});

const tokens = await response.json();
// {
//   access_token: "bx_access_...",
//   token_type: "Bearer",
//   expires_in: 3600,
//   refresh_token: "bx_refresh_...",
//   scope: "profile email"
// }

Get User Info

Gunakan access token untuk mendapatkan informasi user.

const userInfo = await fetch('https://brainxiex.com/api/oauth2/userinfo', {
  headers: {
    'Authorization': `Bearer ${tokens.access_token}`
  }
});

const user = await userInfo.json();
// {
//   sub: "123",
//   brainxiex_id: "user_brainxiex_id",
//   name: "User Name",
//   picture: "https://...",
//   username: "username",
//   email: "[email protected]",
//   email_verified: true
// }

Refresh Access Token

Gunakan refresh token untuk mendapatkan access token baru tanpa login ulang.

const refreshToken = tokens.refresh_token;

const response = await fetch('https://brainxiex.com/api/oauth2/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: new URLSearchParams({
    grant_type: 'refresh_token',
    refresh_token: refreshToken,
    client_id: clientId,
    client_secret: clientSecret
  })
});

const newTokens = await response.json();
// New access_token and refresh_token

🌐 API Endpoints

POST /api/oauth2/token

Exchange authorization code atau refresh token untuk access token.

POST https://brainxiex.com/api/oauth2/token

Request Body (Authorization Code Grant):

grant_type=authorization_code
&code=AUTHORIZATION_CODE
&client_id=CLIENT_ID
&client_secret=CLIENT_SECRET
&redirect_uri=REDIRECT_URI
&code_verifier=CODE_VERIFIER (optional, for PKCE)

Response:

{
  "access_token": "bx_access_...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "bx_refresh_...",
  "scope": "profile email"
}

GET /api/oauth2/userinfo

Get user information menggunakan access token.

GET https://brainxiex.com/api/oauth2/userinfo

Request Headers:

Authorization: Bearer ACCESS_TOKEN

Response:

{
  "sub": "123",
  "brainxiex_id": "user_brainxiex_id",
  "name": "User Name",
  "picture": "https://...",
  "username": "username",
  "email": "[email protected]",
  "email_verified": true,
  "phone_number": "628123456789",
  "phone_number_verified": true
}

🎯 Scopes

Scopes menentukan data apa yang bisa diakses oleh aplikasi Anda.

Scope Description Data Returned
profile Basic profile information name, picture, username
email Email address email, email_verified
whatsapp WhatsApp number phone_number, phone_number_verified
Contoh Penggunaan: profile email untuk data dasar + email, atau profile email whatsapp untuk semua data.

💻 Implementation Examples

Frontend (JavaScript)

// Step 1: Generate PKCE (optional but recommended)
function generatePKCE() {
  const codeVerifier = base64UrlEncode(crypto.getRandomValues(new Uint8Array(32)));
  const codeChallenge = base64UrlEncode(await sha256(codeVerifier));
  return { codeVerifier, codeChallenge };
}

// Step 2: Redirect to authorization
function login() {
  const { codeVerifier, codeChallenge } = generatePKCE();
  sessionStorage.setItem('code_verifier', codeVerifier);

  const params = new URLSearchParams({
    response_type: 'code',
    client_id: 'your_client_id',
    redirect_uri: 'https://your-app.com/callback',
    scope: 'profile email',
    state: generateRandomString(),
    code_challenge: codeChallenge,
    code_challenge_method: 'S256'
  });

  window.location.href = `https://brainxiex.com/oauth2/authorize?${params}`;
}

// Step 3: Handle callback
async function handleCallback() {
  const urlParams = new URLSearchParams(window.location.search);
  const code = urlParams.get('code');
  const state = urlParams.get('state');

  const codeVerifier = sessionStorage.getItem('code_verifier');

  // Exchange code for token
  const response = await fetch('https://brainxiex.com/api/oauth2/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      code,
      client_id: 'your_client_id',
      client_secret: 'your_client_secret',
      redirect_uri: 'https://your-app.com/callback',
      code_verifier: codeVerifier
    })
  });

  const tokens = await response.json();

  // Store tokens securely
  localStorage.setItem('access_token', tokens.access_token);
  localStorage.setItem('refresh_token', tokens.refresh_token);

  // Get user info
  const user = await getUserInfo(tokens.access_token);
  console.log('Logged in as:', user);
}

Backend (Node.js/Express)

const express = require('express');
const app = express();

app.get('/auth/login', (req, res) => {
  const authUrl = new URL('https://brainxiex.com/oauth2/authorize');
  authUrl.searchParams.set('response_type', 'code');
  authUrl.searchParams.set('client_id', process.env.CLIENT_ID);
  authUrl.searchParams.set('redirect_uri', process.env.REDIRECT_URI);
  authUrl.searchParams.set('scope', 'profile email');
  authUrl.searchParams.set('state', generateRandomString());
  res.redirect(authUrl.toString());
});

app.get('/auth/callback', async (req, res) => {
  const { code, state } = req.query;

  // Exchange code for token
  const tokenResponse = await fetch('https://brainxiex.com/api/oauth2/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      code,
      client_id: process.env.CLIENT_ID,
      client_secret: process.env.CLIENT_SECRET,
      redirect_uri: process.env.REDIRECT_URI
    })
  });

  const tokens = await tokenResponse.json();

  // Get user info
  const userResponse = await fetch('https://brainxiex.com/api/oauth2/userinfo', {
    headers: { 'Authorization': `Bearer ${tokens.access_token}` }
  });

  const user = await userResponse.json();

  // Create or update user in your database
  await upsertUser(user);

  // Create session
  req.session.user = user;
  res.redirect('/dashboard');
});

🔒 Security Considerations

Important Security Guidelines - Ikuti panduan ini untuk keamanan maksimal.

1. Protect Client Secret

  • Client Secret HANYA digunakan di server-side
  • Jangan pernah menyimpan Client Secret di frontend
  • Gunakan environment variables

2. Use HTTPS

  • Semua redirect URI harus menggunakan HTTPS di production
  • Local development boleh menggunakan HTTP

3. Validate State Parameter

  • Generate random state sebelum redirect
  • Validasi state setelah callback
  • Mencegah CSRF attacks

4. Use PKCE

  • Sangat disarankan untuk mobile apps dan SPAs
  • Mencegah authorization code interception

5. Secure Token Storage

  • Access token: Simpan di memory atau httpOnly cookie
  • Refresh token: Simpan di httpOnly cookie dengan secure flag
  • Jangan simpan di localStorage jika memungkinkan

6. Token Expiration

  • Access token kadaluarsa dalam 1 jam
  • Refresh token kadaluarsa dalam 30 hari
  • Implementasikan refresh token rotation

7. Scope Limitation

  • Request minimal scope yang dibutuhkan
  • Jangan request scope yang tidak digunakan

🔧 Troubleshooting

Error: invalid_client

Client ID atau Client Secret salah. Pastikan credentials benar dari dashboard.

Error: invalid_redirect_uri

Redirect URI tidak terdaftar. Pastikan redirect URI cocok persis dengan yang didaftarkan. Cek trailing slash.

Error: invalid_grant

  • Authorization code sudah digunakan (single use)
  • Authorization code sudah kadaluarsa (10 menit)
  • Code verifier mismatch (jika menggunakan PKCE)

Error: invalid_scope

Scope yang diminta tidak diizinkan. Pastikan scope sesuai dengan yang didaftarkan.

Error: access_denied

User menolak authorization. Tampilkan pesan yang user-friendly.

Need Help? Hubungi [email protected] atau kunjungi WhatsApp Support

© 2026 Brainxiex Development. All rights reserved.