Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.example-dev
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ AUTH_TRUST_HOST=true
# SSO Configuration
#GOOGLE_CLIENT_ID=
#GOOGLE_CLIENT_SECRET=
#GITHUB_CLIENT_ID=
#GITHUB_CLIENT_SECRET=
#GITLAB_CLIENT_ID=
#GITLAB_CLIENT_SECRET=
#KEYCLOAK_CLIENT_ID=
#KEYCLOAK_CLIENT_SECRET=
#KEYCLOAK_ISSUER=
Expand Down
4 changes: 4 additions & 0 deletions deploy/docker/.env.example-prod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ ENABLE_DEMO_MODE=false
# SSO Configuration
#GOOGLE_CLIENT_ID=
#GOOGLE_CLIENT_SECRET=
#GITHUB_CLIENT_ID=
#GITHUB_CLIENT_SECRET=
#GITLAB_CLIENT_ID=
#GITLAB_CLIENT_SECRET=
#KEYCLOAK_CLIENT_ID=
#KEYCLOAK_CLIENT_SECRET=
#KEYCLOAK_ISSUER=
Expand Down
8 changes: 4 additions & 4 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ Minimum values to edit:

### Choose authentication mode

RTAP supports SSO or a demo login button. Supported SSO providers today are Google, Keycloak, and Okta. If you need another provider, open an issue and we can add it.
RTAP supports SSO or a demo login button. Supported SSO providers today are Google, GitHub, GitLab, Keycloak, and Okta. If you need another provider, open an issue and we can add it.

- **SSO (recommended):** configure your provider's details (like client ID/secret + issuer when required) using the variable names provided in the .env file.
- **SSO (recommended):** configure your provider's details (client ID/secret, plus issuer for Keycloak/Okta) using the variable names provided in the .env file.
- **Demo mode:** set `ENABLE_DEMO_MODE=true`. This exposes a “Sign in as Demo Admin” button and **anyone with access to the sign-in page can log in without an account**. Use only for isolated testing or demos.

For Google SSO, configure the following in the Google Cloud console:
For any SSO provider, configure the following in your identity provider console:

- Authorized JavaScript origins: matches `AUTH_URL` from `.env`.
- Authorized redirect URIs: `AUTH_URL` + `/api/auth/callback/google`.
- Authorized redirect URIs: `AUTH_URL` + `/api/auth/callback/<provider>` (for example, `/api/auth/callback/github`).

### Start the containers

