This page did the auth checking directly on the page file.
25 |
{JSON.stringify({ isAuthenticated }, null, 2)}
26 |
{JSON.stringify(user, null, 2)}
27 |
28 |
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/next-seo.config.js:
--------------------------------------------------------------------------------
1 | const title = 'Learn Next.js Auth Redirect';
2 | const description =
3 | 'Attempt to learn how to redirect Next.js protected page without flashing content';
4 |
5 | const SEO = {
6 | title,
7 | description,
8 | // canonical: 'https://theodorusclarence.com',
9 | openGraph: {
10 | type: 'website',
11 | locale: 'en_IE',
12 | url: 'https://theodorusclarence.com',
13 | title,
14 | description,
15 | images: [
16 | {
17 | url:
18 | 'https://theodorusclarence.com/favicon/ms-icon-144x144.png',
19 | alt: title,
20 | width: 144,
21 | height: 144,
22 | },
23 | ],
24 | },
25 | };
26 |
27 | export default SEO;
28 |
29 | // EXAMPLES
30 | {
31 | /*
32 | const title = 'Next.js Tailwind Starter';
33 | const description = 'your description';
34 | const url = 'https://theodorusclarence.com';
35 |
36 | ; */
46 | }
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Learn Auth Redirect Nextjs
2 | This is a NextJs and Tailwind project bootstrapped using nextjs-tailwind-starter created by [Theodorus Clarence](https://github.com/theodorusclarence/nextjs-tailwind-starter).
3 |
4 | ## Log
5 | - [x] redirect when is not logged in (works if you directly open /blocked)
6 | - [x] don't show content when waiting to check if logged in (fixed with full page loader)
7 | - [ ] when going to page /blocked using button, still flashes full page loader for a split second
8 |
9 |
10 |
11 | ## Getting Started
12 |
13 | To use this starter, you can use create-next-app to do it by:
14 | ```bash
15 | npx create-next-app -e https://github.com/theodorusclarence/nextjs-tailwind-starter project-name
16 | ```
17 |
18 | or
19 |
20 | [](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Ftheodorusclarence%2Fnextjs-tailwind-starter)
21 |
22 | First, run the development server:
23 |
24 | ```bash
25 | npm run dev
26 | # or
27 | yarn dev
28 | ```
29 |
30 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
31 |
32 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file
33 |
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @layer base {
6 | /* inter-regular - latin */
7 | @font-face {
8 | font-family: 'Inter';
9 | font-style: normal;
10 | font-weight: 400;
11 | font-display: optional;
12 | src: local('Inter'),
13 | url('/fonts/inter-regular-webfont.woff2') format('woff2'),
14 | url('/fonts/inter-regular-webfont.woff') format('woff');
15 | }
16 |
17 | /* inter-500 - latin */
18 | @font-face {
19 | font-family: 'Inter';
20 | font-style: normal;
21 | font-weight: 500;
22 | font-display: optional;
23 | src: local('Inter'),
24 | url('/fonts/inter-medium-webfont.woff2') format('woff2'),
25 | url('/fonts/inter-medium-webfont.woff') format('woff');
26 | }
27 |
28 | /* inter-700 - latin */
29 | @font-face {
30 | font-family: 'Inter';
31 | font-style: normal;
32 | font-weight: 700;
33 | font-display: optional;
34 | src: local('Inter'),
35 | url('/fonts/inter-bold-webfont.woff2') format('woff2'),
36 | url('/fonts/inter-bold-webfont.woff') format('woff');
37 | }
38 |
39 | /* Write your own custom base styles here */
40 | h1 {
41 | @apply text-3xl font-bold md:text-5xl font-primary;
42 | }
43 |
44 | h2 {
45 | @apply text-2xl font-bold md:text-4xl font-primary;
46 | }
47 |
48 | h3 {
49 | @apply text-xl font-bold md:text-3xl font-primary;
50 | }
51 |
52 | h4 {
53 | @apply text-lg font-bold font-primary;
54 | }
55 |
56 | body {
57 | @apply text-sm font-primary md:text-base;
58 | }
59 |
60 | .layout {
61 | /* 750px */
62 | /* max-width: 43.75rem; */
63 |
64 | /* 1100px */
65 | max-width: 68.75rem;
66 | @apply w-11/12 mx-auto;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/contexts/auth.js:
--------------------------------------------------------------------------------
1 | import React, { createContext, useContext, useState, useEffect } from 'react';
2 | import { useRouter } from 'next/router';
3 | const AuthContext = createContext();
4 |
5 | function AuthProvider({ children }) {
6 | const [user, setUser] = useState({
7 | error: 'you are logged out, and there is no user object, and no token',
8 | });
9 | const [isAuthenticated, setIsAuthenticated] = useState(false);
10 | const [isLoading, setIsLoading] = useState(true);
11 |
12 | useEffect(() => {
13 | const token = localStorage.getItem('token');
14 | console.log('token: ', token);
15 | if (!(token === null || token === undefined)) {
16 | loginWithToken();
17 | }
18 | setIsLoading(false);
19 | }, []);
20 |
21 | function loginWithToken() {
22 | localStorage.setItem('token', 'true');
23 | setIsAuthenticated(true);
24 | setUser({
25 | name: 'hello',
26 | msg: 'Logged in because token in localStorage',
27 | });
28 | }
29 | function login() {
30 | setIsAuthenticated(true);
31 | setUser({
32 | name: 'hello',
33 | msg: 'Logged in by clicking login button, you still have no token',
34 | });
35 | }
36 |
37 | function logout() {
38 | setIsAuthenticated(false);
39 | setUser({
40 | error: 'you are logged out, and there is no user object, and no token',
41 | });
42 | localStorage.removeItem('token');
43 | }
44 |
45 | return (
46 |
56 | {children}
57 |
58 | );
59 | }
60 |
61 | const useAuth = () => useContext(AuthContext);
62 |
63 | export { AuthProvider, useAuth };
64 |
--------------------------------------------------------------------------------
/pages/index.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 | import { NextSeo } from 'next-seo';
3 |
4 | import { useAuth } from '@/contexts/auth';
5 | import CustomLink from '@/components/CustomLink';
6 |
7 | export default function Home() {
8 | const { user, logout, login, isAuthenticated, loginWithToken } = useAuth();
9 | const [originLocation, setOriginLocation] = useState(
10 | 'http://localhost:3000'
11 | );
12 |
13 | useEffect(() => {
14 | if (typeof window !== 'undefined') {
15 | setOriginLocation(window.location.origin);
16 | }
17 | }, []);
18 |
19 | const addToken = () => {
20 | loginWithToken();
21 | };
22 |
23 | return (
24 | <>
25 |
26 |
27 |
28 |
29 |
30 |
Learn Auth Redirect Next.js
31 |
32 | If we open a page and it is not logged in, it will
33 | show a full page loader, then when it is fully
34 | rendered, useEffect will run and push to home page.
35 |
36 |
37 | The blocked-unhandled will show the case when not
38 | using full page loader, and it will flash the
39 | content
40 |
41 |
45 | Check out this blog post for explanation
46 |
47 |
68 | Setting up token, if you add token, then you are
69 | considered logged in even in a new tab
70 |
71 |
74 |
77 |
78 |
79 | List of page (using Next.js Link), will authorized
80 | if login (token & no token):
81 |
82 |
83 |
84 | go to /unprotected page (everyone can access
85 | even if not logged in)
86 |
87 |
88 | go to /blocked-unhandled page (will flash
89 | content, try opening a new tab to see more
90 | clearly)
91 |
92 |
93 | go to /blocked page (won't show content if not
94 | authorized)
95 |
96 |
97 | go to /blocked-component page
98 |
99 |
100 |
101 | Try to directly go to (will open a new tab), will
102 | only authorized if using token:
103 |