Skip to main content
EventPalour provides a robust authentication system with support for OAuth providers, email verification, two-factor authentication, and passkey support.

Authentication Methods

OAuth Providers

Users can sign in using their existing Google accounts. EventPalour currently supports:
  • Google OAuth: Sign in with Google accounts
The OAuth integration uses the Arctic library for secure authentication flow:
/home/daytona/workspace/source/lib/server/oauth.ts
import { Google } from "arctic";

export const google = new Google(
  env.GOOGLE_CLIENT_ID,
  env.GOOGLE_CLIENT_SECRET,
  `${env_client.NEXT_PUBLIC_APP_URL}/api/auth/oauth/google/callback`,
);

Email and Password

Traditional email and password authentication is supported with email verification for added security.

Session Management

EventPalour uses secure session management with the following features:

Current Session

Retrieve the current authenticated user:
import { getCurrentUser } from "@/lib/actions/auth";

const { user } = await getCurrentUser();

Sign Out

Securely invalidate user sessions:
/home/daytona/workspace/source/lib/actions/auth.ts:110-119
export async function signOut() {
  const { session } = await getCurrentSession();

  if (session) {
    await invalidateSession(session.id);
    await deleteSessionTokenCookie();
  }

  return { success: true };
}

Two-Factor Authentication (2FA)

EventPalour supports two-factor authentication for enhanced account security. Users can enable 2FA to require a second verification step when signing in.
2FA significantly improves account security by requiring both something you know (password) and something you have (authentication device).

Passkey Support

Passkey support (WebAuthn) is available for passwordless authentication, providing a modern and secure authentication experience.
Passkey functionality is currently in development and may be disabled in production until fully tested.

Authorization and Access Control

Platform Roles

EventPalour uses platform-level roles to manage user permissions:
  • Attendee: Regular users who can browse and register for events
  • Organizer: Users who can create and manage workspaces and events
  • Admin: Platform administrators with full access

Workspace Roles

Within workspaces, users can have different roles:
  • Member: Basic access to workspace features
  • Moderator: Can create events and manage speakers
  • Admin: Full workspace management capabilities
  • Owner: Workspace creator with all permissions

Role Hierarchy

/home/daytona/workspace/source/lib/actions/auth.ts:86-96
const roleHierarchy: Record<WorkspaceRole, number> = {
  member: 1,
  moderator: 2,
  admin: 3,
};

if (roleHierarchy[role] < roleHierarchy[requiredRole]) {
  redirect("/workspace/unauthorized");
}

return { user, workspace, workspaceRole: role };

Protected Routes

Require Authentication

Protect routes that require user authentication:
import { requireAuth } from "@/lib/actions/auth";

const { user } = await requireAuth();

Require Platform Role

Enforce platform-level role requirements:
import { requireRole } from "@/lib/actions/auth";
import { PlatformRole } from "@/lib/db/schema/enums";

const { user } = await requireRole(PlatformRole.ORGANIZER);

Require Workspace Access

Validate workspace access permissions:
/home/daytona/workspace/source/lib/actions/auth.ts:53-68
export async function validateWorkspaceAccess(workspaceId: string) {
  const { workspace, role, isOwner } =
    await getWorkspaceWithAccess(workspaceId);
  const user = await getUser();

  if (!user) {
    redirect("/auth/sign-in");
  }

  return {
    user,
    workspace,
    workspaceRole: role,
    isOwner,
  };
}

User Workspaces

Retrieve all workspaces a user has access to:
/home/daytona/workspace/source/lib/actions/auth.ts:121-137
export async function getUserWorkspacesList() {
  const user = await getUser();

  if (!user) {
    return [];
  }

  const workspaces = await getUserWorkspaces(user.id);

  return workspaces.map((w) => ({
    id: w.workspace.id,
    name: w.workspace.name,
    imageUrl: w.workspace.imageUrl,
    role: w.role,
    isOwner: w.isOwner,
  }));
}

Security Best Practices

1

Enable 2FA

Always recommend users enable two-factor authentication for their accounts.
2

Secure Sessions

Sessions are automatically invalidated on sign out and use secure cookie storage.
3

Email Verification

Email addresses are verified to ensure account ownership.
4

Role-Based Access

All sensitive operations check user roles before allowing access.

Common Use Cases

Check if User is Workspace Owner

const { isOwner } = await validateWorkspaceAccess(workspaceId);

if (isOwner) {
  // Owner-specific logic
}

Require Moderator Access

const { workspaceRole } = await requireWorkspaceRole(
  workspaceId,
  WorkspaceRole.MODERATOR
);

Get Current Workspace for Organizers

/home/daytona/workspace/source/lib/actions/auth.ts:99-108
export async function getCurrentWorkspace() {
  const user = await getUserWithRole(PlatformRole.ORGANIZER);
  const workspace = await getUserOwnedWorkspace(user.id);

  if (!workspace) {
    redirect("/auth/onboarding/organizer");
  }

  return { user, workspace };
}

Build docs developers (and LLMs) love