Skip to content

Commit

Permalink
🪰
Browse files Browse the repository at this point in the history
  • Loading branch information
quochuydev committed Aug 14, 2024
1 parent c45b423 commit 1a67e2e
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 18 deletions.
11 changes: 11 additions & 0 deletions auth/app/api/auth/signedout/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import configuration from "@/configuration";
import { returnUrlCookieName } from "@/lib/constant";
import { cookies } from "next/headers";
import { NextResponse } from "next/server";

export async function POST() {
const requestCookie = cookies();
const returnUrlCookie = requestCookie.get(returnUrlCookieName);
const redirectUrl = returnUrlCookie?.value || configuration.appUrl;
return NextResponse.redirect(redirectUrl);
}
23 changes: 19 additions & 4 deletions auth/app/api/auth/signin/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ export async function POST(request: NextRequest) {
if (!csrfTokenCookie) throw new Error("csrfToken cookie not found");
if (csrfTokenCookie.value !== csrfToken) throw new Error("Invalid csrfToken");

const wellKnownResponse = await fetch(
`${configuration.portal.issuer}/.well-known/openid-configuration`
);

const wellKnown = (await wellKnownResponse.json()) as {
issuer: string;
authorization_endpoint: string;
token_endpoint: string;
userinfo_endpoint: string;
end_session_endpoint: string;
};

if (wellKnownResponse.status !== 200) {
throw { code: wellKnownResponse.status, details: wellKnown };
}

const codeVerifier = generateCodeVerifier();
const codeChallenge = generateCodeChallenge(codeVerifier);
const state = generateState();
Expand Down Expand Up @@ -59,10 +75,9 @@ export async function POST(request: NextRequest) {
if (prompt) params.prompt = prompt;
if (loginHint) params.login_hint = loginHint;

const authorizeUrl = new URL(
`/oauth/v2/authorize?${new URLSearchParams(params).toString()}`,
configuration.portal.issuer
).toString();
const authorizeUrl = `${
wellKnown.authorization_endpoint
}?${new URLSearchParams(params).toString()}`;

if (returnUrl) setShortLiveCookie(returnUrlCookieName, returnUrl);
setShortLiveCookie(stateCookieName, state);
Expand Down
65 changes: 62 additions & 3 deletions auth/app/api/auth/signout/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,64 @@
import { NextResponse } from "next/server";
import configuration from "@/configuration";
import { returnUrlCookieName } from "@/lib/constant";
import { setShortLiveCookie } from "@/lib/cookie";
import { prisma } from "@/lib/prisma";
import { NextRequest, NextResponse } from "next/server";

export async function GET() {
return NextResponse.json({});
export async function POST(request: NextRequest) {
const body = (await request.json()) as {
returnUrl?: string;
idTokenHint?: string;
clientId?: string;
postLogoutRedirectUri?: string;
state?: string;
};
const { returnUrl, idTokenHint, clientId, postLogoutRedirectUri, state } =
body;

const wellKnownResponse = await fetch(
`${configuration.portal.issuer}/.well-known/openid-configuration`
);

const wellKnown = (await wellKnownResponse.json()) as {
issuer: string;
authorization_endpoint: string;
token_endpoint: string;
userinfo_endpoint: string;
end_session_endpoint: string;
};

if (wellKnownResponse.status !== 200) {
throw { code: wellKnownResponse.status, details: wellKnown };
}

const params: {
id_token_hint?: string;
client_id?: string;
post_logout_redirect_uri?: string;
state?: string;
} = {
id_token_hint: idTokenHint,
client_id: clientId,
post_logout_redirect_uri: postLogoutRedirectUri,
state: state,
};

if (idTokenHint) {
await prisma.session.updateMany({
where: {
idToken: idTokenHint,
},
data: {
deletedAt: new Date(),
},
});
}

const endSessionUrl = `${
wellKnown.end_session_endpoint
}?${new URLSearchParams(params).toString()}`;

if (returnUrl) setShortLiveCookie(returnUrlCookieName, returnUrl);

return NextResponse.json({ endSessionUrl });
}
12 changes: 12 additions & 0 deletions auth/app/auth/signedout/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import configuration from "@/configuration";
import { returnUrlCookieName } from "@/lib/constant";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";

export default async function Page({ searchParams }: { searchParams: {} }) {
console.log(`debug:searchParams`, searchParams);
const requestCookie = cookies();
const returnUrlCookie = requestCookie.get(returnUrlCookieName);
const redirectUrl = returnUrlCookie?.value || configuration.appUrl;
return redirect(redirectUrl);
}
17 changes: 13 additions & 4 deletions auth/app/auth/signout/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,19 @@ export default async function Page({
}: {
searchParams: {
return_url?: string;
prompt?: string;
scope?: string;
login_hint?: string;
id_token_hint?: string;
client_id?: string;
post_logoutRedirect_uri?: string;
state?: string;
};
}) {
return <SignOut returnUrl={searchParams.return_url} />;
return (
<SignOut
returnUrl={searchParams.return_url}
idTokenHint={searchParams.id_token_hint}
clientId={searchParams.client_id}
postLogoutRedirectUri={searchParams.post_logoutRedirect_uri}
state={searchParams.state}
/>
);
}
2 changes: 1 addition & 1 deletion auth/ui/SignIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ export default function SignIn(props: {
scope?: string;
loginHint?: string;
}) {
const { returnUrl, prompt, scope, loginHint } = props;
const router = useRouter();
const { returnUrl, prompt, scope, loginHint } = props;

useEffect(() => {
fetch(`https://auth.example.local/api/auth/csrf`, {
Expand Down
26 changes: 20 additions & 6 deletions auth/ui/SignOut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,33 @@
import { useEffect } from "react";
import { useRouter } from "next/navigation";

export default function SignOut(props: { returnUrl?: string }) {
const { returnUrl } = props;
export default function SignOut(props: {
returnUrl?: string;
idTokenHint?: string;
clientId?: string;
postLogoutRedirectUri?: string;
state?: string;
}) {
const { returnUrl, idTokenHint, clientId, postLogoutRedirectUri, state } =
props;
const router = useRouter();

useEffect(() => {
fetch(`https://auth.example.local/api/auth/signout`, {
method: "GET",
method: "POST",
body: JSON.stringify({
returnUrl,
idTokenHint,
clientId,
postLogoutRedirectUri,
state,
}),
})
.then((response) => response.json())
.then(async (data) => {
console.log(`debug:data`, data);
.then(({ endSessionUrl }) => {
if (endSessionUrl) router.replace(endSessionUrl);
});
}, [returnUrl, router]);
}, [clientId, idTokenHint, postLogoutRedirectUri, returnUrl, router, state]);

return <div>Loading...</div>;
}

0 comments on commit 1a67e2e

Please sign in to comment.