Skip to content

Authorization Ticket Integration

Target Audience: Developers implementing Tulo Shop integration for sites not using Tulo Payway SSO2

Overview

Authorization tickets enable seamless Single Sign-On (SSO) between your site and Tulo Shop, allowing users to:

  1. Log into Tulo Shop from your site without re-entering credentials
  2. Return to your site after purchase automatically logged in

This guide is for sites that manage their own authentication and do not use Tulo Payway SSO2 for login.

When to Use Authorization Tickets

Use this integration method when:

  • Your site has its own authentication system (not Tulo Payway SSO2)
  • You want seamless SSO between your site and Tulo Shop
  • Users should be able to move between systems without re-logging in

How It Works

Authorization tickets are short-lived, one-time use codes that can be exchanged for a Payway access token tied to a user's identity. These tickets are generated via the Payway API.

Detailed Documentation

For a comprehensive technical reference on authorization tickets, see Ticket Authentication in the Payway documentation.

The flow consists of two scenarios:

Scenario 1: Sending Users to Tulo Shop

When a logged-in user on your site wants to make a purchase:

graph LR
    A[Your Site<br/>User logged in] --> B[Generate Ticket<br/>via Payway API]
    B --> C[Redirect to Shop<br/>with ticket in URL]
    C --> D[Tulo Shop<br/>User automatically logged in]

Scenario 2: Receiving Users Back After Purchase

When a user completes a purchase and returns to your site:

graph LR
    A[User completes purchase<br/>in Tulo Shop] --> B[Shop generates ticket<br/>for your domain]
    B --> C[User redirected to<br/>your site with ticket]
    C --> D[Your site validates ticket<br/>User automatically logged in]

Prerequisites

Before implementing authorization ticket integration, ensure you have:

1. Payway API Access

  • API Client ID (for your site)
  • API Client Secret
  • Server-to-server access token capability
  • Access to Payway Authorization API endpoints

2. Tulo Shop Configuration

Contact Tulo support to configure your domain in Tulo Shop's TicketConfiguration. You'll need to choose an integration mode:

Option A: ReturnUrl Mode (Recommended) : Tickets are appended directly to your return URL as a query parameter : Best for simple integrations where your site handles ticket validation on the main domain

Option B: SeparateTicketAuth Mode : Tickets are sent to a separate authentication endpoint with the final destination in a returnUrl parameter : Best for centralized authentication servers or when using a separate auth subdomain

Provide to Tulo support:

  • Your domain name (e.g., news.example.com)
  • Your Payway Client ID
  • Preferred integration mode
  • Auth endpoint URL (if using SeparateTicketAuth mode)

3. HTTPS Certificate

All ticket exchanges must use HTTPS for security.


Implementation: Sending Users to Tulo Shop

Step 1: Generate Authorization Ticket

When a logged-in user needs to visit Tulo Shop, generate an authorization ticket via the Payway API.

Detailed API Documentation

For complete details on generating authorization tickets, including request/response formats and error handling, see Ticket Authentication - Origin Application.

Key points:

  • Use an access token tied to the user's identity (not a server-to-server token)
  • The access token must have the /api/authorization/ticket scope
  • Send the Tulo Shop client_id as the only parameter
  • The user's identity comes from the access token itself
  • Tickets are short-lived and can only be used once
  • Generate tickets just-in-time before redirecting the user

Step 2: Redirect User to Tulo Shop

Build the Tulo Shop URL with the ticket in the at query parameter and include a returnUrl parameter so the user can return to your site after purchase.

URL Format:

https://shop.example.com/marketplace/{groupId}/{marketplaceId}?at={ticket}&returnUrl={your_site_url}

Parameters:

Parameter Required Description
at Yes The authorization ticket
returnUrl Recommended URL where the user should return after purchase
campaign Optional Pre-select a campaign
period Optional Pre-select a payment period

Always Include returnUrl

The returnUrl parameter is essential for Scenario 2 (receiving users back). Always include it so users can seamlessly return to your site after purchase.


