Dozens of authentication calls made per page load
Unanswered
Tonkinese posted this in #help-forum
TonkineseOP
is this a normal terminal log on a single page request?
[auth][warn][debug-enabled] Read
[provider][apollo][provider]
GET /products/123 200 in 551ms
GET /api/auth/session 200 in 36ms
GET /api/auth/session 200 in 10ms
GET /api/auth/session 200 in 14ms
GET /api/auth/session 200 in 8ms
GET /api/auth/session 200 in 8ms
GET /api/auth/session 200 in 15ms
GET /api/auth/session 200 in 8ms
GET /api/auth/session 200 in 9ms
GET /api/auth/session 200 in 15ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 6ms
GET /api/auth/session 200 in 8ms
GET /api/auth/session 200 in 12ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 13ms
GET /api/auth/session 200 in 6ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 15ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 6ms
GET /api/auth/session 200 in 13ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 14ms
GET /api/auth/session 200 in 8ms
GET /api/auth/session 200 in 14ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 17ms
GET /api/auth/session 200 in 8ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 14ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 6ms
GET /api/auth/session 200 in 15ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 15ms
GET /api/auth/session 200 in 7ms
GET /api/auth/session 200 in 9ms
GET /api/auth/session 200 in 14ms21 Replies
Great golden digger wasp
this is wired
and it is not a single requst
these are dozens of requests
@Great golden digger wasp these are dozens of requests
TonkineseOP
sorry i meant to say only a single page request (i.e. refreshing the page on localhost:3000)
@Cimarrón Uruguayo useEffect gone crazy?
TonkineseOP
hmm could be, don't think so though
TonkineseOP
i'm guessing it's caused by auth.js, just not sure how exactly
terminal is showing this warning log:
⚠ ./src/auth.ts
Attempted import error: 'Issuer' is not exported from 'openid-client' (imported as 'Issuer').maybe related?
Great golden digger wasp
Can you share the folder structure and the code
@Great golden digger wasp Can you share the folder structure and the code
TonkineseOP
yeah sure, so first this is what the app structure looks like:
/src/app
└── auth
├── [...nextauth]
│ └── route.ts
└── callback
└── credentials
└── route.tsauth.ts:
import NextAuth from "next-auth";
import "next-auth/jwt";
import { JWT } from "next-auth/jwt";
import Credentials from "next-auth/providers/credentials";
import NextAuthOptions from "next-auth";
import { Issuer } from "openid-client";
import authConfig from "./auth.config";
async function refreshAccessToken(token: JWT): Promise<JWT> {
try {
const issuer = await Issuer.discover(process.env.ZITADEL_ISSUER ?? "");
const client = new issuer.Client({
client_id: process.env.ZITADEL_CLIENT_ID || "",
token_endpoint_auth_method: "none",
});
const { refresh_token, access_token, expires_at } = await client.refresh(
token.refreshToken as string
);
return {
...token,
accessToken: access_token,
expiresAt: (expires_at ?? 0) * 1000,
refreshToken: refresh_token,
};
} catch (error) {
console.error(error);
return {
...token,
error: "RefreshAccessTokenError",
};
}
}
const config = {
...authConfig,
session: {
strategy: "jwt",
},
callbacks: {
async jwt({ token, user, account }) {
token.user ??= user;
token.accessToken ??= account?.access_token;
token.refreshToken ??= account?.refresh_token;
token.expiresAt ??= (account?.expires_at ?? 0) * 1000;
token.error = undefined;
if (Date.now() < (token.expiresAt as number)) {
return token;
}
return refreshAccessToken(token);
},
async session({ session, token: { user, error: tokenError } }) {
session.user = {
id: user?.id,
email: user?.email,
image: user?.image,
name: user?.name,
loginName: user?.loginName,
};
session.clientId = process.env.ZITADEL_CLIENT_ID;
session.error = tokenError;
return session;
},
},
experimental: {
enableWebAuthn: true,
},
debug: process.env.NODE_ENV !== "production" ? true : false,
} satisfies typeof NextAuthOptions;continued:
export const { handlers, auth, signIn, signOut } = NextAuth(config);
export async function handler(request: NextRequest) {
const session = await auth();
return await fetch("http://localhost:8080/query", {
headers: { Authorization: `Bearer ${session?.accessToken}` },
});
}
declare module "next-auth" {
interface Session {
accessToken?: string;
}
}
declare module "next-auth/jwt" {
interface JWT {
accessToken?: string;
}
}and auth.config.ts:
import NextAuth, { NextAuthOptions } from "next-auth";
import Zitadel from "next-auth/providers/zitadel";
import { ZodError } from "zod";
import axios from "axios";
import { signInSchema } from "@/lib/zod";
const saltAndHashPassword = async (pw) => pw;
const getUserFromDb = async (email, pwHash) => ({
id: 1,
});
export default {
providers: [
Zitadel({
issuer: process.env.ZITADEL_ISSUER,
clientId: process.env.ZITADEL_CLIENT_ID,
clientSecret: process.env.ZITADEL_CLIENT_SECRET,
checks: ["pkce"],
authorization: {
params: {
scope: `openid email profile urn:zitadel:iam:org:project:id:zitadel:aud`,
},
},
async profile(profile) {
return {
id: profile.sub,
name: profile.name,
firstName: profile.given_name,
lastName: profile.family_name,
email: profile.email,
loginName: profile.preferred_username,
image: profile.picture,
};
},
}),
],
} satisfies NextAuthOptions;and then my base layout has a
import { SessionProvider } from "next-auth/react"; provider that wraps { children }that should be all the relevant code
TonkineseOP
does that auth.js configuration look ok?
TonkineseOP
maybe it's
refreshAccessToken being called multiple times for some reasonTonkineseOP
ok I think the issue is that
Issuer is undefined: import { Issuer } from 'openid-client';
async function refreshAccessToken(token: JWT): Promise<JWT> {
try {
const issuer = await Issuer.discover(process.env.ZITADEL_ISSUER ?? '');
const client = new issuer.Client({
client_id: process.env.ZITADEL_CLIENT_ID || '',
token_endpoint_auth_method: 'none',
});
const { refresh_token, access_token, expires_at } = await client.refresh(token.refreshToken as string);
return {
...token,
accessToken: access_token,
expiresAt: (expires_at ?? 0) * 1000,
refreshToken: refresh_token, // Fall back to old refresh token
};
} catch (error) {
console.error('Error during refreshAccessToken', error);
return {
...token,
error: 'RefreshAccessTokenError',
};
}
}maybe the package api changed?
TonkineseOP
yeah i'm guessing this is the issue