fix mfa login after keycloak
This commit is contained in:
28
app/api/after-mfa/route.ts
Normal file
28
app/api/after-mfa/route.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { enhanceRouteHandler } from '@/packages/next/src/routes';
|
||||||
|
import { createAuthCallbackService } from '@/packages/supabase/src/auth-callback.service';
|
||||||
|
import { getSupabaseServerClient } from '@/packages/supabase/src/clients/server-client';
|
||||||
|
|
||||||
|
export const POST = () =>
|
||||||
|
enhanceRouteHandler(
|
||||||
|
async () => {
|
||||||
|
try {
|
||||||
|
const supabaseClient = getSupabaseServerClient();
|
||||||
|
const {
|
||||||
|
data: { user },
|
||||||
|
} = await supabaseClient.auth.getUser();
|
||||||
|
const service = createAuthCallbackService(supabaseClient);
|
||||||
|
|
||||||
|
if (user && service.isKeycloakUser(user)) {
|
||||||
|
await service.setupMedusaUserForKeycloak(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(null, { status: 200 });
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error on verifying:', { err });
|
||||||
|
return new Response(null, { status: 500 });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
auth: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
@@ -47,6 +47,11 @@ export async function GET(request: NextRequest) {
|
|||||||
|
|
||||||
const service = createAuthCallbackService(getSupabaseServerClient());
|
const service = createAuthCallbackService(getSupabaseServerClient());
|
||||||
const oauthResult = await service.exchangeCodeForSession(authCode);
|
const oauthResult = await service.exchangeCodeForSession(authCode);
|
||||||
|
|
||||||
|
if (oauthResult.requiresMultiFactorAuthentication) {
|
||||||
|
redirect(pathsConfig.auth.verifyMfa);
|
||||||
|
}
|
||||||
|
|
||||||
if (!('isSuccess' in oauthResult)) {
|
if (!('isSuccess' in oauthResult)) {
|
||||||
return redirectOnError(oauthResult.searchParams);
|
return redirectOnError(oauthResult.searchParams);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,12 +44,7 @@ async function VerifyPage(props: Props) {
|
|||||||
!!nextPath && nextPath.length > 0 ? nextPath : pathsConfig.app.home;
|
!!nextPath && nextPath.length > 0 ? nextPath : pathsConfig.app.home;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MultiFactorChallengeContainer
|
<MultiFactorChallengeContainer userId={user.id} paths={{ redirectPath }} />
|
||||||
userId={user.id}
|
|
||||||
paths={{
|
|
||||||
redirectPath,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,8 +46,13 @@ export function MultiFactorChallengeContainer({
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const verifyMFAChallenge = useVerifyMFAChallenge({
|
const verifyMFAChallenge = useVerifyMFAChallenge({
|
||||||
onSuccess: () => {
|
onSuccess: async () => {
|
||||||
router.replace(paths.redirectPath);
|
try {
|
||||||
|
await fetch('/api/after-mfa', { method: 'POST' });
|
||||||
|
router.replace(paths.redirectPath);
|
||||||
|
} catch (err) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import 'server-only';
|
import 'server-only';
|
||||||
|
|
||||||
import getBaseWebpackConfig from 'next/dist/build/webpack-config';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AuthError,
|
AuthError,
|
||||||
type EmailOtpType,
|
type EmailOtpType,
|
||||||
@@ -9,6 +7,8 @@ import {
|
|||||||
User,
|
User,
|
||||||
} from '@supabase/supabase-js';
|
} from '@supabase/supabase-js';
|
||||||
|
|
||||||
|
import { checkRequiresMultiFactorAuthentication } from './check-requires-mfa';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name createAuthCallbackService
|
* @name createAuthCallbackService
|
||||||
* @description Creates an instance of the AuthCallbackService
|
* @description Creates an instance of the AuthCallbackService
|
||||||
@@ -137,10 +137,12 @@ class AuthCallbackService {
|
|||||||
| {
|
| {
|
||||||
isSuccess: boolean;
|
isSuccess: boolean;
|
||||||
user: User;
|
user: User;
|
||||||
|
requiresMultiFactorAuthentication: boolean;
|
||||||
}
|
}
|
||||||
| ErrorURLParameters
|
| ErrorURLParameters
|
||||||
> {
|
> {
|
||||||
let user: User;
|
let user: User;
|
||||||
|
let requiresMultiFactorAuthentication: boolean;
|
||||||
try {
|
try {
|
||||||
const { data, error } =
|
const { data, error } =
|
||||||
await this.client.auth.exchangeCodeForSession(authCode);
|
await this.client.auth.exchangeCodeForSession(authCode);
|
||||||
@@ -153,8 +155,14 @@ class AuthCallbackService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Keycloak users - set up Medusa integration
|
requiresMultiFactorAuthentication =
|
||||||
if (data?.user && this.isKeycloakUser(data.user)) {
|
await checkRequiresMultiFactorAuthentication(this.client);
|
||||||
|
|
||||||
|
if (
|
||||||
|
!requiresMultiFactorAuthentication &&
|
||||||
|
data?.user &&
|
||||||
|
this.isKeycloakUser(data.user)
|
||||||
|
) {
|
||||||
await this.setupMedusaUserForKeycloak(data.user);
|
await this.setupMedusaUserForKeycloak(data.user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,20 +187,21 @@ class AuthCallbackService {
|
|||||||
return {
|
return {
|
||||||
isSuccess: true,
|
isSuccess: true,
|
||||||
user,
|
user,
|
||||||
|
requiresMultiFactorAuthentication,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if user is from Keycloak provider
|
* Check if user is from Keycloak provider
|
||||||
*/
|
*/
|
||||||
private isKeycloakUser(user: any): boolean {
|
isKeycloakUser(user: any): boolean {
|
||||||
return (
|
return (
|
||||||
user?.app_metadata?.provider === 'keycloak' ||
|
user?.app_metadata?.provider === 'keycloak' ||
|
||||||
user?.app_metadata?.providers?.includes('keycloak')
|
user?.app_metadata?.providers?.includes('keycloak')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async setupMedusaUserForKeycloak(user: any): Promise<void> {
|
async setupMedusaUserForKeycloak(user: any): Promise<void> {
|
||||||
if (!user.email) {
|
if (!user.email) {
|
||||||
console.warn('Keycloak user has no email, skipping Medusa setup');
|
console.warn('Keycloak user has no email, skipping Medusa setup');
|
||||||
return;
|
return;
|
||||||
@@ -285,6 +294,7 @@ interface ErrorURLParameters {
|
|||||||
error: string;
|
error: string;
|
||||||
code?: string;
|
code?: string;
|
||||||
searchParams: string;
|
searchParams: string;
|
||||||
|
requiresMultiFactorAuthentication: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getErrorURLParameters({
|
export function getErrorURLParameters({
|
||||||
@@ -313,6 +323,7 @@ export function getErrorURLParameters({
|
|||||||
error: errorMessage,
|
error: errorMessage,
|
||||||
code: code ?? '',
|
code: code ?? '',
|
||||||
searchParams: searchParams.toString(),
|
searchParams: searchParams.toString(),
|
||||||
|
requiresMultiFactorAuthentication: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user