Implementation: Receiving Users Back from Tulo Shop

After completing a purchase, Tulo Shop will redirect the user back to your site with an authorization ticket. Your site must validate this ticket and create a session.

Understanding the Return Flow

When Tulo Shop redirects the user:

  1. User completes purchase - User selects a product, creates account (if new), and completes payment
  2. Automatic login in Shop - If the user created a new account, they are automatically logged into Tulo Shop
  3. Order confirmation - User sees "Thank you" page with a "Return" button
  4. Ticket generation - When user clicks "Return", Shop generates a ticket for your domain
  5. Redirect to your site - User is redirected to your returnUrl with the ticket

Receiving the Ticket

The URL format depends on the integration mode configured:

User arrives directly at your return URL with the ticket:

https://yoursite.com/welcome-back?ticket={authorization_ticket}

SeparateTicketAuth Mode

User arrives at your dedicated auth endpoint:

https://auth.yoursite.com/ticket-login?ticket={ticket}&returnUrl=https://yoursite.com/welcome-back

Your auth endpoint validates the ticket, then redirects to the returnUrl.

Step 1: Validate Ticket with Payway

Exchange the ticket for an access token using the Payway API:

POST https://payway-api.example.com/api/authorization/access_token
Content-Type: application/json

{
  "grant_type": "ticket",
  "ticket": "{received_ticket}",
  "client_id": "{your_client_id}",
  "client_secret": "{your_client_secret}"
}

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "..."
}

Step 2: Get User Account Information

Use the access token to fetch user details:

GET https://payway-api.example.com/external/api/v1/me/
Authorization: Bearer {access_token}

Response:

{
  "id": "account_123",
  "email": "user@example.com",
  "firstName": "John",
  "lastName": "Doe",
  "customerNumber": "CUST001"
}

Step 3: Create Session and Log In User

After successfully validating the ticket and retrieving user information, your site needs to:

  1. Create a session for the user using your site's session management
  2. Store user information in the session (user ID, email, name, Payway account ID, etc.)
  3. Optionally store the access token if you need to make future API calls to Payway on behalf of the user
  4. Redirect the user to the final destination or remove the ticket from the URL for cleaner URLs

Implementation details will vary based on your technology stack and existing authentication system. The key is to establish an authenticated session that integrates with your site's existing user management.


Complete Round-Trip Example

Here's how the complete flow works when a user comes from your site, purchases a subscription, and returns:

1. User on Your Site (Logged In)

User is logged into: https://yoursite.com
User clicks: "Upgrade to Premium"

2. Your Site Generates Ticket

// Generate ticket via Payway API
const ticket = await generateTicket(user.paywayAccountId);

// Redirect to Shop with ticket and returnUrl
const shopUrl = `https://shop.example.com/marketplace/group1/market1` +
  `?at=${ticket}` +
  `&returnUrl=${encodeURIComponent('https://yoursite.com/welcome-back')}`;

res.redirect(shopUrl);

Result: https://shop.example.com/marketplace/group1/market1?at=xyz123...&returnUrl=https://yoursite.com/welcome-back

3. User in Tulo Shop (Automatically Logged In)

  • User lands in Tulo Shop already logged in (via ticket)
  • User selects subscription product
  • User completes payment
  • User sees order confirmation: "Thank you for your purchase!"
  • User sees "Return to yoursite.com" button

4. User Clicks "Return" Button

Tulo Shop: - Checks if user is logged in: ✓ - Looks up yoursite.com in its TicketConfiguration - Generates authorization ticket for your domain - Redirects to: https://yoursite.com/welcome-back?ticket=abc789...

5. Your Site Receives User with Ticket

// GET /welcome-back?ticket=abc789...

app.get('/welcome-back', async (req, res) => {
  const ticket = req.query.ticket;

  if (ticket) {
    // Validate ticket and create session
    await handleTicketLogin(req, ticket);
    // User is now logged in on your site
    return res.redirect('/welcome-back'); // Remove ticket from URL
  }

  // Show welcome page
  res.render('welcome-back', { user: req.session.user });
});

