kaneo (minimalist kanban) fork to experiment adding a tangled integration github.com/usekaneo/kaneo
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: separate github sso and integration

Tin dc4c67dd 9ac30bbb

+155 -39
+7 -1
.env.sample
··· 11 11 # Authentication 12 12 AUTH_SECRET= 13 13 14 - # GitHub SSO & Integration 14 + # GitHub SSO (Sign in with GitHub — OAuth App) 15 + GITHUB_OAUTH_CLIENT_ID= 16 + GITHUB_OAUTH_CLIENT_SECRET= 17 + # Legacy fallback for SSO (used only if GITHUB_OAUTH_* are unset) 15 18 GITHUB_CLIENT_ID= 16 19 GITHUB_CLIENT_SECRET= 20 + 21 + # GitHub integration (GitHub App — repository sync, webhooks) 17 22 GITHUB_APP_ID= 18 23 GITHUB_WEBHOOK_SECRET= 19 24 GITHUB_PRIVATE_KEY= 25 + GITHUB_APP_NAME= 20 26 21 27 # SMTP Configuration 22 28 SMTP_HOST=
+2 -1
ENVIRONMENT_SETUP.md
··· 43 43 ### Optional Variables 44 44 45 45 Kaneo supports many optional configuration options including: 46 - - SSO providers (GitHub, Google, Discord, Custom OAuth/OIDC) 46 + - SSO providers (GitHub OAuth via `GITHUB_OAUTH_CLIENT_ID` / `GITHUB_OAUTH_CLIENT_SECRET`, Google, Discord, Custom OAuth/OIDC) 47 + - GitHub repository integration (GitHub App: `GITHUB_APP_ID`, `GITHUB_PRIVATE_KEY`, `GITHUB_WEBHOOK_SECRET`, optional `GITHUB_APP_NAME`) — separate from GitHub SSO 47 48 - SMTP configuration for email 48 49 - Access control settings 49 50 - CORS configuration
+5 -2
apps/api/src/auth.ts
··· 25 25 import { publishEvent } from "./events"; 26 26 import { checkRegistrationAllowed } from "./utils/check-registration-allowed"; 27 27 import { generateDemoName } from "./utils/generate-demo-name"; 28 + import { getGithubSsoOAuthCredentials } from "./utils/github-sso-env"; 28 29 29 30 config(); 31 + 32 + const githubSso = getGithubSsoOAuthCredentials(); 30 33 31 34 const isRegistrationDisabled = process.env.DISABLE_REGISTRATION === "true"; 32 35 const isPasswordRegistrationDisabled = ··· 173 176 }, 174 177 socialProviders: { 175 178 github: { 176 - clientId: process.env.GITHUB_CLIENT_ID || "", 177 - clientSecret: process.env.GITHUB_CLIENT_SECRET || "", 179 + clientId: githubSso.clientId, 180 + clientSecret: githubSso.clientSecret, 178 181 scope: ["user:email"], 179 182 }, 180 183 google: {
+2 -3
apps/api/src/utils/get-settings.ts
··· 1 1 import { config } from "dotenv-mono"; 2 + import { isGithubSsoConfigured } from "./github-sso-env"; 2 3 3 4 config(); 4 5 ··· 14 15 Boolean(process.env.SMTP_SECURE) && 15 16 Boolean(process.env.SMTP_USER) && 16 17 Boolean(process.env.SMTP_PASSWORD), 17 - hasGithubSignIn: 18 - Boolean(process.env.GITHUB_CLIENT_ID) && 19 - Boolean(process.env.GITHUB_CLIENT_SECRET), 18 + hasGithubSignIn: isGithubSsoConfigured(), 20 19 hasGoogleSignIn: 21 20 Boolean(process.env.GOOGLE_CLIENT_ID) && 22 21 Boolean(process.env.GOOGLE_CLIENT_SECRET),
+24
apps/api/src/utils/github-sso-env.ts
··· 1 + /** 2 + * GitHub "Sign in with GitHub" uses OAuth client credentials. 3 + * Prefer `GITHUB_OAUTH_*` so GitHub App integration env vars can be set 4 + * without implicitly enabling SSO. Legacy `GITHUB_CLIENT_*` is still supported. 5 + */ 6 + export function getGithubSsoOAuthCredentials(): { 7 + clientId: string; 8 + clientSecret: string; 9 + } { 10 + const oauthId = process.env.GITHUB_OAUTH_CLIENT_ID?.trim(); 11 + const oauthSecret = process.env.GITHUB_OAUTH_CLIENT_SECRET?.trim(); 12 + if (oauthId && oauthSecret) { 13 + return { clientId: oauthId, clientSecret: oauthSecret }; 14 + } 15 + return { 16 + clientId: process.env.GITHUB_CLIENT_ID?.trim() || "", 17 + clientSecret: process.env.GITHUB_CLIENT_SECRET?.trim() || "", 18 + }; 19 + } 20 + 21 + export function isGithubSsoConfigured(): boolean { 22 + const { clientId, clientSecret } = getGithubSsoOAuthCredentials(); 23 + return Boolean(clientId && clientSecret); 24 + }
+22 -8
apps/docs/core/installation/environment-variables.mdx
··· 15 15 - [Authentication](#authentication) 16 16 - [Object Storage](#object-storage) 17 17 - [Access Control](#access-control) 18 - - [GitHub SSO & Integration](#github-sso-&-integration) 18 + - [GitHub SSO](#github-sso) 19 + - [GitHub integration](#github-integration) 19 20 - [Google SSO](#google-sso) 20 21 - [Discord SSO](#discord-sso) 21 22 - [Custom OAuth/OIDC](#custom-oauth-oidc) ··· 81 82 | `DISABLE_REGISTRATION` | Disable public user registration. When set to `true`, the sign-up option will not be shown on the sign-in page and new user creation is blocked (including via SSO). **Note:** Users with valid workspace invitations can still register even when this is enabled. | `false` | 82 83 | `DISABLE_PASSWORD_REGISTRATION` | Disable password-based account creation. When set to `true`, email/password sign-up is blocked, but social/OIDC registration remains available unless `DISABLE_REGISTRATION=true`. | `false` | 83 84 84 - ### GitHub SSO & Integration 85 + ### GitHub SSO 86 + 87 + Sign in with GitHub uses a [GitHub OAuth App](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app). Set `GITHUB_OAUTH_CLIENT_ID` and `GITHUB_OAUTH_CLIENT_SECRET` (or rely on the legacy variables below). 85 88 86 89 Name | Description | 87 90 --- | --- | 88 - | `GITHUB_CLIENT_ID` | The GitHub client ID. 89 - | `GITHUB_CLIENT_SECRET` | The GitHub client secret. 90 - | `GITHUB_APP_ID` | The GitHub app ID. 91 - | `GITHUB_WEBHOOK_SECRET` | The GitHub webhook secret. 92 - | `GITHUB_PRIVATE_KEY` | The GitHub private key. 91 + | `GITHUB_OAUTH_CLIENT_ID` | OAuth client ID for GitHub sign-in. 92 + | `GITHUB_OAUTH_CLIENT_SECRET` | OAuth client secret for GitHub sign-in. 93 + | `GITHUB_CLIENT_ID` | Legacy fallback for OAuth client ID when `GITHUB_OAUTH_*` is not set. 94 + | `GITHUB_CLIENT_SECRET` | Legacy fallback for OAuth client secret when `GITHUB_OAUTH_*` is not set. 95 + 96 + ### GitHub integration 97 + 98 + Repository sync and webhooks use a [GitHub App](https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps). These variables do not enable GitHub sign-in; configure [GitHub SSO](#github-sso) separately if you want both. 99 + 100 + Name | Description | 101 + --- | --- | 102 + | `GITHUB_APP_ID` | The GitHub App ID. 103 + | `GITHUB_WEBHOOK_SECRET` | Secret used to verify GitHub webhook payloads. 104 + | `GITHUB_PRIVATE_KEY` | PEM private key for the GitHub App (JWT authentication). 105 + | `GITHUB_APP_NAME` | (Optional) GitHub App slug, used for installation links in the UI. 93 106 94 107 ### Google SSO 95 108 ··· 134 147 135 148 ## Key points 136 149 137 - - If you enable GitHub SSO, you need to set up the GitHub app which is used to authenticate users in the [GitHub Developer Settings](https://github.com/settings/developers). See the [GitHub SSO guide](/core/social-providers/github). 150 + - If you enable GitHub SSO, create a GitHub OAuth App in [GitHub Developer Settings](https://github.com/settings/developers) and set `GITHUB_OAUTH_CLIENT_ID` / `GITHUB_OAUTH_CLIENT_SECRET` (or the legacy `GITHUB_CLIENT_*` variables). See the [GitHub SSO guide](/core/social-providers/github). 151 + - If you use the GitHub repository integration, configure a GitHub App and set the integration variables in [GitHub integration](#github-integration). See the [GitHub integration configuration](/core/integrations/github/configuration) guide. 138 152 - If you enable Google SSO, you need to set up the Google app which is used to authenticate users in the [Google Cloud Console](https://console.cloud.google.com/). See the [Google SSO guide](/core/social-providers/google). 139 153 - If you enable Discord SSO, you need to set up the Discord application which is used to authenticate users in the [Discord Developer Portal](https://discord.com/developers/applications). See the [Discord SSO guide](/core/social-providers/discord). 140 154 - If you enable Custom OAuth/OIDC, you need to configure your identity provider with the appropriate redirect URI. See the [Custom OAuth/OIDC guide](/core/social-providers/custom-oauth).
+7 -13
apps/docs/core/integrations/github/configuration.mdx
··· 15 15 Add the following environment variables to your Kaneo deployment: 16 16 17 17 ```bash 18 - # GitHub App Configuration 18 + # GitHub App (integration only — repository sync, webhooks) 19 19 GITHUB_APP_ID=123456 20 - GITHUB_CLIENT_ID=Iv1.abc123def456 21 - GITHUB_CLIENT_SECRET=abc123def456ghi789jkl012mno345pqr678stu 22 20 GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY----- 23 21 MIIEpAIBAAKCAQEA... 24 22 [Full contents of your private key] ··· 26 24 -----END RSA PRIVATE KEY-----" 27 25 GITHUB_WEBHOOK_SECRET=your-webhook-secret-here 28 26 29 - # Optional: GitHub App Name for installation URLs 27 + # Optional: GitHub App slug for installation URLs in the UI 30 28 GITHUB_APP_NAME=kaneo-your-instance-name 31 29 ``` 30 + 31 + <Info> 32 + GitHub sign-in uses separate OAuth variables (`GITHUB_OAUTH_CLIENT_ID` / `GITHUB_OAUTH_CLIENT_SECRET`). You can run the integration without enabling GitHub SSO. See [GitHub SSO](/core/social-providers/github) and [Environment variables](/core/installation/environment-variables#github-sso). 33 + </Info> 32 34 33 35 ### Variable Reference 34 36 35 37 | Variable | Description | Required | Example | 36 38 |----------|-------------|----------|---------| 37 39 | `GITHUB_APP_ID` | Your GitHub App's ID | ✅ | `123456` | 38 - | `GITHUB_CLIENT_ID` | OAuth client ID from your app | ✅ | `Iv1.abc123def456` | 39 - | `GITHUB_CLIENT_SECRET` | OAuth client secret | ✅ | `abc123def456ghi789jkl012mno345pqr678stu` | 40 40 | `GITHUB_PRIVATE_KEY` | Full private key content (with newlines) | ✅ | `-----BEGIN RSA...` | 41 41 | `GITHUB_WEBHOOK_SECRET` | Secret for webhook verification | ✅ | `your-secret` | 42 - | `GITHUB_APP_NAME` | App name for installation URLs | ⚠️ | `kaneo-mycompany` | 42 + | `GITHUB_APP_NAME` | App slug for installation URLs in the UI | ⚠️ | `kaneo-mycompany` | 43 43 44 44 <Warning> 45 45 `GITHUB_APP_NAME` is optional but recommended. It's used to generate direct installation links in the UI. ··· 58 58 environment: 59 59 # ... other environment variables 60 60 GITHUB_APP_ID: "123456" 61 - GITHUB_CLIENT_ID: "Iv1.abc123def456" 62 - GITHUB_CLIENT_SECRET: "abc123def456ghi789jkl012mno345pqr678stu" 63 61 GITHUB_PRIVATE_KEY: | 64 62 -----BEGIN RSA PRIVATE KEY----- 65 63 MIIEpAIBAAKCAQEA... ··· 88 86 type: Opaque 89 87 stringData: 90 88 GITHUB_APP_ID: "123456" 91 - GITHUB_CLIENT_ID: "Iv1.abc123def456" 92 - GITHUB_CLIENT_SECRET: "abc123def456ghi789jkl012mno345pqr678stu" 93 89 GITHUB_PRIVATE_KEY: | 94 90 -----BEGIN RSA PRIVATE KEY----- 95 91 MIIEpAIBAAKCAQEA... ··· 125 121 ```bash 126 122 # .env file 127 123 GITHUB_APP_ID=123456 128 - GITHUB_CLIENT_ID=Iv1.abc123def456 129 - GITHUB_CLIENT_SECRET=abc123def456ghi789jkl012mno345pqr678stu 130 124 GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY----- 131 125 MIIEpAIBAAKCAQEA... 132 126 [Full contents of your private key]
+3 -3
apps/docs/core/integrations/github/setup.mdx
··· 137 137 From the app settings page, note down these important values: 138 138 139 139 - **App ID** (shown at the top of the page) 140 - - **Client ID** (in the "Basic information" section) 141 - - **Client Secret** (click "Generate a new client secret") 142 140 - **Webhook Secret** (the one you created earlier) 143 141 - **Private Key** (contents of the downloaded `.pem` file) 144 142 143 + The GitHub App also shows an OAuth **Client ID** and **Client Secret** under "Basic information". Kaneo’s **repository integration** does not use those environment variables; they are only relevant if you enable **Sign in with GitHub** using `GITHUB_OAUTH_CLIENT_ID` / `GITHUB_OAUTH_CLIENT_SECRET` (see [GitHub SSO](/core/social-providers/github)). 144 + 145 145 <Info> 146 - You'll need all of these values for the [configuration step](/core/integrations/github/configuration). 146 + You need **App ID**, **private key**, and **webhook secret** for the [configuration step](/core/integrations/github/configuration). 147 147 </Info> 148 148 </Step> 149 149 </Steps>
+4 -6
apps/docs/core/integrations/github/troubleshooting.mdx
··· 105 105 **Solutions**: 106 106 1. **Verify All Variables Are Set** 107 107 ```bash 108 - # Check if environment variables are loaded 108 + # Check if integration environment variables are loaded (do not print secrets) 109 109 echo $GITHUB_APP_ID 110 - echo $GITHUB_CLIENT_ID 111 - # etc. 110 + if [ -n "$GITHUB_WEBHOOK_SECRET" ]; then echo "GITHUB_WEBHOOK_SECRET is set"; else echo "GITHUB_WEBHOOK_SECRET is missing"; fi 112 111 ``` 113 112 114 113 2. **Check Private Key Format** ··· 257 256 258 257 1. **Verify Environment Variables** 259 258 ```bash 260 - # Check that all required variables are set (don't print private key!) 259 + # Check that all required integration variables are set (don't print private key or webhook secret!) 261 260 echo "App ID: $GITHUB_APP_ID" 262 - echo "Client ID: $GITHUB_CLIENT_ID" 263 - echo "Webhook Secret: [REDACTED]" 264 261 echo "App Name: $GITHUB_APP_NAME" 262 + if [ -n "$GITHUB_WEBHOOK_SECRET" ]; then echo "GITHUB_WEBHOOK_SECRET is set"; else echo "GITHUB_WEBHOOK_SECRET is missing"; fi 265 263 ``` 266 264 267 265 2. **Test Repository Access**
+2 -2
apps/docs/core/social-providers/github.mdx
··· 13 13 2. Create a new OAuth app. 14 14 3. Set the redirect URI to `KANEO_API_URL/api/auth/callback/github`. 15 15 4. Copy the client ID and client secret. 16 - 5. Set the `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET` environment variables. 16 + 5. Set `GITHUB_OAUTH_CLIENT_ID` and `GITHUB_OAUTH_CLIENT_SECRET` (or the legacy `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET` if you prefer). 17 17 18 - For more information on what your `KANEO_API_URL` is, see the [Environment variables](/core/installation/environment-variables#github-sso--integration) page. 18 + For more information on what your `KANEO_API_URL` is, see the [Environment variables](/core/installation/environment-variables#github-sso) page. 19 19 20 20 ## Usage 21 21
+2
tests/api-integration/setup.ts
··· 72 72 process.env.SMTP_SECURE = ""; 73 73 process.env.SMTP_USER = ""; 74 74 process.env.SMTP_PASSWORD = ""; 75 + process.env.GITHUB_OAUTH_CLIENT_ID = ""; 76 + process.env.GITHUB_OAUTH_CLIENT_SECRET = ""; 75 77 process.env.GITHUB_CLIENT_ID = ""; 76 78 process.env.GITHUB_CLIENT_SECRET = ""; 77 79 process.env.GOOGLE_CLIENT_ID = "";
+75
tests/api/utils/github-sso-env.test.ts
··· 1 + import { afterEach, beforeEach, describe, expect, it } from "vitest"; 2 + import { 3 + getGithubSsoOAuthCredentials, 4 + isGithubSsoConfigured, 5 + } from "../../../apps/api/src/utils/github-sso-env"; 6 + 7 + const keys = [ 8 + "GITHUB_OAUTH_CLIENT_ID", 9 + "GITHUB_OAUTH_CLIENT_SECRET", 10 + "GITHUB_CLIENT_ID", 11 + "GITHUB_CLIENT_SECRET", 12 + ] as const; 13 + 14 + describe("github-sso-env", () => { 15 + const original: Partial<Record<(typeof keys)[number], string | undefined>> = 16 + {}; 17 + 18 + beforeEach(() => { 19 + for (const key of keys) { 20 + original[key] = process.env[key]; 21 + delete process.env[key]; 22 + } 23 + }); 24 + 25 + afterEach(() => { 26 + for (const key of keys) { 27 + const value = original[key]; 28 + if (value === undefined) { 29 + delete process.env[key]; 30 + } else { 31 + process.env[key] = value; 32 + } 33 + } 34 + }); 35 + 36 + it("prefers GITHUB_OAUTH_* when both are set", () => { 37 + process.env.GITHUB_OAUTH_CLIENT_ID = "oauth-id"; 38 + process.env.GITHUB_OAUTH_CLIENT_SECRET = "oauth-secret"; 39 + process.env.GITHUB_CLIENT_ID = "legacy-id"; 40 + process.env.GITHUB_CLIENT_SECRET = "legacy-secret"; 41 + expect(getGithubSsoOAuthCredentials()).toEqual({ 42 + clientId: "oauth-id", 43 + clientSecret: "oauth-secret", 44 + }); 45 + expect(isGithubSsoConfigured()).toBe(true); 46 + }); 47 + 48 + it("falls back to legacy GITHUB_CLIENT_* when OAuth vars are unset", () => { 49 + process.env.GITHUB_CLIENT_ID = "legacy-id"; 50 + process.env.GITHUB_CLIENT_SECRET = "legacy-secret"; 51 + expect(getGithubSsoOAuthCredentials()).toEqual({ 52 + clientId: "legacy-id", 53 + clientSecret: "legacy-secret", 54 + }); 55 + expect(isGithubSsoConfigured()).toBe(true); 56 + }); 57 + 58 + it("returns empty credentials when nothing is configured", () => { 59 + expect(getGithubSsoOAuthCredentials()).toEqual({ 60 + clientId: "", 61 + clientSecret: "", 62 + }); 63 + expect(isGithubSsoConfigured()).toBe(false); 64 + }); 65 + 66 + it("treats partial OAuth pair as absent and falls back to legacy", () => { 67 + process.env.GITHUB_OAUTH_CLIENT_ID = "only-id"; 68 + process.env.GITHUB_CLIENT_ID = "legacy-id"; 69 + process.env.GITHUB_CLIENT_SECRET = "legacy-secret"; 70 + expect(getGithubSsoOAuthCredentials()).toEqual({ 71 + clientId: "legacy-id", 72 + clientSecret: "legacy-secret", 73 + }); 74 + }); 75 + });