Auto-Login Integration (Play Button)
When a user clicks the "Play" button on a merchant card in Kukuruku, the system automatically creates and pays an order, then redirects the user to the merchant's platform with authentication parameters. This provides a seamless one-click experience.
Prerequisites
To support auto-login, you must have both:
- Payment Integration configured (to receive callbacks)
- KukurukuID OAuth 2.0 configured (to authenticate users)
How It Works
User clicks "Play" on Kukuruku
|
v
Kukuruku creates order (POST /api/v1/orders/payins)
|
v
Kukuruku pays order from user's KukuPay balance
|
v
User is redirected to your platform URL with parameters:
https://your-site.com/?auto_login=true&custom4=...&order_id=...
|
v
Your platform detects auto_login=true
|
v
Your platform initiates OAuth login using issuer from custom4
|
v
User is authenticated, balance is credited via callback
Redirect Parameters
When a user is redirected to your platform, the URL includes these query parameters:
Authentication Parameters
| Parameter | Value | Description |
|---|---|---|
auto_login | true | Indicates this is an auto-login redirect |
joker_login | true | Confirms the redirect originates from Kukuruku |
custom4 | https://auth.kukuruku.win/realms/public | KukurukuID issuer URL — use this for OAuth authentication |
Order Parameters
| Parameter | Value | Description |
|---|---|---|
order_id | UUID | Order identifier in KukuPay |
custom2 | UUID | Same as order_id (duplicate for compatibility) |
Tracking Parameters
| Parameter | Description |
|---|---|
sub_id1 | Affiliate ID |
sub_id2 | Traffic source |
sub_id3 | Link ID |
sub_id4 | Creative ID |
sub_id5 | User UUID |
aff_click_id | Affiliate click ID |
custom1 | Test flag |
custom3 | Always true |
Example URL
https://your-site.com/login?
auto_login=true&
joker_login=true&
custom3=true&
custom4=https%3A%2F%2Fauth.kukuruku.win%2Frealms%2Fpublic&
order_id=550e8400-e29b-41d4-a716-446655440000&
custom2=550e8400-e29b-41d4-a716-446655440000&
sub_id5=7e77c7af-50a1-411d-8e3c-5eeda15891fc
Implementation Guide
Step 1: Detect Auto-Login
Check for the auto_login=true parameter on your landing page:
const params = new URLSearchParams(window.location.search);
if (params.get('auto_login') === 'true') {
const issuerUrl = params.get('custom4');
const orderId = params.get('order_id');
// Initiate OAuth login
initiateKukurukuLogin(issuerUrl, orderId);
}
Step 2: Authenticate via KukurukuID
Use the custom4 parameter as the OAuth issuer URL to initiate the Authorization Code Flow:
function initiateKukurukuLogin(issuerUrl, orderId) {
const state = JSON.stringify({ orderId });
const authUrl = `${issuerUrl}/protocol/openid-connect/auth` +
`?client_id=${YOUR_CLIENT_ID}` +
`&redirect_uri=${encodeURIComponent(YOUR_CALLBACK_URL)}` +
`&response_type=code` +
`&scope=openid+profile+email` +
`&state=${encodeURIComponent(state)}`;
window.location.href = authUrl;
}
Step 3: Handle OAuth Callback
Exchange the authorization code for tokens and identify the user:
app.get('/callback', async (req, res) => {
const { code, state } = req.query;
const { orderId } = JSON.parse(state);
// Exchange code for tokens
const tokens = await exchangeCodeForTokens(code);
// Get user profile
const user = await getUserProfile(tokens.access_token);
// Find or create user in your system by email
const localUser = await findOrCreateUser(user.data.email);
// Store order context for callback matching
await storeOrderContext(orderId, localUser.id);
// Redirect to your platform
res.redirect('/dashboard');
});
Step 4: Handle Payment Callback
Kukuruku sends a payment callback asynchronously. When you receive it:
app.post('/kukuruku/callback', (req, res) => {
// 1. Verify signature
const isValid = verifySignature(req.body, req.headers.signature);
if (!isValid) return res.status(401).json({ success: false });
// 2. Find user by email from callback
const user = findUserByEmail(req.body.user_email);
// 3. Credit balance
if (req.body.status === 'paid') {
creditUserBalance(user.id, req.body.amount, req.body.currency);
}
res.json({ success: true });
});
The payment callback and the user redirect may arrive in any order. Your implementation must handle both sequences:
- User arrives first, callback later — create user session, credit balance when callback arrives
- Callback arrives first, user later — credit balance, create user session when user arrives
Use user_email from the callback to match the user authenticated via OAuth.
Merchant URL Configuration
Your platform URL(s) are configured in the Kukuruku system. Each merchant can have multiple URLs (for A/B testing or load balancing). The system selects one randomly for each redirect.
Contact the Kukuruku team to register or update your platform URLs.
Complete Example (Express.js)
const express = require('express');
const axios = require('axios');
const sha512 = require('js-sha512').sha512;
const AUTH_URL = 'https://auth.kukuruku.win/realms/public';
const API_URL = 'https://api.kukuruku.win';
const CLIENT_ID = 'your-client-id';
const CLIENT_SECRET = 'your-client-secret';
const SECRET_KEY = 'your-merchant-secret-key';
const CALLBACK_URL = 'https://your-site.com/auth/callback';
const app = express();
app.use(express.json());
// Landing page — detect auto-login
app.get('/', (req, res) => {
if (req.query.auto_login === 'true') {
const issuer = req.query.custom4;
const orderId = req.query.order_id;
const state = Buffer.from(JSON.stringify({ orderId })).toString('base64');
return res.redirect(
`${issuer}/protocol/openid-connect/auth` +
`?client_id=${CLIENT_ID}` +
`&redirect_uri=${encodeURIComponent(CALLBACK_URL)}` +
`&response_type=code` +
`&scope=openid+profile+email` +
`&state=${state}`
);
}
res.render('home');
});
// OAuth callback
app.get('/auth/callback', async (req, res) => {
const { code, state } = req.query;
const { orderId } = JSON.parse(
Buffer.from(state, 'base64').toString()
);
// Exchange code for tokens
const { data: tokens } = await axios.post(
`${AUTH_URL}/protocol/openid-connect/token`,
new URLSearchParams({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
grant_type: 'authorization_code',
code,
redirect_uri: CALLBACK_URL,
})
);
// Get user profile from Kukuruku API
const { data: profile } = await axios.get(`${API_URL}/api/v1/me`, {
headers: { Authorization: `Bearer ${tokens.access_token}` },
});
// Find or create user by Kukuruku ID
const user = await findOrCreateUser({
kukurukuId: profile.data.id,
email: tokens.id_token, // decode to get email
name: profile.data.first_name,
});
// Create session
req.session.userId = user.id;
req.session.orderId = orderId;
res.redirect('/dashboard');
});
// Kukuruku payment callback
app.post('/kukuruku/callback', (req, res) => {
// Verify HMAC-SHA512 signature
const expectedSignature = sha512.hmac(
SECRET_KEY, JSON.stringify(req.body)
);
if (expectedSignature !== req.headers.signature) {
return res.status(401).json({ success: false });
}
// Process payment
if (req.body.status === 'paid') {
creditBalance(req.body.user_email, req.body.amount, req.body.currency);
}
res.json({ success: true });
});