Result

✅ User upgraded subscription in Tulo Shop ✅ User is logged into Tulo Shop ✅ User is logged into your site ✅ User can access premium content


Security Best Practices

Ticket Handling

Critical Security Measures

  1. Use tickets immediately - Tickets are short-lived
  2. One-time use only - Each ticket can only be exchanged once
  3. Never log tickets - Tickets are sensitive credentials (like passwords)
  4. HTTPS only - All ticket exchanges must use HTTPS
  5. Validate quickly - Don't delay between receiving ticket and validation

Prevent Ticket Reuse

Implement ticket reuse prevention to avoid security vulnerabilities:

// In-memory cache for processed tickets (use Redis in production)
const processedTickets = new Set();

async function handleTicketLogin(req, ticket) {
  // Check if ticket already used
  if (processedTickets.has(ticket)) {
    throw new Error('Ticket already used');
  }

  try {
    // Validate ticket with Payway
    const accessToken = await validateTicket(ticket);

    // Mark ticket as processed
    processedTickets.add(ticket);

    // Set timeout to clean up old tickets (tickets are short-lived anyway)
    setTimeout(() => processedTickets.delete(ticket), 120000);

    // Create session...
  } catch (error) {
    // Don't mark as processed if validation fails
    throw error;
  }
}

Session Security

Configure secure session settings:

// Express.js example
app.use(session({
  secret: process.env.SESSION_SECRET,
  name: 'yoursite.sid',
  cookie: {
    httpOnly: true,        // Prevents JavaScript access
    secure: true,          // HTTPS only
    sameSite: 'lax',       // CSRF protection
    maxAge: 1800000        // 30 minutes
  },
  resave: false,
  saveUninitialized: false
}));

Error Handling

Ticket Validation Errors

Handle common error scenarios gracefully:

async function handleTicketLogin(req, ticket) {
  try {
    // Validate ticket...
    return true;
  } catch (error) {
    if (error.response?.status === 401) {
      // Invalid or expired ticket
      console.error('Ticket validation failed: Invalid or expired ticket');
      return false;
    }

    if (error.response?.status === 400) {
      // Malformed ticket
      console.error('Ticket validation failed: Malformed ticket');
      return false;
    }

    // Other errors (network, server errors)
    console.error('Ticket validation failed:', error.message);
    return false;
  }
}

User-Facing Error Messages

Provide clear, actionable error messages:

app.get('/welcome-back', async (req, res) => {
  const ticket = req.query.ticket;

  if (ticket) {
    const loginSuccess = await handleTicketLogin(req, ticket);

    if (!loginSuccess) {
      // Show error message to user
      return res.render('error', {
        title: 'Login Failed',
        message: 'Your login link has expired or is invalid. Please log in again.',
        actionLink: '/login',
        actionText: 'Go to Login'
      });
    }
  }

  // Continue...
});

Testing

Test Checklist

  • [ ] Generate ticket - Your site can successfully generate tickets via Payway API
  • [ ] Redirect to Shop - User redirects to Tulo Shop with ticket in URL
  • [ ] Auto-login in Shop - User lands in Shop already logged in
  • [ ] Complete purchase - User can select and purchase products
  • [ ] Return with ticket - User returns to your site with ticket in URL
  • [ ] Validate ticket - Your site successfully validates ticket with Payway API
  • [ ] Create session - User session is created on your site
  • [ ] Access content - User can access protected content
  • [ ] Ticket expiry - Expired tickets are properly rejected
  • [ ] Ticket reuse - Used tickets cannot be reused
  • [ ] HTTPS enforcement - All ticket exchanges use HTTPS
  • [ ] Error handling - Invalid tickets show user-friendly error messages

Testing Environments

Stage Environment: - Tulo Shop: https://shop-stage.example.com - Payway API: https://payway-api-stage.example.com

Production Environment: - Tulo Shop: https://shop.example.com - Payway API: https://payway-api.example.com

