DoneIsBetter SSO Integration Guide

API Version: 5.5.0

OAuth 2.0 Authorization Server

⚠️ Important: OAuth 2.0 Flow

This SSO service uses OAuth 2.0 Authorization Code Flow. The old client-side approach has been deprecated. You must implement server-side token exchange and handle app-level permissions.

Overview

DoneIsBetter SSO is an OAuth 2.0 authorization server that provides:

  • Centralized Authentication - Users log in once, access multiple apps
  • App-Level Permissions - Control which users can access which applications
  • Role-Based Access - Assign users as user or admin per app
  • Admin Approval Workflow - New users require SSO admin approval before accessing apps
  • Secure Token Management - JWT-based access and refresh tokens

Authentication Flow

  1. User Clicks "Login"

    Your app redirects to SSO authorization endpoint:

    https://sso.doneisbetter.com/api/oauth/authorize? client_id=YOUR_CLIENT_ID& redirect_uri=https://yourapp.com/auth/callback& response_type=code& scope=openid profile email
  2. User Authenticates

    SSO presents login page. User enters credentials or uses magic link/PIN.

  3. Permission Check

    SSO verifies user has approved access to your app:

    • status: 'approved' → Continue to step 4
    • status: 'pending' → Show "Access Pending Approval" message
    • status: 'revoked' or no permission → Show "Access Denied"
  4. Authorization Code

    SSO redirects back to your app with authorization code:

    https://yourapp.com/auth/callback?code=AUTHORIZATION_CODE
  5. Token Exchange (Server-Side)

    Your backend exchanges code for tokens:

    POST https://sso.doneisbetter.com/api/oauth/token
    Content-Type: application/json
    
    {
      "grant_type": "authorization_code",
      "code": "AUTHORIZATION_CODE",
      "client_id": "YOUR_CLIENT_ID",
      "client_secret": "YOUR_CLIENT_SECRET",
      "redirect_uri": "https://yourapp.com/auth/callback"
    }
  6. Receive Tokens

    SSO returns access token, ID token, and refresh token:

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

    Decode ID token to get user info and app-level role:

    {
      "sub": "user-uuid",
      "email": "user@example.com",
      "name": "User Name",
      "role": "admin",  // App-level role: 'user' or 'admin'
      "iat": 1234567890,
      "exp": 1234571490
    }

Integration Steps

  1. Register Your Domain

    Contact us at support@doneisbetter.com to register your domain.

    Required information:

    • Your domain name
    • Organization name
    • Technical contact email
    • Development and production URLs
  2. Add SSO Client

    Include our client script in your HTML:

    <script src="https://sso.doneisbetter.com/sso-client.js"></script>
  3. Initialize SSO

    Create an SSO instance and check authentication:

    const sso = new SSOClient('https://sso.doneisbetter.com');
    
    // Check on page load
    document.addEventListener('DOMContentLoaded', async () => {
      const session = await sso.validateSession();
      if (session.isValid) {
        // Handle authenticated user
        console.log('User:', session.user);
      } else {
        // Handle unauthenticated state
        sso.redirectToLogin();
      }
    });

API Reference

Session Validation

Endpoint: GET https://sso.doneisbetter.com/api/sso/validate

Headers:

  • Content-Type: application/json
  • Origin: your-domain.com

Success Response (200 OK)

{
  "isValid": true,
  "user": {
    "id": "user_id",
    "username": "username",
    "permissions": {
      "isAdmin": false,
      "canViewUsers": false,
      "canManageUsers": false
    }
  },
  "session": {
    "expiresAt": "2025-07-21T14:43:47Z"
  }
}

Error Responses

  • 401 - Invalid or expired session
  • 403 - Unauthorized domain
  • 500 - Server error

Security Best Practices

  • Always use HTTPS in production
  • Validate session status before accessing protected resources
  • Implement proper error handling
  • Don't store sensitive user data in localStorage
  • Keep the SSO client script updated to the latest version

Example Implementations

React

import { useEffect, useState } from 'react';

function App() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function checkAuth() {
      const sso = new SSOClient('https://sso.doneisbetter.com');
      try {
        const result = await sso.validateSession();
        if (result.isValid) {
          setUser(result.user);
        } else {
          sso.redirectToLogin();
        }
      } catch (error) {
        console.error('Auth error:', error);
      } finally {
        setLoading(false);
      }
    }
    checkAuth();
  }, []);

  if (loading) return <div>Loading...</div>;
  if (!user) return null;

  return <div>Welcome, {user.username}!</div>;
}

Vue.js

// auth.js
export default {
  data() {
    return {
      user: null,
      loading: true
    }
  },
  async created() {
    const sso = new SSOClient('https://sso.doneisbetter.com');
    try {
      const result = await sso.validateSession();
      if (result.isValid) {
        this.user = result.user;
      } else {
        sso.redirectToLogin();
      }
    } catch (error) {
      console.error('Auth error:', error);
    } finally {
      this.loading = false;
    }
  }
}

Support

For technical support or to report issues:

© 2025 DoneIsBetter. All rights reserved.