Sign in with microsoft now works but sign out when signed in via microsoft does not

This commit is contained in:
2025-06-06 16:35:28 -05:00
parent 35e019558f
commit 930dc0867d
6 changed files with 43 additions and 81 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,4 +1,3 @@
// src/app/(auth-pages)/auth/callback/route.ts
'use server'; 'use server';
import 'server-only'; import 'server-only';
import { createServerClient } from '@/utils/supabase'; import { createServerClient } from '@/utils/supabase';
@ -12,10 +11,8 @@ export const GET = async (request: NextRequest) => {
const token_hash = searchParams.get('token'); const token_hash = searchParams.get('token');
const type = searchParams.get('type') as EmailOtpType | null; const type = searchParams.get('type') as EmailOtpType | null;
const redirectTo = searchParams.get('redirect_to') ?? '/'; const redirectTo = searchParams.get('redirect_to') ?? '/';
const supabase = await createServerClient(); const supabase = await createServerClient();
// Handle OAuth callback (Microsoft, Apple, etc.)
if (code) { if (code) {
const { error } = await supabase.auth.exchangeCodeForSession(code); const { error } = await supabase.auth.exchangeCodeForSession(code);
if (error) { if (error) {
@ -25,7 +22,6 @@ export const GET = async (request: NextRequest) => {
return redirect(redirectTo); return redirect(redirectTo);
} }
// Handle email OTP (existing logic)
if (token_hash && type) { if (token_hash && type) {
const { error } = await supabase.auth.verifyOtp({ const { error } = await supabase.auth.verifyOtp({
type, type,

View File

@ -1,77 +0,0 @@
'use server';
import 'server-only';
import { createServerClient } from '@/utils/supabase';
import { type EmailOtpType } from '@supabase/supabase-js';
import { type NextRequest, NextResponse } from 'next/server';
export const GET = async (request: NextRequest) => {
const { searchParams, origin } = new URL(request.url);
const code = searchParams.get('code');
const token = searchParams.get('token');
const type = searchParams.get('type') as EmailOtpType | null;
const redirectTo = searchParams.get('redirect_to')?.toString();
const supabase = await createServerClient();
if (token && type) {
try {
if (type === 'signup') {
// Confirm email signup
const { error } = await supabase.auth.verifyOtp({
token_hash: token,
type: 'signup',
});
if (error) {
console.error('Email confirmation error:', error);
return NextResponse.redirect(`${origin}/sign-in?error=Invalid or expired confirmation link`);
}
} else if (type === 'recovery') {
// Handle password recovery
const { error } = await supabase.auth.verifyOtp({
token_hash: token,
type: 'recovery',
});
if (error) {
console.error('Password recovery error:', error);
return NextResponse.redirect(`${origin}/sign-in?error=Invalid or expired reset link`);
} else {
return NextResponse.redirect(`${origin}/reset-password`);
}
} else if (type === 'email_change') {
// Handle email change
const { error } = await supabase.auth.verifyOtp({
token_hash: token,
type: 'email_change',
});
if (error) {
console.error('Email change error:', error);
return NextResponse.redirect(`${origin}/profile?error=Invalid or expired email change link`);
}
}
} catch (error) {
console.error('Verification error:', error);
return NextResponse.redirect(`${origin}/sign-in?error=Verification failed`);
}
}
// Handle code-based flow (OAuth, etc.)
if (code) {
await supabase.auth.exchangeCodeForSession(code);
}
// Handle redirect
if (redirectTo) {
try {
new URL(redirectTo);
return NextResponse.redirect(redirectTo);
} catch {
return NextResponse.redirect(`${origin}${redirectTo}`);
}
}
return NextResponse.redirect(origin);
}

View File

@ -0,0 +1,39 @@
'use client';
import { useAuth } from '@/components/context/auth';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
import { Loader2 } from 'lucide-react';
const AuthSuccessPage = () => {
const { refreshUserData, isAuthenticated } = useAuth();
const router = useRouter();
useEffect(() => {
const handleAuthSuccess = async () => {
// Refresh the auth context to pick up the new session
await refreshUserData();
// Small delay to ensure state is updated
setTimeout(() => {
router.push('/');
}, 100);
};
handleAuthSuccess().catch((error) => {
console.error(`Error: ${error instanceof Error ? error.message : error}`);
});
}, [refreshUserData, router]);
// Show loading while processing
return (
<div className='flex items-center justify-center min-h-screen'>
<div className='flex flex-col items-center space-y-4'>
<Loader2 className='h-8 w-8 animate-spin' />
<p>Completing sign in...</p>
</div>
</div>
);
};
export default AuthSuccessPage;

View File

@ -60,10 +60,12 @@ export const signIn = async (formData: FormData): Promise<Result<null>> => {
export const signInWithMicrosoft = async (): Promise<Result<string>> => { export const signInWithMicrosoft = async (): Promise<Result<string>> => {
const supabase = await createServerClient(); const supabase = await createServerClient();
const origin = (await headers()).get('origin');
const { data, error } = await supabase.auth.signInWithOAuth({ const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'azure', provider: 'azure',
options: { options: {
scopes: 'openid, profile email offline_access', scopes: 'openid, profile email offline_access',
redirectTo: `${origin}/auth/callback?redirect_to=/auth/success`,
}, },
}); });
if (error) return { success: false, error: error.message }; if (error) return { success: false, error: error.message };
@ -72,10 +74,12 @@ export const signInWithMicrosoft = async (): Promise<Result<string>> => {
export const signInWithApple = async (): Promise<Result<string>> => { export const signInWithApple = async (): Promise<Result<string>> => {
const supabase = await createServerClient(); const supabase = await createServerClient();
const origin = process.env.BASE_URL!;
const { data, error } = await supabase.auth.signInWithOAuth({ const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'apple', provider: 'apple',
options: { options: {
scopes: 'openid, profile email offline_access', scopes: 'openid, profile email offline_access',
redirectTo: `${origin}/auth/callback?redirect_to=/auth/success`,
}, },
}); });
if (error) return { success: false, error: error.message }; if (error) return { success: false, error: error.message };