Security

CORS Configuration

Allowed origin rules, browser behavior, and safe expectations for cross-origin SSO consumers.

SSO Version

5.29.0

Overview

Cross-Origin Resource Sharing (CORS) allows your application to make secure requests to the SSO service from a different origin (domain). This is essential for OAuth 2.0 flows and API interactions.

Important

Your application's origin must be registered with the SSO admin before CORS requests will be allowed.

SSO CORS Policy

The SSO service implements the following CORS policy:

  • Allowed Origins: Only pre-registered origins (no wildcards)
  • Credentials: Cookies are allowed (Access-Control-Allow-Credentials: true)
  • Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
  • Headers: Content-Type, Authorization, X-Requested-With
  • ⚠️ Preflight Caching: 24 hours (Access-Control-Max-Age: 86400)

Registering Your Origin

To enable CORS for your application, contact the SSO administrator to register your origin(s):

  1. Determine your application's origin(s) (e.g., https://myapp.com)
  2. Contact SSO admin via email: sso@doneisbetter.com
  3. Provide the following information:
    • Your application name
    • Origin URL(s) (must be HTTPS in production)
    • OAuth client_id (if already issued)
    • Redirect URI(s) for OAuth callback
  4. Wait for admin approval (typically within 24 hours)

Local development note

For local development, http://localhost origins (any port) are automatically allowed.

CORS Headers in SSO Responses

When your origin is registered, the SSO service will include these headers in responses:

// Example SSO Response Headers
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With
Access-Control-Max-Age: 86400
Vary: Origin

// If origin is NOT registered:
HTTP/1.1 403 Forbidden
{ "error": "Origin not allowed" }

Client-Side CORS Configuration

Fetch API (Recommended)

// WHY: Include credentials (cookies) in cross-origin requests

const response = await fetch('https://sso.doneisbetter.com/api/public/session', {
  method: 'GET',
  credentials: 'include', // REQUIRED: Sends HTTP-only cookies
  headers: {
    'Content-Type': 'application/json'
  }
});

const data = await response.json();

Axios

import axios from 'axios';

// Global configuration
axios.defaults.withCredentials = true;

// Per-request configuration
const response = await axios.get(
  'https://sso.doneisbetter.com/api/public/session',
  { withCredentials: true }
);

XMLHttpRequest (Legacy)

const xhr = new XMLHttpRequest();
xhr.withCredentials = true; // REQUIRED for cookies
xhr.open('GET', 'https://sso.doneisbetter.com/api/public/session');
xhr.send();

Backend CORS Configuration (Your App)

If your backend needs to call SSO APIs, no CORS configuration is needed—server-to-server requests bypass CORS entirely.

However, if your frontend calls your backend, which then calls SSO, configure CORS on your backend:

Express.js

const cors = require('cors');

app.use(cors({
  origin: 'https://yourfrontend.com', // Your frontend origin
  credentials: true // Allow cookies
}));

Next.js API Routes

// pages/api/auth/[...].js
export default function handler(req, res) {
  res.setHeader('Access-Control-Allow-Origin', 'https://yourfrontend.com');
  res.setHeader('Access-Control-Allow-Credentials', 'true');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');

  if (req.method === 'OPTIONS') {
    return res.status(200).end();
  }

  // Handle actual request
}

Common CORS Errors

Error: "Origin not allowed"

Cause: Your origin is not registered with the SSO service.

Solution: Contact SSO admin to register your origin.

Error: "Credentials flag not set"

Cause: You're not sending credentials: 'include' in requests.

Solution: Add credentials: 'include' to fetch calls or withCredentials: true to Axios.

Error: "Preflight request failed"

Cause: OPTIONS preflight request is being blocked.

Solution: Ensure your origin is registered and you're using HTTPS (not HTTP) in production.

Testing CORS Configuration

// Test if your origin is allowed
fetch('https://sso.doneisbetter.com/api/health', {
  method: 'GET',
  credentials: 'include'
})
  .then(response => {
    console.log('CORS OK:', response.ok);
    console.log('Headers:', response.headers.get('Access-Control-Allow-Origin'));
  })
  .catch(error => {
    console.error('CORS Error:', error);
  });

Summary

  • ☑️ Contact SSO admin to register your origin
  • ☑️ Always use credentials: 'include' for API requests
  • ☑️ Use HTTPS in production (HTTP only for localhost development)
  • ☑️ Test CORS configuration before going live