Expand Down
4 changes: 4 additions & 0 deletions src/app/(public-routes)/auth/signin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@ export default async function SignInPage(props: { searchParams?: Promise<{ callb
const { callbackUrl = "/", error } = (await props.searchParams) ?? {};
const demoEnabled = env.ENABLE_DEMO_MODE === "true";
const googleEnabled = Boolean(env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET);
const githubEnabled = Boolean(env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET);
const gitlabEnabled = Boolean(env.GITLAB_CLIENT_ID && env.GITLAB_CLIENT_SECRET);
const keycloakEnabled = Boolean(env.KEYCLOAK_CLIENT_ID && env.KEYCLOAK_CLIENT_SECRET && env.KEYCLOAK_ISSUER);
const oktaEnabled = Boolean(env.OKTA_CLIENT_ID && env.OKTA_CLIENT_SECRET && env.OKTA_ISSUER);

return (
<SignInPageClient
googleEnabled={googleEnabled}
githubEnabled={githubEnabled}
gitlabEnabled={gitlabEnabled}
keycloakEnabled={keycloakEnabled}
oktaEnabled={oktaEnabled}
demoEnabled={demoEnabled}
Expand Down
10 changes: 10 additions & 0 deletions src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ export const env = createEnv({
// Optional: Google OAuth client credentials (registers provider when present)
GOOGLE_CLIENT_ID: z.string().optional(),
GOOGLE_CLIENT_SECRET: z.string().optional(),
// Optional: GitHub OAuth client credentials (registers provider when present)
GITHUB_CLIENT_ID: z.string().optional(),
GITHUB_CLIENT_SECRET: z.string().optional(),
// Optional: GitLab OAuth client credentials (registers provider when present)
GITLAB_CLIENT_ID: z.string().optional(),
GITLAB_CLIENT_SECRET: z.string().optional(),
// Optional: Keycloak OAuth client credentials (registers provider when present)
KEYCLOAK_CLIENT_ID: z.string().optional(),
KEYCLOAK_CLIENT_SECRET: z.string().optional(),
Expand Down Expand Up @@ -57,6 +63,10 @@ export const env = createEnv({
ENABLE_DEMO_MODE: process.env.ENABLE_DEMO_MODE,
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,
GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET,
GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID,
GITHUB_CLIENT_SECRET: process.env.GITHUB_CLIENT_SECRET,
GITLAB_CLIENT_ID: process.env.GITLAB_CLIENT_ID,
GITLAB_CLIENT_SECRET: process.env.GITLAB_CLIENT_SECRET,
KEYCLOAK_CLIENT_ID: process.env.KEYCLOAK_CLIENT_ID,
KEYCLOAK_CLIENT_SECRET: process.env.KEYCLOAK_CLIENT_SECRET,
KEYCLOAK_ISSUER: process.env.KEYCLOAK_ISSUER,
Expand Down
10 changes: 9 additions & 1 deletion src/features/shared/auth/sign-in-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,29 @@ import { Button, Card, CardContent, CardHeader, CardTitle } from "@components/ui

interface Props {
googleEnabled: boolean;
githubEnabled: boolean;
gitlabEnabled: boolean;
keycloakEnabled: boolean;
oktaEnabled: boolean;
demoEnabled: boolean;
callbackUrl: string;
initialError?: string;
}

type OAuthProviderId = "google" | "keycloak" | "okta";
type OAuthProviderId = "google" | "github" | "gitlab" | "keycloak" | "okta";

const oauthOptions: Array<{ id: OAuthProviderId; label: string }> = [
{ id: "google", label: "Continue with Google" },
{ id: "github", label: "Continue with GitHub" },
{ id: "gitlab", label: "Continue with GitLab" },
{ id: "keycloak", label: "Continue with Keycloak" },
{ id: "okta", label: "Continue with Okta" },
];

export default function SignInPageClient({
googleEnabled,
githubEnabled,
gitlabEnabled,
keycloakEnabled,
oktaEnabled,
demoEnabled,
Expand Down Expand Up @@ -79,6 +85,8 @@ export default function SignInPageClient({

const oauthEnabled: Record<OAuthProviderId, boolean> = {
google: googleEnabled,
github: githubEnabled,
gitlab: gitlabEnabled,
keycloak: keycloakEnabled,
okta: oktaEnabled,
};
Expand Down
22 changes: 21 additions & 1 deletion src/server/auth/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { type DefaultSession, type NextAuthConfig } from "next-auth";
import type { Adapter } from "next-auth/adapters";
import type { JWT as NextAuthJWT } from "next-auth/jwt";
import GitHubProvider from "next-auth/providers/github";
import GitLabProvider from "next-auth/providers/gitlab";
import GoogleProvider from "next-auth/providers/google";
import KeycloakProvider from "next-auth/providers/keycloak";
import OktaProvider from "next-auth/providers/okta";
Expand Down Expand Up @@ -42,7 +44,7 @@ declare module "@auth/core/adapters" {
type AugmentedJWT = NextAuthJWT & { role?: UserRole };

const demoModeEnabled = env.ENABLE_DEMO_MODE === "true";
const oauthProviders = new Set(["google", "keycloak", "okta"]);
const oauthProviders = new Set(["google", "github", "gitlab", "keycloak", "okta"]);

const isRecord = (value: unknown): value is Record<string, unknown> =>
typeof value === "object" && value !== null;
Expand Down Expand Up @@ -205,6 +207,24 @@ export const authConfig = {
}),
]
: []),
...(process.env.GITHUB_CLIENT_ID && process.env.GITHUB_CLIENT_SECRET
? [
GitHubProvider({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
allowDangerousEmailAccountLinking: true,
}),
]
: []),
...(process.env.GITLAB_CLIENT_ID && process.env.GITLAB_CLIENT_SECRET
? [
GitLabProvider({
clientId: process.env.GITLAB_CLIENT_ID,
clientSecret: process.env.GITLAB_CLIENT_SECRET,
allowDangerousEmailAccountLinking: true,
}),
]
: []),
...(process.env.KEYCLOAK_CLIENT_ID && process.env.KEYCLOAK_CLIENT_SECRET && process.env.KEYCLOAK_ISSUER
? [
KeycloakProvider({
Expand Down
Loading