Skip to content

Partner IdP SSO Integration Guide

This guide provides a comprehensive walkthrough for integrating your organization's OIDC identity provider with Contio for seamless single sign-on (SSO) authentication.

Overview

Partner IdP SSO enables your users to authenticate with Contio using your organization's existing identity provider. Instead of managing separate Contio credentials, users sign in through your corporate SSO system for seamless access.

OAuth Connection Required

Before users can authenticate via SSO, they must first establish a connection between their Contio account and your partner app via OAuth. This ensures users have explicitly consented to the partner relationship. SSO provides authentication convenience using corporate IdP credentials, not user provisioning.

Key Benefits

Partner IdP SSO provides unified authentication by allowing users to access Contio with their existing corporate credentials, eliminating the need for separate passwords. This reduces user friction since there's no additional password management required for Contio access after the initial OAuth connection. The integration supports enterprise security compliance by leveraging your existing identity governance, MFA policies, and access controls.

Supported Identity Providers

Contio supports any OIDC-compliant identity provider, including Okta, Auth0, Azure AD (organizational tenants), OneLogin, Ping Identity, and custom OIDC implementations.

Blocked Public Providers

Public consumer identity providers cannot be used for Partner IdP SSO because Contio already supports them natively. The following providers are blocked: Google (accounts.google.com), Microsoft consumer accounts (login.microsoftonline.com/consumers), and Zoho (accounts.zoho.com). Use Contio's native social login for these providers instead. Note that Microsoft Azure AD for organizations (tenant-specific endpoints) is fully supported.

Prerequisites

Before configuring Partner IdP SSO, ensure you have the following:

Partner App Requirements

Your partner app must be registered with Contio and have an active status. You'll need your Partner API Key and Client ID for authentication when configuring the IdP. If you haven't registered your partner app yet, contact Contio support to begin the onboarding process.

Identity Provider Requirements

Your OIDC identity provider must expose a discovery endpoint (.well-known/openid-configuration) over HTTPS. You'll need to create an OAuth/OIDC application in your IdP admin console and obtain the Client ID and Client Secret. The IdP must support the authorization code flow with PKCE and return ID tokens containing at minimum the user's email address.

Domain Configuration

For strict mode (recommended for enterprise deployments), you must specify the email domains that are authorized to use SSO. These domains must be corporate domains owned by your organization. Generic email domains (gmail.com, yahoo.com, etc.) are not allowed, and each domain can only be claimed by one partner to prevent conflicts.

Partner Slug

Your partner app has a unique slug used in the SSO entry URL (/p/{slug}). This slug is auto-generated from your company name during registration but can be customized via the Partner Admin API. The slug must be lowercase alphanumeric with hyphens, between 3-63 characters, and cannot use reserved terms.

IdP Configuration

Configure your identity provider using the Partner Admin API. Each partner app can have one IdP configuration.

Create IdP Configuration

// Note: IdP configuration methods coming soon to SDK
// For now, use direct API calls:

const response = await fetch('https://api.contio.ai/v1/partner/admin/idp', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.CONTIO_API_KEY,
    'X-Client-ID': process.env.CONTIO_CLIENT_ID,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Acme Corporate SSO',
    discovery_url: 'https://login.acme.com/.well-known/openid-configuration',
    // Note: idp_client_id and idp_client_secret are credentials from YOUR Identity Provider
    // (e.g., Okta, Azure AD), NOT your Contio Partner OAuth credentials
    idp_client_id: 'contio-integration-prod',
    idp_client_secret: 'your-client-secret-from-idp',
    scopes: ['openid', 'email', 'profile'],
    claim_mappings: {
      email: 'email',
      name: 'name'
    },
    mode: 'strict',
    allowed_email_domains: ['acme.com', 'acme.co.uk']
  })
});

const config = await response.json();
console.log('SSO Entry URL:', `https://app.contio.ai/p/${config.partner_slug}`);

Retrieve IdP Configuration

const response = await fetch('https://api.contio.ai/v1/partner/admin/idp', {
  method: 'GET',
  headers: {
    'X-API-Key': process.env.CONTIO_API_KEY,
    'X-Client-ID': process.env.CONTIO_CLIENT_ID
  }
});

const config = await response.json();

Update IdP Configuration

All fields are optional for updates. Only include the fields you want to change:

const response = await fetch('https://api.contio.ai/v1/partner/admin/idp', {
  method: 'PUT',
  headers: {
    'X-API-Key': process.env.CONTIO_API_KEY,
    'X-Client-ID': process.env.CONTIO_CLIENT_ID,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Updated SSO Name',
    allowed_email_domains: ['acme.com', 'acme.co.uk', 'newdomain.com'],
    is_active: true,
    // To update IdP credentials, use idp_client_id and idp_client_secret:
    // idp_client_id: 'new-client-id-from-idp',
    // idp_client_secret: 'new-client-secret-from-idp'
  })
});

