OAuth Implementation - Wiz-DevTech/grok_kcc GitHub Wiki

Secure Setup Confirmation & Sample OAuth Implementation

Thanks for sharing—I've noted the Client ID (M539PU4124AA4ZJ2W1P0YO8HVR1ZPUBH) for reference. Critical Security Note: Never share or commit the Client Secret (IN83KN2ZF7NAPSF27QG0800FA1P0XFAP0EIFE9C47TNRR9UU8SK3PSNY2BPRLMAUY) to public repos, logs, or chats again—treat it like a password. Store it in env vars (e.g., .env file) or a secrets manager (Vault). If compromised, regenerate it in ClickUp's Apps settings ASAP.

With these creds, your "Saas-DID Foundation Hub" app is ready for production-grade integrations (e.g., GitHub Actions for task updates or bots for AI summaries). Below, I'll provide a plug-and-play Node.js sample for the full OAuth flow: authorizing users, fetching tokens, and making a simple API call (e.g., list your Workspace tasks). This ties directly into our project—e.g., use it in a GitHub Action to sync Phase 1 audit tasks.

Prerequisites

  • Node.js 18+ installed.
  • Create a .env file in your project root:
    CLICKUP_CLIENT_ID=M539PU4124AA4ZJ2W1P0YO8HVR1ZPUBH
    CLICKUP_CLIENT_SECRET=IN83KN2ZF7NAPSF27QG0800FA1P0XFAP0EIFE9C47TNRR9UU8SK3PSNY2BPRLMAUY
    REDIRECT_URI=http://localhost:3000/callback  # Matches your app's registered URL
    
  • Run npm init -y && npm i express dotenv axios qs for deps.

Sample Node.js OAuth Server (auth.js)

This sets up a mini Express server:

  1. Redirects to ClickUp for auth.
  2. Handles callback, exchanges code for token.
  3. Uses token to fetch tasks (e.g., from your "SaaS-DID Foundation Hub" Workspace).
require('dotenv').config();
const express = require('express');
const axios = require('axios');
const qs = require('qs');

const app = express();
const PORT = 3000;
const CLIENT_ID = process.env.CLICKUP_CLIENT_ID;
const CLIENT_SECRET = process.env.CLICKUP_CLIENT_SECRET;
const REDIRECT_URI = process.env.REDIRECT_URI;

// Step 1: Auth endpoint (hit /auth to start login)
app.get('/auth', (req, res) => {
  const authUrl = `https://auth.clickup.com/oauth/authorize?${qs.stringify({
    client_id: CLIENT_ID,
    redirect_uri: REDIRECT_URI,
    response_type: 'code',
    state: 'state_xyz'  // Anti-CSRF; customize
  })}`;
  res.redirect(authUrl);
});

// Step 2: Callback handler
app.get('/callback', async (req, res) => {
  const { code, state, error } = req.query;
  if (error || state !== 'state_xyz') {
    return res.status(400).send('Auth failed');
  }

  try {
    // Exchange code for tokens
    const tokenResponse = await axios.post('https://auth.clickup.com/api/oauth/token', qs.stringify({
      grant_type: 'authorization_code',
      client_id: CLIENT_ID,
      client_secret: CLIENT_SECRET,
      code,
      redirect_uri: REDIRECT_URI
    }), {
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
    });

    const { access_token, refresh_token } = tokenResponse.data;
    console.log('Tokens:', { access_token, refresh_token });  // Store securely (e.g., DB/session)

    // Step 3: Example API call - Fetch tasks from your Workspace (replace TEAM_ID with yours from /api/v2/team)
    const tasksResponse = await axios.get('https://api.clickup.com/api/v2/team/TEAM_ID/task', {  // Get TEAM_ID via GET /api/v2/team
      headers: { Authorization: access_token }
    });
    console.log('Sample Tasks:', tasksResponse.data);  // e.g., List Phase 1 tasks

    res.send(`Success! Tokens acquired. Check console for tasks. <a href="/auth">Re-auth</a>`);
  } catch (err) {
    console.error('Token exchange failed:', err.response?.data);
    res.status(500).send('Token fetch error');
  }
});

app.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}. Hit /auth to start.`);
});

How to Run & Test

  1. Save as auth.js, then node auth.js.
  2. Visit http://localhost:3000/auth → ClickUp login → Redirect back.
  3. Console logs tokens + sample tasks. If no tasks, first create the Workspace/Space via ClickUp UI.
  4. Token Refresh: When access_token expires (2 hours), use refresh_token:
    // Add to your code
    const refreshResponse = await axios.post('https://auth.clickup.com/api/oauth/token', qs.stringify({
      grant_type: 'refresh_token',
      client_id: CLIENT_ID,
      client_secret: CLIENT_SECRET,
      refresh_token
    }), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } });
    

Project Integration Examples

  • GitHub Action for Sync: Update the YAML from earlier:
    - name: Refresh & Update Task
      run: node update-task.js  # Script using access_token to PUT /task/{id} with phase status
      env:
        CLICKUP_ACCESS_TOKEN: ${{ secrets.CLICKUP_TOKEN }}  # Store tokens in GitHub Secrets
    
  • Bot/AI Flow: In n8n/Zapier, use this token to call POST /list/{id}/task for AI-generated subtasks (e.g., from OpenAI: "Create DID audit checklist").
  • Scale Tip: For team use, store tokens per-user in a DB (e.g., PostgreSQL with your SaaS multi-tenancy).

This gets your automations live in minutes—e.g., auto-update Phase 2 refactor tasks on GitHub merge. Tested the flow mentally against ClickUp docs; if you hit snags (e.g., TEAM_ID), share the error, and I'll debug. Next up: Full GitHub sync script or n8n workflow?