Test with Stage First

Always test the complete integration in the stage environment before deploying to production.


Troubleshooting

Issue: User Not Logged Into Shop

Symptoms: User arrives at Shop but is not logged in

Possible Causes:

  1. Ticket expired (generated too early)
  2. Ticket malformed or missing from URL
  3. Wrong Client ID used when generating ticket
  4. Ticket already used (clicked link twice)

Solutions:

  • Generate tickets just-in-time before redirect
  • Verify ticket is correctly appended to URL
  • Confirm you're using the correct Tulo Shop Client ID
  • Implement ticket reuse prevention

Issue: User Returns Without Ticket

Symptoms: User returns to your site but URL has no ticket parameter

Possible Causes:

  1. Your domain not configured in Tulo Shop's TicketConfiguration
  2. User not logged into Shop when clicking "Return"
  3. Wrong integration mode configured

Solutions:

  • Contact Tulo support to verify your domain is configured
  • Ensure user completed purchase and was auto-logged in
  • Verify configuration mode (ReturnUrl vs SeparateTicketAuth) matches your implementation

Issue: Ticket Validation Fails

Symptoms: Your site receives ticket but Payway API returns 401 Unauthorized

Possible Causes:

  1. Wrong Client ID or Client Secret
  2. Ticket expired before validation
  3. Ticket already used
  4. Network/connectivity issues

Solutions:

  • Verify Payway API credentials (Client ID and Secret)
  • Minimize time between receiving ticket and validation
  • Check if ticket was already processed (implement reuse prevention)
  • Check network connectivity to Payway API

Issue: Session Not Created

Symptoms: Ticket validates successfully but user not logged in

Possible Causes:

  1. Session save failing silently
  2. Cookie domain mismatch
  3. CORS issues (if using separate auth endpoint)
  4. Session not persisted to storage

Solutions:

  • Add detailed logging to session creation
  • Verify cookie configuration (domain, secure, httpOnly)
  • Check browser console for errors
  • Ensure session storage (Redis, database) is working

API Reference

Generate Ticket

Generate an authorization ticket for a user.

Endpoint: POST /api/authorization/ticket

Headers:

Authorization: Bearer {s2s_access_token}
Content-Type: application/json

Request Body:

{
  "accountId": "string",
  "clientId": "string"
}

Response:

{
  "ticket": "string"
}

Status Codes: - 200 OK - Ticket generated successfully - 401 Unauthorized - Invalid access token - 400 Bad Request - Invalid accountId or clientId


Exchange Ticket for Access Token

Exchange an authorization ticket for an access token.

Endpoint: POST /api/authorization/access_token

Headers:

Content-Type: application/json

Request Body:

{
  "grant_type": "ticket",
  "ticket": "string",
  "client_id": "string",
  "client_secret": "string"
}

Response:

{
  "access_token": "string",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "string"
}

Status Codes: - 200 OK - Token issued successfully - 401 Unauthorized - Invalid ticket, client_id, or client_secret - 400 Bad Request - Malformed request


Get User Account

Retrieve the authenticated user's account information.

Endpoint: GET /external/api/v1/me/

Headers:

Authorization: Bearer {access_token}

Response:

{
  "id": "string",
  "email": "string",
  "firstName": "string",
  "lastName": "string",
  "customerNumber": "string",
  "address": {
    "street": "string",
    "zipCode": "string",
    "city": "string",
    "countryCode": "string"
  }
}

Status Codes: - 200 OK - User information retrieved successfully - 401 Unauthorized - Invalid or expired access token


Support

For assistance with authorization ticket integration:

  1. Configuration Issues - Contact Tulo support to verify your domain configuration
  2. Technical Implementation - Refer to code examples in this guide
  3. Payway API Issues - Contact Tulo Payway API support

When contacting support, include:

  • Your domain name
  • Integration mode (ReturnUrl or SeparateTicketAuth)
  • Error messages or logs (without sensitive data like tickets or tokens)
  • Steps to reproduce the issue
  • Environment (stage or production)