Skip to content

Commit

Permalink
Merge pull request #10 from podcodar/marco/handle-redirects
Browse files Browse the repository at this point in the history
Improve authentication workflow
  • Loading branch information
marco-souza authored May 12, 2023
2 parents 19bf659 + c1aec10 commit 1ee18d3
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 42 deletions.
19 changes: 8 additions & 11 deletions src/app/admin/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import Navbar from "@/components/Navbar";
import { container } from "@/shared/tw";
import { Metadata } from "next";
import { PropsWithChildren } from "react";
import AuthProvider from "@/contexts/AuthProvider";
import { getServerSession } from "next-auth";
import { authOptions } from "@/shared/auth";
import { redirect } from "next/navigation";
import { headers } from "next/headers";
import { PropsWithChildren } from "react";
import AuthProvider from "@/contexts/AuthProvider";
import { authOptions, makeRedirectURL, getOriginPath } from "@/shared/auth";
import Navbar from "@/components/Navbar";
import { container } from "@/shared/tw";

export const metadata: Metadata = {
title: "PodCodar Admin",
Expand All @@ -16,11 +15,9 @@ export default async function RootLayout({ children }: PropsWithChildren) {
const session = await getServerSession(authOptions);

if (!session) {
const headerObj = headers();
const origin = headerObj.get("x-url") ?? "";

return redirect(`/login?callbackUrl=${origin}`);
};
const origin = getOriginPath();
return redirect(makeRedirectURL(origin));
}

return (
<body>
Expand Down
15 changes: 12 additions & 3 deletions src/app/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import Navbar from "@/components/Navbar";
import { container } from "@/shared/tw";
import { Metadata } from "next";
import { PropsWithChildren } from "react";
import { getServerSession } from "next-auth";
import { redirect } from "next/navigation";
import { container } from "@/shared/tw";
import { authOptions, makeRedirectURL, getOriginPath } from "@/shared/auth";
import Navbar from "@/components/Navbar";
import AuthProvider from "@/contexts/AuthProvider";

export const metadata: Metadata = {
title: "PodCodar",
};

export default async function RootLayout({ children }: PropsWithChildren) {
// TODO: Validate Auth
const session = await getServerSession(authOptions);

if (!session) {
const origin = getOriginPath();
return redirect(makeRedirectURL(origin));
}

return (
<body>
<AuthProvider>
Expand Down
14 changes: 11 additions & 3 deletions src/app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import GithubSignInButton from "@/components/GithubSignInButton";
import SignOutButton from "@/components/SignOutButton";
import { authOptions } from "@/shared/auth";
import { getServerSession } from "next-auth";
import { redirect } from "next/navigation";

const SignInPage = async () => {
const session = await getServerSession(authOptions);

if (session) {
// TODO: get user role to see where to redirect (/app or /admin)
return redirect("/app");
}

const SignInPage = () => {
return (
<section className='flex flex-col gap-8 items-center justify-center'>
<GithubSignInButton />
<SignOutButton />
</section>
);
};
Expand Down
14 changes: 8 additions & 6 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This code is based on the example from https://tailwindui.com/components/application-ui/navigation/navbars
"use client";
import { Fragment } from "react";
import { signOut } from "next-auth/react";
import { Disclosure, Menu, Transition } from "@headlessui/react";
import { Bars3Icon, BellIcon, XMarkIcon } from "@heroicons/react/24/outline";
import { Logo } from "./Logo";
Expand All @@ -21,7 +22,7 @@ const navigation = [
{ name: "Agenda", href: "#", current: false },
];

const profileLinks = [{ name: "Settings", href: "#" }, { name: "Sign out", href: "#" },];
const profileLinks = [{ name: "Settings", onClick: () => {} }, { name: "Sign out", onClick: () => signOut() }];

export default function Navbar() {
return (
Expand Down Expand Up @@ -91,15 +92,16 @@ export default function Navbar() {
{profileLinks.map((item) => (
<Menu.Item key={item.name}>
{({ active }) => (
<a
<Disclosure.Button
as="button"
className={classes(
active ? "bg-gray-100" : "",
"block px-4 py-2 text-sm text-gray-700"
)}
href={item.href}
onClick={item.onClick}
>
{item.name}
</a>
</Disclosure.Button>
)}
</Menu.Item>
))}
Expand Down Expand Up @@ -171,10 +173,10 @@ export default function Navbar() {
<div className="mt-3 space-y-1 px-2">
{profileLinks.map((item) => (
<Disclosure.Button
as="a"
as="button"
className="block rounded-md px-3 py-2 text-base font-medium text-gray-400 hover:bg-gray-700 hover:text-white"
href={item.href}
key={item.name}
onClick={item.onClick}
>
{item.name}
</Disclosure.Button>
Expand Down
16 changes: 0 additions & 16 deletions src/components/SignOutButton.tsx

This file was deleted.

5 changes: 3 additions & 2 deletions src/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { NextRequest, NextResponse } from "next/server";
import { ORIGIN_URL_KEY } from "@/shared/settings";

export function middleware(request: NextRequest) {
// add origin path to redirect when not session available
const headers = new Headers(request.headers);
headers.set("x-url", request.nextUrl.pathname);
headers.set(ORIGIN_URL_KEY, request.nextUrl.pathname);

return NextResponse.next({
request: { headers }
});
};

export const config = {
matcher: ["/admin/:path*"]
matcher: ["/app/:path*", "/admin/:path*"]
};
13 changes: 12 additions & 1 deletion src/shared/auth.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import { headers } from "next/headers";
import { NextAuthOptions } from "next-auth";
import GithubProvider from "next-auth/providers/github";
import { githubCredentials } from "./settings";
import { NO_SESSION_REDIRECT, ORIGIN_URL_KEY, githubCredentials } from "./settings";

export const authOptions: NextAuthOptions = {
providers: [GithubProvider(githubCredentials)],
pages: {
signIn: "/login"
}
};

export function getOriginPath() {
const headerObj = headers();
const origin = headerObj.get(ORIGIN_URL_KEY) ?? "";
return origin;
}

export function makeRedirectURL(origin: string) {
return `${NO_SESSION_REDIRECT}${origin}`;
}
3 changes: 3 additions & 0 deletions src/shared/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ export const githubCredentials = {
clientId: process.env.GITHUB_CLIENT_ID as string,
clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
};

export const ORIGIN_URL_KEY = "x-url";
export const NO_SESSION_REDIRECT = "/login?callbackUrl=";

1 comment on commit 1ee18d3

@vercel
Copy link

@vercel vercel bot commented on 1ee18d3 May 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.