Delete IdP Configuration

const response = await fetch('https://api.contio.ai/v1/partner/admin/idp', {
  method: 'DELETE',
  headers: {
    'X-API-Key': process.env.CONTIO_API_KEY,
    'X-Client-ID': process.env.CONTIO_CLIENT_ID
  }
});
// Returns 204 No Content on success

Domain Validation Modes

The mode field controls how user email domains are validated during SSO:

Mode Description Use Case
strict Requires allowed_email_domains to be specified. Only users with email addresses matching these domains can authenticate. Generic domains are blocked, and cross-partner domain exclusivity is enforced. Enterprise partners with known corporate domains
partner_managed Domain list is optional. If provided, the same validation rules apply. If empty, the partner's IdP controls access entirely. Important: All users must have a prior OAuth connection to your partner app before they can use SSO. Multi-tenant platforms managing diverse user bases

Partner Connection Requirement

All users must have previously authorized your partner app via OAuth before they can use SSO. This applies to both strict and partner_managed modes. SSO provides authentication convenience using corporate IdP credentials, not user provisioning. Users must first create a Contio account and connect via OAuth to establish the partner relationship.

Claim Mappings

The claim_mappings field maps your IdP's claim names to Contio user fields. Most OIDC-compliant IdPs use standard claim names, but you can customize mappings for non-standard implementations:

Standard OIDC IdP (default mappings):

{
  "claim_mappings": {
    "email": "email",
    "name": "name"
  }
}

Custom IdP with non-standard claims:

{
  "claim_mappings": {
    "email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
    "name": "displayName",
    "given_name": "firstName",
    "family_name": "lastName"
  }
}

Contio Field Purpose Required
email User's email address for account linking Yes
name User's display name No
given_name User's first name No
family_name User's last name No

Integration Flow

The Partner IdP SSO flow uses PKCE-based authorization with server-side session management for security.

Flow Diagram

sequenceDiagram
    participant User
    participant PartnerApp as "Partner App"
    participant ContioLanding as "Contio /p/{slug}"
    participant PartnerIdP as "Partner IdP"
    participant ContioAPI as "Contio API"
    participant Desktop as "Contio Desktop"

    PartnerApp->>ContioLanding: GET /p/{slug}?target=desktop
    ContioLanding->>ContioAPI: GET /v1/partner/sso/info/{slug}
    ContioAPI-->>ContioLanding: Partner config + IdP status
    ContioLanding->>ContioLanding: Display partner-branded page

    ContioLanding->>ContioAPI: GET /v1/partner/sso/initiate?slug={slug}
    ContioAPI-->>ContioLanding: authorization_url + session_id
    ContioLanding->>PartnerIdP: Redirect to authorization_url
    alt User has active IdP session
        Note over PartnerIdP: Session valid - no prompt
    else No active session
        User->>PartnerIdP: Enter credentials
    end
    PartnerIdP-->>ContioAPI: GET /v1/partner/sso/callback?code=...&state=...

    ContioAPI->>ContioAPI: Exchange code, validate ID token
    ContioAPI->>ContioAPI: Find user, verify partner connection
    ContioAPI-->>Desktop: Deep link: contio://auth/callback

IdP Session Behavior

