Replaced NextAuth's built-in OAuth provider (incompatible with Cloudflare Workers) with custom OAuth implementation using native fetch API. Features: - Custom OAuth flow compatible with Cloudflare Workers edge runtime - Auto-provisions users from Nextcloud based on group membership - Group-based role assignment (artists, shop_admins, admins) - Auto-creates artist profiles for users in 'artists' group - Seamless integration with existing NextAuth session management Technical changes: - Added custom OAuth routes: /api/auth/nextcloud/authorize & callback - Created Nextcloud API client for user provisioning (lib/nextcloud-client.ts) - Extended credentials provider to accept Nextcloud one-time tokens - Added user management functions to database layer - Updated signin UI to use custom OAuth flow - Added environment variables for OAuth configuration Documentation: - Comprehensive setup guide in docs/NEXTCLOUD-OAUTH-SETUP.md - Updated CLAUDE.md with new authentication architecture Fixes: NextAuth OAuth incompatibility with Cloudflare Workers (unenv https.request error) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
56 lines
1.8 KiB
TypeScript
56 lines
1.8 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { cookies } from 'next/headers'
|
|
|
|
/**
|
|
* Custom Nextcloud OAuth Authorization Handler
|
|
*
|
|
* This route initiates the OAuth flow by redirecting to Nextcloud's authorization endpoint.
|
|
* Uses native fetch API instead of NextAuth's OAuth provider (which doesn't work in Cloudflare Workers).
|
|
*/
|
|
export async function GET(request: NextRequest) {
|
|
const baseUrl = process.env.NEXTCLOUD_BASE_URL
|
|
const clientId = process.env.NEXTCLOUD_OAUTH_CLIENT_ID
|
|
|
|
if (!baseUrl || !clientId) {
|
|
return NextResponse.json(
|
|
{ error: 'Nextcloud OAuth is not configured' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
|
|
// Get callback URL from request or use default
|
|
const callbackUrl = request.nextUrl.searchParams.get('callbackUrl') || '/admin'
|
|
|
|
// Generate random state for CSRF protection
|
|
const state = crypto.randomUUID()
|
|
|
|
// Store state and callback URL in cookies
|
|
const cookieStore = await cookies()
|
|
cookieStore.set('nextcloud_oauth_state', state, {
|
|
httpOnly: true,
|
|
secure: process.env.NODE_ENV === 'production',
|
|
sameSite: 'lax',
|
|
maxAge: 600, // 10 minutes
|
|
path: '/',
|
|
})
|
|
|
|
cookieStore.set('nextcloud_oauth_callback', callbackUrl, {
|
|
httpOnly: true,
|
|
secure: process.env.NODE_ENV === 'production',
|
|
sameSite: 'lax',
|
|
maxAge: 600,
|
|
path: '/',
|
|
})
|
|
|
|
// Build authorization URL
|
|
const authUrl = new URL(`${baseUrl}/index.php/apps/oauth2/authorize`)
|
|
authUrl.searchParams.set('client_id', clientId)
|
|
authUrl.searchParams.set('response_type', 'code')
|
|
authUrl.searchParams.set('redirect_uri', `${process.env.NEXTAUTH_URL}/api/auth/nextcloud/callback`)
|
|
authUrl.searchParams.set('state', state)
|
|
authUrl.searchParams.set('scope', 'openid profile email')
|
|
|
|
// Redirect to Nextcloud
|
|
return NextResponse.redirect(authUrl.toString())
|
|
}
|