Skip to main content

How UIP Authentication Works

UIP uses a simple two-path UX based on the user’s device. Your application detects the device type and shows the appropriate interface:

Desktop Flow

Display the QR code image returned by the API. The user scans it with their UIP app to complete verification.

Mobile Flow

Display an “Open UIP” button that deep links into the UIP app. No QR code scanning needed on mobile.

Implementation Flow

1

Create a Session

Call POST /v1/identify or POST /v1/sign with your intent. The API returns a session_id, qr_code (base64 PNG data URI), and expires_at.
const session = await fetch('https://api.uip.digital/v1/identify', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    intent: 'Sign in to My App',
    requested_data: ['first_name', 'last_name']
  })
}).then(r => r.json());
// session = { session_id, qr_code, expires_at }
2

Detect Device Type

Use user-agent detection to determine if the user is on mobile or desktop:
const isMobile = /iPhone|iPad|Android/i.test(navigator.userAgent);
3

Display QR Code (Desktop) or Deep Link (Mobile)

Desktop: Display the qr_code from the API response as an image. It is a base64-encoded PNG data URI that you can use directly as an <img> src.Mobile: Display an “Open UIP” button linking to https://www.uip.id/{session_id}. This deep links into the UIP app.
<div id="uip-desktop">
  <img id="uip-qr" alt="Scan with UIP app to verify identity" />
  <p>Scan with UIP app</p>
</div>

<div id="uip-mobile" style="display: none;">
  <a id="uip-link" class="button">Open UIP</a>
</div>

<script>
  const isMobile = /iPhone|iPad|Android/i.test(navigator.userAgent);

  if (isMobile) {
    document.getElementById('uip-desktop').style.display = 'none';
    document.getElementById('uip-mobile').style.display = 'block';
    document.getElementById('uip-link').href =
      `https://www.uip.id/${sessionId}`;
  } else {
    // qr_code from API response is a base64-encoded PNG data URI
    document.getElementById('uip-qr').src = qrCode;
  }
</script>
4

Poll for Completion

Poll GET /v1/identify/:id (or GET /v1/sign/:id) every 2-3 seconds. When the status changes to completed, all verified data is included in the response.
async function pollForResult(sessionId, apiKey) {
  while (true) {
    const res = await fetch(
      `https://api.uip.digital/v1/identify/${sessionId}`,
      { headers: { 'Authorization': `Bearer ${apiKey}` } }
    );
    const data = await res.json();

    if (data.status === 'completed') return data;
    if (data.status === 'expired') throw new Error('Session expired');

    await new Promise(r => setTimeout(r, 2500));
  }
}
5

Use the Verified Data

The completed response includes all requested identity data (or signature proof). Use it to complete the user’s action.
No webhooks needed for Identify and Sign. The polling flow is the primary integration pattern. Webhooks are only used for the Message API and Authorize API.
Future SDK: A client-side SDK is planned that will handle device detection, QR rendering, and polling automatically. For now, implement this logic in your application.

QR Code Details

The qr_code field in the API response is a base64-encoded PNG data URI. It encodes a URL in the format https://www.uip.id/{session_id}.

Using the QR Code

The QR code is ready to use directly as an image source:
// qr_code from API is like: "data:image/png;base64,iVBORw0KGgo..."
document.getElementById('qr-img').src = session.qr_code;
You do not need to generate your own QR code — the API provides it.

QR Code Display Best Practices

  • Minimum size: 200x200 pixels for reliable scanning
  • Recommended: 256x256 to 300x300 pixels
  • Center the QR code prominently on the page
  • Add adequate white space (quiet zone) around the QR code
  • Show loading indicator while waiting for scan
  • Display clear instructions: “Scan with UIP app”
  • Add animated elements to draw attention to the QR code
  • Show a countdown timer for session expiration
  • Handle expired sessions gracefully (5-minute expiry)
  • Show “Try Again” button to generate a new session
  • Display clear error messages for connection issues
  • Provide fallback options if QR scanning fails
  • Provide alt text for screen readers
  • Include text instructions alongside QR code
  • Ensure sufficient color contrast for visibility
  • Consider alternative authentication methods for accessibility

Session Management

Session Expiration

Sessions expire after 5 minutes. Always check expiration status and generate new sessions as needed. Show a timer to the user.

One-Time Use

Each session is single-use. After the user completes verification, the session cannot be reused.

HTTPS Required

All UIP integrations must use HTTPS in production to prevent man-in-the-middle attacks.

Concurrent Sessions

Support multiple concurrent sessions for users authenticating from different tabs or devices.

Updating the Frontend

Use WebSockets, Server-Sent Events, or short polling from your frontend to detect when the backend receives a completed result.

WebSockets

Best for real-time bidirectional communication. Ideal for dashboards and interactive applications.

Server-Sent Events

Simple one-way updates from server to client. Perfect for status updates and notifications.

Short Polling

Poll your own backend every 2-3 seconds. Simple and works everywhere as a fallback.

Testing QR Flows

1

Use Your $5 Signup Credit

New accounts receive $5 in credits — enough for extensive testing
2

Create Your UIP Identity

Create your own UIP identity to test the full flow end-to-end
3

Test Device Detection

Verify your device detection logic shows QR codes on desktop and deep link buttons on mobile
4

Test Error Scenarios

Test session expiration, user cancellation, and network errors to ensure proper error handling

Next Steps

Quickstart

Build your first integration with working code

Identify API

Full API reference for authentication

Error Handling

Handle errors gracefully