Skip to main content

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:

  1. Payment Integration configured (to receive callbacks)
  2. 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

ParameterValueDescription
auto_logintrueIndicates this is an auto-login redirect
joker_logintrueConfirms the redirect originates from Kukuruku
custom4https://auth.kukuruku.win/realms/publicKukurukuID issuer URL — use this for OAuth authentication

Order Parameters

ParameterValueDescription
order_idUUIDOrder identifier in KukuPay
custom2UUIDSame as order_id (duplicate for compatibility)

Tracking Parameters

ParameterDescription
sub_id1Affiliate ID
sub_id2Traffic source
sub_id3Link ID
sub_id4Creative ID
sub_id5User UUID
aff_click_idAffiliate click ID
custom1Test flag
custom3Always 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 });
});
Important

The payment callback and the user redirect may arrive in any order. Your implementation must handle both sequences:

  1. User arrives first, callback later — create user session, credit balance when callback arrives
  2. 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 });
});