Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve authentication workflow #10

Merged
merged 9 commits into from
May 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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=";