diff --git a/auth/app/api/auth/signedout/route.ts b/auth/app/api/auth/signedout/route.ts
new file mode 100644
index 0000000..06db5b6
--- /dev/null
+++ b/auth/app/api/auth/signedout/route.ts
@@ -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);
+}
diff --git a/auth/app/api/auth/signin/route.ts b/auth/app/api/auth/signin/route.ts
index db36646..b731cc8 100644
--- a/auth/app/api/auth/signin/route.ts
+++ b/auth/app/api/auth/signin/route.ts
@@ -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();
@@ -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);
diff --git a/auth/app/api/auth/signout/route.ts b/auth/app/api/auth/signout/route.ts
index 51ce5ef..cf790e9 100644
--- a/auth/app/api/auth/signout/route.ts
+++ b/auth/app/api/auth/signout/route.ts
@@ -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 });
}
diff --git a/auth/app/auth/signedout/page.tsx b/auth/app/auth/signedout/page.tsx
new file mode 100644
index 0000000..6fca2d9
--- /dev/null
+++ b/auth/app/auth/signedout/page.tsx
@@ -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);
+}
diff --git a/auth/app/auth/signout/page.tsx b/auth/app/auth/signout/page.tsx
index acedc1a..a34eb76 100644
--- a/auth/app/auth/signout/page.tsx
+++ b/auth/app/auth/signout/page.tsx
@@ -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