Your identity provider controls the authentication experience. If the user has an active session with your IdP (e.g., they're already signed into your corporate network), they may be authenticated seamlessly without entering credentials. If no session exists—for example, when accessing via a bookmark, shared link, or after session expiration—your IdP will challenge the user for credentials as configured by your security policies.

Landing Page URL

Direct users to the partner SSO landing page using your partner slug:

https://app.contio.ai/p/{your-slug}

Query Parameters

Parameter Required Description
target No Target application after authentication (see below)
auto No If true, skip the landing page UI and immediately initiate SSO
login_hint No Pre-fill the user's email address (passed to IdP if supported)

Supported Target Values

Target Description
web Redirect to Contio web app (default)
desktop Deep link to Contio desktop app at root
meeting:{id} Deep link to specific meeting in desktop
backlog Deep link to backlog view in desktop

For detailed information on deep linking, see the Deep Linking Guide.

Examples:

# Standard flow - shows landing page, redirects to web
https://app.contio.ai/p/acme

# Auto-redirect to IdP (no landing page)
https://app.contio.ai/p/acme?auto=true

# Desktop app target with email hint
https://app.contio.ai/p/acme?target=desktop&login_hint=user@acme.com&auto=true

# Deep link to specific meeting
https://app.contio.ai/p/acme?target=meeting:550e8400-e29b-41d4-a716-446655440000&auto=true

# Deep link to backlog view
https://app.contio.ai/p/acme?target=backlog&auto=true

Session Management

The SSO flow uses server-side PKCE with HTTP session cookies for security. Sessions expire after 10 minutes if not completed. The flow generates a unique session ID and PKCE code verifier/challenge pair, stores them server-side with the session cookie, and validates the state parameter on callback to prevent CSRF attacks.

Callback Handling

After successful IdP authentication, the callback is handled at /v1/partner/sso/callback. Contio exchanges the authorization code for tokens, validates the ID token signature using JWKS, extracts user claims using your configured mappings, finds or creates the Contio user, and redirects to the target application.

For seamless desktop app integration, use desktop targets (desktop, meeting:{id}, or backlog).

Quick Example

// Launch Contio desktop app via SSO
function launchContioDesktop(userEmail: string) {
  const ssoUrl = new URL('https://app.contio.ai/p/your-slug');
  ssoUrl.searchParams.set('target', 'desktop');
  ssoUrl.searchParams.set('auto', 'true');
  ssoUrl.searchParams.set('login_hint', userEmail);

  window.open(ssoUrl.toString(), '_blank');
}

// Open a specific meeting in desktop
function openMeetingInDesktop(userEmail: string, meetingId: string) {
  const ssoUrl = new URL('https://app.contio.ai/p/your-slug');
  ssoUrl.searchParams.set('target', `meeting:${meetingId}`);
  ssoUrl.searchParams.set('auto', 'true');
  ssoUrl.searchParams.set('login_hint', userEmail);

  window.open(ssoUrl.toString(), '_blank');
}

How It Works

When a desktop target is specified, after successful IdP authentication:

  1. The browser redirects to a callback page showing "Signed in as {name}"
  2. User clicks "Continue to Contio Desktop" button
  3. A deep link (contio://auth/callback?...) opens the desktop app
  4. The desktop app completes token exchange and navigates to the target location

Learn More

For comprehensive deep linking documentation including all target types, validation, error handling, and best practices, see the Deep Linking Guide.

Security Best Practices

Client Secret Storage

Your IdP client secret is encrypted at rest using Contio's encryption service. Never expose the client secret in client-side code or logs. Rotate the client secret periodically according to your security policies.

Domain Validation

Use strict mode for enterprise deployments to ensure only authorized email domains can authenticate. This prevents unauthorized access even if someone gains access to your IdP. Regularly audit your allowed_email_domains list and remove domains that are no longer valid.

PKCE Flow Security

The SSO flow uses server-side PKCE with session cookies rather than storing sensitive data in URL parameters. This provides protection against authorization code interception attacks. Sessions are single-use and expire after 10 minutes.

ID Token Validation

Contio performs comprehensive ID token validation including signature verification using your IdP's JWKS endpoint, issuer validation against the discovery document, audience validation to ensure the token was issued for Contio, expiration checking, and nonce validation to prevent replay attacks.

Rate Limiting

Public SSO endpoints are rate-limited to 30 requests per minute per IP address to prevent abuse. Admin API endpoints for IdP configuration are limited to 500 requests per 5 minutes.

Troubleshooting

Common Error Codes

Error Code HTTP Status Description Recovery Action
idp_config_exists 409 IdP configuration already exists for this partner Use PUT to update or DELETE to remove existing config
invalid_idp 400 Attempted to use a blocked public IdP (Google, Microsoft consumer, Zoho) Use a corporate/organizational IdP instead
domain_is_generic 400 Generic email domain (gmail.com, etc.) in allowed_email_domains Use corporate domains only
domain_already_claimed 409 Email domain is already claimed by another partner Contact Contio support if you own this domain
strict_mode_requires_domains 400 Strict mode selected but no allowed_email_domains provided Add at least one allowed email domain
discovery_fetch_failed 400 Could not fetch OIDC discovery document from discovery_url Verify the URL is correct and accessible
idp_config_not_found 404 No IdP configuration exists for this partner Create an IdP configuration first
partner_connection_required - User lacks prior OAuth connection User must first create a Contio account and authorize via OAuth before using SSO

Discovery Document Issues

If you receive discovery_fetch_failed, verify that your discovery URL is correct and uses HTTPS, the endpoint is publicly accessible (not behind a firewall), the discovery document returns valid JSON with required OIDC fields, and your IdP is operational.

Email Domain Errors

The domain_is_generic error occurs when you try to add a generic email domain like gmail.com or yahoo.com. Contio maintains a registry of 72,000+ generic domains that cannot be claimed. Use only corporate domains owned by your organization.

The domain_already_claimed error means another partner has already claimed this domain. Each domain can only be associated with one partner for security. If you believe you should own this domain, contact Contio support.

Authentication Failures

If users receive "Email domain not authorized", verify the user's email domain is in your allowed_email_domains list. If users receive "User not found" or "Partner connection required", they must first create a Contio account and authorize your partner app via OAuth before using SSO.

Session Expiration

SSO sessions expire after 10 minutes. If users see "Session expired or invalid", they should restart the SSO flow from the beginning. This typically happens if users take too long at the IdP login page.

Next Steps