Dokumentasi API
Panduan lengkap untuk mengintegrasikan aplikasi Anda dengan SSO DPUPR Provinsi Banten.
Base URL
https://sso.dpupr.com
Autentikasi
SSO DPUPR menggunakan protokol OAuth 2.0 dengan PKCE (Proof Key for Code Exchange) untuk autentikasi yang aman. Setiap aplikasi client harus terdaftar untuk mendapatkan Client ID & Secret.
| Grant Type | Penggunaan |
|---|---|
authorization_code |
Aplikasi web dengan backend |
authorization_code + PKCE |
SPA, Mobile App (recommended) |
refresh_token |
Memperbarui access token |
OAuth Flow
Alur autentikasi Authorization Code dengan PKCE:
Generate PKCE
Buat code_verifier (random string) dan code_challenge (SHA256 hash)
Redirect ke Authorization
Redirect user ke /oauth/authorize dengan parameters
User Login
User login dan approve akses
Exchange Code
Tukar authorization_code + code_verifier untuk access token
OAuth Endpoints
/oauth/authorize
Authorization endpoint - redirect user kesini untuk login
Parameters
client_id |
Client ID aplikasi Anda |
redirect_uri |
URL callback setelah login |
response_type |
code |
scope |
Scope yang diminta (space-separated) |
state |
Random string untuk CSRF protection |
code_challenge |
PKCE code challenge (SHA256) |
/oauth/token
Token endpoint - tukar code dengan access token
Request Body
"grant_type": "authorization_code",
"client_id": "your-client-id",
"client_secret": "your-client-secret",
"redirect_uri": "https://your-app.com/callback",
"code": "authorization-code",
"code_verifier": "your-code-verifier"
Scopes
Scope menentukan akses yang diberikan ke aplikasi:
| Scope | Deskripsi |
|---|---|
read-profile |
Membaca profil dasar user |
bina-marga |
Akses untuk Bidang Bina Marga |
sumber-daya-air |
Akses untuk Bidang Sumber Daya Air |
cipta-karya |
Akses untuk Bidang Cipta Karya |
tata-ruang |
Akses untuk Bidang Tata Ruang |
User Profile API
/api/user
Mendapatkan profil lengkap user yang sedang login
Headers
Authorization: Bearer {access_token}
Accept: application/json
Response
{
"id": 1,
"nip": "199001012020121001",
"nama": "John Doe",
"email": "john@dpupr.bantenprov.go.id",
"no_hp": "081234567890",
"is_active": true,
"bidang": {
"id": 1,
"kode": "BM",
"nama": "Bidang Bina Marga"
},
"jabatan": {
"id": 5,
"nama": "Staff"
},
"roles": ["user"],
"permissions": ["users.view"],
"scopes": ["bina-marga", "read-profile"]
}
Logout API
/api/logout
Logout dari sesi saat ini (revoke current token)
/api/logout-all
Single Sign-Out: Logout dari SEMUA aplikasi sekaligus (revoke all tokens)
Integrasi Laravel Socialite
Contoh integrasi dengan Laravel Socialite:
1. Install Package
composer require laravel/socialite
2. Konfigurasi config/services.php
'dpupr_sso' => [
'client_id' => env('DPUPR_SSO_CLIENT_ID'),
'client_secret' => env('DPUPR_SSO_CLIENT_SECRET'),
'redirect' => env('DPUPR_SSO_REDIRECT_URI'),
'host' => 'https://sso.dpupr.com',
],
3. Controller
public function redirect()
{
return Socialite::driver('dpupr_sso')->redirect();
}
public function callback()
{
$user = Socialite::driver('dpupr_sso')->user();
// Login user...
}
Integrasi React / Vue (SPA)
client_secret di kode frontend. Gunakan PKCE Flow.
1. Install Library Client
Disarankan menggunakan library yang menangani PKCE secara otomatis, contohnya react-oauth2-code-pkce.
npm install react-oauth2-code-pkce
2. Konfigurasi AuthProvider
import { AuthProvider } from 'react-oauth2-code-pkce';
const authConfig = {
clientId: 'your-client-id',
authorizationEndpoint: 'https://sso.dpupr.com/oauth/authorize',
tokenEndpoint: 'https://sso.dpupr.com/oauth/token',
redirectUri: 'http://localhost:3000/callback',
scope: 'read-profile bina-marga',
onRefreshTokenExpire: (event) => window.confirm('Session expired. Login again?'),
};
function App() {
return (
<AuthProvider authConfig={authConfig}>
<YourApp />
</AuthProvider>
);
}
3. Menggunakan Token untuk API Request
import { useContext } from 'react';
import { AuthContext } from 'react-oauth2-code-pkce';
const UserProfile = () => {
const { token } = useContext(AuthContext);
const fetchProfile = async () => {
const response = await fetch('https://sso.dpupr.com/api/user', {
headers: {
Authorization: `Bearer ${token}`
}
});
const data = await response.json();
console.log(data);
};
// ...
}
Integrasi Node.js (Express)
Untuk aplikasi backend Node.js, Anda bisa menggunakan flow Authorization Code standar dengan client_secret.
1. Setup Route Login
const axios = require('axios');
const express = require('express');
const app = express();
const SSO_CONFIG = {
client_id: 'your-id',
client_secret: 'your-secret',
redirect_uri: 'http://localhost:3000/callback'
};
// 1. Redirect ke SSO
app.get('/login/sso', (req, res) => {
const url = `https://sso.dpupr.com/oauth/authorize?client_id=${SSO_CONFIG.client_id}&redirect_uri=${SSO_CONFIG.redirect_uri}&response_type=code&scope=read-profile`;
res.redirect(url);
});
2. Handle Callback
// 2. Callback untuk tukar code jadi token
app.get('/callback', async (req, res) => {
const { code } = req.query;
try {
// Request Token
const tokenParams = {
grant_type: 'authorization_code',
client_id: SSO_CONFIG.client_id,
client_secret: SSO_CONFIG.client_secret,
redirect_uri: SSO_CONFIG.redirect_uri,
code: code
};
const { data: tokenData } = await axios.post('https://sso.dpupr.com/oauth/token', tokenParams);
const accessToken = tokenData.access_token;
// Ambil User Info
const { data: userData } = await axios.get('https://sso.dpupr.com/api/user', {
headers: { Authorization: `Bearer ${accessToken}` }
});
res.json({ user: userData, token: accessToken });
} catch (error) {
res.status(500).json({ error: 'Login failed' });
}
});
Integrasi PHP Native
Contoh implementasi tanpa framework menggunakan cURL standard.
1. Konfigurasi (files: config.php)
<?php
define('SSO_CLIENT_ID', 'your-client-id');
define('SSO_CLIENT_SECRET', 'your-client-secret');
define('SSO_REDIRECT_URI', 'http://localhost/app/callback.php');
define('SSO_HOST', 'https://sso.dpupr.com'); // URL SSO Server
?>
2. Redirect ke Login (files: login.php)
<?php
require 'config.php';
$query = http_build_query([
'client_id' => SSO_CLIENT_ID,
'redirect_uri' => SSO_REDIRECT_URI,
'response_type' => 'code',
'scope' => 'read-profile',
'state' => bin2hex(random_bytes(16)) // CSRF Protection
]);
header("Location: " . SSO_HOST . "/oauth/authorize?" . $query);
exit;
?>
3. Handle Callback (files: callback.php)
<?php
require 'config.php';
session_start();
if (!isset($_GET['code'])) {
die("Error: Authorization code not found");
}
// 1. Tukar Code jadi Token via cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, SSO_HOST . "/oauth/token");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'grant_type' => 'authorization_code',
'client_id' => SSO_CLIENT_ID,
'client_secret' => SSO_CLIENT_SECRET,
'redirect_uri' => SSO_REDIRECT_URI,
'code' => $_GET['code'],
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
die("Error exchanging token: " . $response);
}
$tokenData = json_decode($response, true);
$accessToken = $tokenData['access_token'];
// 2. Ambil Profil User
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, SSO_HOST . "/api/user");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer $accessToken",
"Accept: application/json"
]);
$userResponse = curl_exec($ch);
curl_close($ch);
$userProfile = json_decode($userResponse, true);
// 3. Simpan di Session Login
$_SESSION['user'] = $userProfile;
$_SESSION['token'] = $accessToken;
header("Location: dashboard.php");
exit;
?>
Integrasi Mobile App (Flutter/React Native)
Aplikasi Mobile menggunakan PKCE Flow dan Deep Linking (Custom URL Scheme).
Deep Link / App Scheme
Pastikan aplikasi mobile Anda mendaftarkan Custom URL Scheme, misalnya dpuprapp://callback.
Daftarkan URL ini juga di Admin SSO > OAuth Clients.
Web Browser Session
Gunakan WebBrowser atau SafariViewController/ChromeCustomTabs untuk membuka halaman login SSO. Jangan gunakan WebView embedded karena alasan keamanan.
Contoh Flow (React Native - Expo AuthSession)
import * as AuthSession from 'expo-auth-session';
const discovery = {
authorizationEndpoint: 'https://sso.dpupr.com/oauth/authorize',
tokenEndpoint: 'https://sso.dpupr.com/oauth/token',
};
// ... inside component
const [request, response, promptAsync] = AuthSession.useAuthRequest(
{
clientId: 'your-mobile-client-id',
redirectUri: 'exp://localhost:19000/--/callback', // Expo Dev Client
scopes: ['read-profile'],
usePKCE: true, // Wajib ON
},
discovery
);
React.useEffect(() => {
if (response?.type === 'success') {
const { code } = response.params;
// Exchange code for token...
}
}, [response]);
Error Handling
| Status | Error | Deskripsi |
|---|---|---|
401 |
unauthenticated | Token tidak valid atau expired |
403 |
insufficient_scope | Token tidak memiliki scope yang diperlukan |
403 |
account_disabled | Akun user dinonaktifkan |
400 |
invalid_request | Parameter request tidak valid |