curl -X POST "https://api.loyalty.lt/en/shop/auth/qr-login/generate" \
  -H "Content-Type: application/json" \
  -d '{
    "device_name": "My Desktop"
  }'
{
  "success": true,
  "data": {
    "session_id": "550e8400-e29b-41d4-a716-446655440000",
    "qr_code": "abcd1234efgh5678",
    "expires_at": "2024-01-15T14:35:00Z"
  }
}
QR Code authentication is the primary login method in Loyalty.lt, enabling secure authentication between desktop/web and mobile applications using real-time communication.

Overview

QR Code authentication allows users to securely log in to desktop or web applications by scanning a QR code with their mobile device. This method provides enhanced security and convenience.

Authentication Flow

1

Generate QR Code Session

Desktop/web application generates a unique QR code session
2

Display QR Code

QR code is displayed to user on desktop/web interface
3

User Scans QR Code

Authenticated user scans QR code using mobile app
4

User Confirms Login

User confirms login on mobile device
5

Receive Authentication

Desktop/web receives authentication tokens via real-time notification

Endpoints

Generate QR Login Session

curl -X POST "https://api.loyalty.lt/en/shop/auth/qr-login/generate" \
  -H "Content-Type: application/json" \
  -d '{
    "device_name": "My Desktop"
  }'
{
  "success": true,
  "data": {
    "session_id": "550e8400-e29b-41d4-a716-446655440000",
    "qr_code": "abcd1234efgh5678",
    "expires_at": "2024-01-15T14:35:00Z"
  }
}
API Path: POST /{locale}/shop/auth/qr-login/generate Parameters:
locale
string
required
Language locale code (en, lt, etc.)
device_name
string
Name of the device generating the QR session (max 255 characters)
Response:
session_id
string
Unique session identifier for tracking QR login process
qr_code
string
QR code string to be encoded and displayed to user
expires_at
string
Session expiration timestamp (5 minutes from creation)

Poll QR Login Status

curl -X GET "https://api.loyalty.lt/en/shop/auth/qr-login/poll/550e8400-e29b-41d4-a716-446655440000"
{
  "success": true,
  "data": {
    "session_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "pending",
    "expires_at": "2024-01-15T14:35:00Z"
  }
}
API Path: GET /{locale}/shop/auth/qr-login/poll/{sessionId} Parameters:
locale
string
required
Language locale code
sessionId
string
required
The session ID from generate QR endpoint
Response:
session_id
string
Session identifier
status
string
Current session status: pending, scanned, or confirmed
expires_at
string
Session expiration timestamp

Scan QR Code (Mobile App)

This endpoint requires the user to be authenticated via mobile app with valid JWT token.
curl -X POST "https://api.loyalty.lt/en/shop/auth/qr-login/scan/abcd1234efgh5678" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
{
  "success": true,
  "message": "QR code scanned successfully",
  "data": {
    "session_id": "550e8400-e29b-41d4-a716-446655440000",
    "device_name": "My Desktop"
  }
}
API Path: POST /{locale}/shop/auth/qr-login/scan/{qrCode} Parameters:
locale
string
required
Language locale code
qrCode
string
required
QR code string from the generated session
Headers:
Authorization
string
required
Bearer JWT token of authenticated mobile user
Response:
session_id
string
Session identifier that was scanned
device_name
string
Name of the device requesting authentication

Confirm QR Login (Mobile App)

curl -X POST "https://api.loyalty.lt/en/shop/auth/qr-login/confirm/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
{
  "success": true,
  "message": "QR login confirmed successfully"
}
API Path: POST /{locale}/shop/auth/qr-login/confirm/{sessionId} Parameters:
locale
string
required
Language locale code
sessionId
string
required
Session ID from the scanned QR code
Headers:
Authorization
string
required
Bearer JWT token of authenticated mobile user

Real-time Communication

The QR login system uses Ably for real-time communication to notify the desktop/web application when authentication status changes.

WebSocket Channel

Subscribe to: qr-login:{sessionId}

Event Types

Payload when scanned:
{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "scanned",
  "user": {
    "id": 123,
    "name": "John Doe"
  }
}
Payload when confirmed:
{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "confirmed",
  "user": {
    "id": 123,
    "name": "John Doe",
    "phone": "+37060000000",
    "email": "john@example.com"
  },
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
  "refresh_token": "def502004f4c7e1e3a5b...",
  "expires_in": 3600
}

Implementation Example

import { useEffect, useState } from 'react';
import Ably from 'ably/promises';

function QRLogin() {
  const [qrData, setQrData] = useState(null);
  const [status, setStatus] = useState('pending');
  const [authData, setAuthData] = useState(null);

  useEffect(() => {
    generateQRSession();
  }, []);

  const generateQRSession = async () => {
    const response = await fetch('/api/en/shop/auth/qr-login/generate', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ device_name: 'Web Browser' })
    });
    
    const data = await response.json();
    if (data.success) {
      setQrData(data.data);
      subscribeToUpdates(data.data.session_id);
    }
  };

  const subscribeToUpdates = (sessionId) => {
    const ably = new Ably.Realtime('YOUR_ABLY_KEY');
    const channel = ably.channels.get(`qr-login:${sessionId}`);
    
    channel.subscribe('qr_login_status', (message) => {
      const { status, token, refresh_token, user } = message.data;
      setStatus(status);
      
      if (status === 'confirmed' && token) {
        setAuthData({ token, refresh_token, user });
        // Store tokens and redirect user
        localStorage.setItem('auth_token', token);
        localStorage.setItem('refresh_token', refresh_token);
        window.location.href = '/dashboard';
      }
    });
  };

  return (
    <div>
      {qrData && (
        <div>
          <QRCodeDisplay value={qrData.qr_code} />
          <p>Status: {status}</p>
          {status === 'pending' && <p>Scan QR code with your mobile app</p>}
          {status === 'scanned' && <p>Confirm login on your mobile device</p>}
        </div>
      )}
    </div>
  );
}

Security Features

Error Handling

Error CodeDescriptionResolution
VALIDATION_ERRORInvalid request parametersCheck device_name length
QR_SESSION_NOT_FOUNDSession expired or doesn’t existGenerate new QR session
AUTH_REQUIREDMobile user not authenticatedLogin to mobile app first
QR_CODE_NOT_FOUNDQR code expired or invalidGenerate new QR code
QR_SESSION_UNAUTHORIZEDUser not authorized for sessionUse same account that scanned QR
QR_GENERATION_ERRORFailed to create QR sessionTry again or contact support
QR_SCAN_ERRORFailed to scan QR codeCheck network and try again
QR_CONFIRM_ERRORFailed to confirm loginCheck authentication and retry