如何在Next.js应用的React组件或普通函数中获取Auth0的idToken
解决Next.js中后端调用携带idToken的问题及props兼容错误
先解决你遇到的props编译错误
你之前的问题是因为在getServerSideProps里返回了idToken,但ExamplePageProps和MyComponentProps都没定义这个字段,导致类型不兼容。按下面步骤修改:
- 更新页面的Props接口
修改src/pages/example/index.page.tsx里的ExamplePageProps,新增idToken字段:
export interface ExamplePageProps { initialTranslations: any; // 替换成你实际的类型定义 idToken?: string; }
- 在getServerSideProps中获取并返回idToken
调用@auth0/nextjs-auth0的getSession拿到token,加入返回的props:
import { getSession } from '@auth0/nextjs-auth0'; export const getServerSideProps: GetServerSideProps<ExamplePageProps> = async (context) => { const initialTranslations = await getTranslations(context.locale, ['example']); const session = await getSession(context.req, context.res); const idToken = session?.user?.idToken; return { props: { initialTranslations, idToken, }, }; };
- 把idToken传给MyComponent并更新组件Props
先给MyComponent的Props加idToken字段:
// src/pages/components/MyComponent/MyComponent.tsx export interface MyComponentProps { // 你的其他props定义 idToken?: string; } export const MyComponent: FC<MyComponentProps> = ({ idToken }) => { const handleClick = async () => { await makeBackendCall(param1, param2, idToken); } // ... 组件其余内容 }
然后在页面中传递这个props:
// src/pages/example/index.page.tsx function ExamplePage(props: ExamplePageProps) { return ( <MyComponent idToken={props.idToken} /> ); }
- 修改后端调用函数接收idToken
更新makeBackendCall,把token加到请求头:
// src/fetchers/webapi.ts export const makeBackendCall = async (param1: string, param2: string, idToken?: string): Promise<Response> => { const headers: HeadersInit = {}; if (idToken) { headers['X-ID-Token'] = idToken; // 改成后端要求的header字段,比如`Authorization: Bearer ${idToken}` } return fetch('http://some.url', { method: 'GET', headers, }); }
更简便的全局方案:自动注入idToken到所有后端调用
上面的方法需要每个组件传token,比较繁琐。推荐用React Context + 封装fetch工具的方式,让所有后端调用自动带上token:
步骤1:创建Auth上下文管理token
// src/contexts/AuthContext.tsx import { createContext, useContext, ReactNode } from 'react'; import { useUser } from '@auth0/nextjs-auth0/client'; interface AuthContextType { idToken?: string; } const AuthContext = createContext<AuthContextType>({}); export const AuthProvider = ({ children }: { children: ReactNode }) => { const { user } = useUser(); return ( <AuthContext.Provider value={{ idToken: user?.idToken }}> {children} </AuthContext.Provider> ); }; export const useAuth = () => useContext(AuthContext);
步骤2:在_app.tsx中挂载上下文
// src/pages/_app.tsx import { AuthProvider as Auth0Provider } from '@auth0/nextjs-auth0'; import { AuthProvider } from '../contexts/AuthContext'; function MyApp({ Component, pageProps }) { return ( <Auth0Provider> <AuthProvider> <Component {...pageProps} /> </AuthProvider> </Auth0Provider> ); } export default MyApp;
步骤3:封装带token的fetch工具
// src/fetchers/webapi.ts import { useAuth } from '../contexts/AuthContext'; // 封装自动带token的fetch函数 const fetchWithToken = async (url: string, options: RequestInit = {}) => { const { idToken } = useAuth(); const headers = { ...options.headers, // 按后端要求设置header,这里示例用X-ID-Token,也可以用Authorization: Bearer ${idToken} ...(idToken && { 'X-ID-Token': idToken }), }; return fetch(url, { ...options, headers, }); }; // 所有后端调用都用这个封装好的函数 export const makeBackendCall = async (param1: string, param2: string): Promise<Response> => { return fetchWithToken(`http://some.url?param1=${param1}¶m2=${param2}`, { method: 'GET', }); }; export const anotherCallWhichNeedsTheToken = async () => { return fetchWithToken('http://some.other.url', { method: 'POST' }); };
这样以后所有后端调用都不用手动传token了,工具函数会自动从上下文里取并加到请求头里,也不用每个组件都处理token传递的问题。
内容的提问来源于stack exchange,提问作者vtomic85
相关产品推荐
相关产品推荐

