1

I want a custom page rendered on access_denied/ [next-auth][error][OAUTH_CALLBACK_ERROR] on nextAuth signIn()

In _app.tsx,

    export default function App({Component, pageProps}: ProtectedAppProps<{session: Session;GOOGLE_ANALYTICS:string}>) {
    ....
    return <React.Fragment>
                   <Auth>
                      <Component {...pageProps} /> 
                </Auth>
    </React.Fragment>
 }

  function Auth({ children } : any) {
      const { status } = useSession({ required: true,
        onUnauthenticated() {
          signIn('okta');
        }, 
      })
    
      if (status === "loading") {
        return <div>Loading...</div>
      }
      return children
 }

Inside pages->api->auth->[...nextauth].ts,

import NextAuth from 'next-auth'
import { JWT } from 'next-auth/jwt'
import OktaProvider from 'next-auth/providers/okta'


async function refreshAccessToken(token: JWT) {
  ...
}

export default NextAuth({
    providers: [
        OktaProvider({
          clientId : process.env.OKTA_OAUTH2_CLIENT_ID as string,
          clientSecret : process.env.OKTA_OAUTH2_CLIENT_SECRET as string,
          issuer : process.env.OKTA_OAUTH2_ISSUER as string,
          authorization: {
            params: {
              scope:  'openid profile email offline_access',
            }
          }
      }),
    ],
    pages: {
      error: "/auth/error",
    },
    secret : process.env.JWT_SECRET as string,
    callbacks: {
      async redirect({ url, baseUrl }) {
        if (url === "/api/auth/signin" || url === "/api/auth/signout") {
          return "/auth/error";
        }
        return baseUrl;
      },
      async jwt({ token, user, account, profile, isNewUser }) {

        // Persist the OAuth access_token to the token right after signin
        if (account) {
          token.accessToken = account.access_token;
          token.idtoken = account.id_token;
          token.refreshToken = account.refresh_token;
        }

        // Return previous token if the access token has not expired yet
        const idtoken = token.idtoken as String;
        if(idtoken != undefined){
            var tokenParsed = JSON.parse(Buffer.from(idtoken.split('.')[1], 'base64').toString());
            const dateNowInSeconds = new Date().getTime() / 1000

            console.log("tokenParsed.exp - "+tokenParsed.exp);
            if (dateNowInSeconds < tokenParsed.exp) {
              return token
            }
            return refreshAccessToken(token)
        }else{
          return token;
        }
      },
      async session({ session, token, user }) {
        session.accessToken = <string> token.accessToken
        return session
      }
    },
    debug: true
})

Inside pages->auth->error.tsx

import Link from "next/link";
import React from 'react';
import { useEffect } from "react";
import { useRouter } from "next/router";

export default function error() {
  const router = useRouter();

  useEffect(() => {
    setTimeout(() => {
      router.push("/");
    }, 5000);
  }, []);

  return (
    <div>
      <h1>403 - Access Forbidden</h1>
      <p>You are not authorized to access this page.</p>
      <p>You will be redirected to the home page in 5 seconds...</p>
      <Link href="/">Go to home page</Link>
    </div>
  );
}

On access denied scenario I want auth/error.tsx page to be displayed but it redirects to http://localhost:3000/api/auth/signin?error=Callback http://localhost:3000/api/auth/signin?error=Callback

On console I get this [next-auth][error][OAUTH_CALLBACK_ERROR] error enter image description here

How to redirect to /auth/error.tsx component on the above error?

Vandana
  • 23
  • 5
  • Does this answer your question? [How to handle login failed error in NextAuth.js?](https://stackoverflow.com/questions/70165993/how-to-handle-login-failed-error-in-nextauth-js) – Youssouf Oumar Mar 16 '23 at 17:40

0 Answers0