首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >next-auth / urql -访问访问令牌以在urql客户端中设置Authorization标头

next-auth / urql -访问访问令牌以在urql客户端中设置Authorization标头
EN

Stack Overflow用户
提问于 2021-04-06 20:40:25
回答 1查看 423关注 0票数 0

我正在使用next-auth为我的next.js应用程序管理JWT令牌和会话。我还使用urql作为GraphQL客户端。我在一个文件中初始化urql客户端,如下所示:

代码语言:javascript
复制
import { createClient } from 'urql';

const client = createClient({
  url: process.env.NEXT_PUBLIC_API_URL,
  fetchOptions: () => {
    return {
      headers: {}, // I'd like to set Auth header here...
    };
  },
});

export default client;

然后将其添加到_app.tsx,如下所示:

代码语言:javascript
复制
import type { AppProps } from 'next/app';
import { Provider as AuthProvider } from 'next-auth/client';
import { Provider as GraphqlProvider } from 'urql';
import client from '../graphql/client';

function App({ Component, pageProps }: AppProps) {
  const { session } = pageProps;

  return (
    <GraphqlProvider value={client}>
      <AuthProvider session={session}>
        <Component {...pageProps} />
      </AuthProvider>
    </GraphqlProvider>
  );
}

export default App;

在这个阶段没有什么花哨的东西。

现在我的问题是,我希望能够访问访问令牌,以便在客户机中添加Authorization头,但是,因为这部分代码存在于React组件之外,所以我不能使用next-auth提供的useSession挂钩。

有没有人能提出解决这个问题的最佳方法?谢谢。

EN

回答 1

Stack Overflow用户

发布于 2021-04-26 07:22:46

关于如何处理这种情况,我从一个next-auth维护者那里得到了一个非常有用的响应:https://github.com/nextauthjs/next-auth/discussions/1806

重要的是让AuthProvider作为_app.tsx中最父的组件,然后创建一个useClient钩子,将其传递给urql的提供者:

/graphql/client.ts

代码语言:javascript
复制
import { createClient } from '@urql/core';
import { useSession } from 'next-auth/client';
import * as React from 'react';

/**
 * Get GraphQL Client in browser environments (frontend).
 *
 * If the user has an active session, it will add an accessToken to all requests
 */
const useClient = (options?: RequestInit) => {
  const [session] = useSession();
  const token = session?.accessToken;
  // const handleError = useErrorHandler();

  return React.useMemo(() => {
    const client = createClient({
      url: process.env.NEXT_PUBLIC_API_URL,
      fetchOptions: () => {
        return {
          headers: {
            Authorization: token ? `Bearer ${token}` : '',
            ...(options?.headers ? options.headers : {}),
          },
        };
      },
    });

    return client;
  }, [options, token]);
};

export default useClient;

然后创建urql提供程序,传入从useClient钩子获得的客户端:

/graphql/provider.tsx

代码语言:javascript
复制
import React from 'react';
import { Provider } from 'urql';
import useClient from './client';

interface GraphqlProviderProps {}

const GraphqlProvider: React.FC<GraphqlProviderProps> = ({ children }) => {
  const client = useClient();

  return <Provider value={client}>{children}</Provider>;
};

export default GraphqlProvider;

然后在_app.tsx中使用它作为AuthProvider的子级

代码语言:javascript
复制
import { Provider as AuthProvider } from 'next-auth/client';
import type { AppProps } from 'next/app';
import GraphqlProvider from '../graphql/provider';
import '../styles/index.css';

function App({ Component, pageProps }: AppProps) {
  const { session } = pageProps;

  return (
    <AuthProvider session={session}>
      <GraphqlProvider>
        <Component {...pageProps} />
      </GraphqlProvider>
    </AuthProvider>
  );
}

export default App;

最后,您可以暂停所有useQuery请求,直到session初始化:/pages/index.tsx

代码语言:javascript
复制
import { signIn, signOut, useSession } from 'next-auth/client';
import React from 'react';
import { useQuery } from 'urql';

interface HomeProps {}

const Home: React.FC<HomeProps> = ({}) => {
  const [session, loading] = useSession();

  const QUERY = `
  query {
    users {
      id
      name
      email
    }
  }
  `;

  const request = useQuery({ query: QUERY, pause: !session });
  console.log(request);
  
  return (
    <div>
      {!session && (
        <>
          Not signed in <br />
          <button onClick={() => signIn()}>Sign in</button>
        </>
      )}

      {session && (
        <>
          Signed in as {session.user.email} <br />
          <button onClick={() => signOut()}>Sign out</button>
        </>
      )}
    </div>
  );
};

export default Home;

而且它起作用了!您可以在网络请求中看到带有有效jwt令牌的auth标头:-)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66968857

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档