如何将 auth0 访问令牌添加到 react-apollo
how to add auth0 access token to react-apollo
我正在尝试在 React js 中向 apollo 客户端添加授权令牌,让用户登录...
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import { ThemeProvider } from 'react-jss';
import Theme from 'resources/theme';
import Routes from 'routes';
import './index.css';
import * as serviceWorker from './serviceWorker';
import { Auth0Provider } from "@auth0/auth0-react";
import 'bootstrap/dist/css/bootstrap.min.css';
import ReactNotification from 'react-notifications-component'
import './components/orders/fonts/NotoSansJP-Regular.otf'
import 'react-notifications-component/dist/theme.css'
import { ApolloProvider , ApolloClient, InMemoryCache } from '@apollo/client';
import { useAuth0 } from "@auth0/auth0-react";
const client = new ApolloClient({
uri: process.env.REACT_APP_API_BACK ,
headers: {
Authorization: `Bearer ${accessToken}` // doesn’t work
},
cache: new InMemoryCache()
});
ReactDOM.render(
<Auth0Provider
domain= {process.env.REACT_APP_AUTH0_DOMAIN }
clientId= {process.env.REACT_APP_AUTH0_CLIENT_ID}
redirectUri={window.location.origin}
audience={process.env.REACT_APP_AUTH0_AUDIENCE}
scope="warehouse"
>
<ApolloProvider client={client}>
<ThemeProvider theme={Theme}>
<Router>
<ReactNotification />
<Routes />
</Router>
</ThemeProvider>,
</ApolloProvider>
</Auth0Provider>,
document.getElementById('root')
);
serviceWorker.unregister();
获取我需要导入的令牌:
import { useAuth0 } from "@auth0/auth0-react";
添加这行:
const { getAccessTokenSilently } = useAuth0();
但这不能在 index.js 中完成,我认为
获取令牌:
const accessToken = await getAccessTokenSilently
这是我在文档和 google 搜索中找到的,但我认为在我的情况下无法完成,大多数教程都展示了如何在个人资料页面中获取用户数据(包括令牌)但这不是我想要的。
我想将它传递给index.js
中的客户端
您需要为
创建专用组件
function useToken() {
const { getAccessTokenSilently } = useAuth0();
const [token, setToken] = useState(null);
useEffect(() => { getAccessTokenSilently().then(setToken) }, [])
return token;
}
function MyApolloProvider({ children }) {
const token = useToken();
// useRef instead of useMemo to make sure client is not re-created randomly
const clientRef = useRef(null);
if (token && !clientRef.current) {
// This code should only be executed once.
clientRef.current = new ApolloClient(/**/)
}
if (!clientRef.current) {
// Now we have to wait until client is initialized with token, so you might want to add some spinner
return null;
}
return <ApolloClient client={clientRef.current} >{children}</ApolloClient>
}
然后你用它来代替原来的 ApolloProvider ReactDOM.render。
如果令牌发生变化,那么事情就会变得有点困难。
https://www.apollographql.com/docs/react/networking/authentication/#header
你还在用类似的方法:
function useToken() { /* should return actual token and update it if changed */ }
function MyApolloProvider({ children }) {
const token = useToken();
const tokenRef = useRef(token);
const clientRef = useRef(null);
tokenRef.current = token; // make sure that tokenRef always has up to date token
if (!clientRef.current) {
// This function is called on each request individually and it takes token from ref
const authLink = setContext((_, { headers }) => {
// similar to documentation example, but you read token from ref
const token = tokenRef.current;
return {
headers: {
...headers,
authorization: `Bearer ${token}`,
}
}
});
clientRef.current = new ApolloClient(
link: authLink.concat(httpLink),
// ...
)
}
}
在index.js
中的用法,无论第一种还是第二种情况:
ReactDOM.render(
<Auth0Provider /* options */>
<MyApolloProvider>
{/* ... */}
</MyApolloProvider>
</Auth0Provider>,
document.getElementById("root")
);
这里的主要内容是 MyApolloProvider
应该在 Auth0Provider
之内才能访问令牌。
这就是我最后做的事情:
import {
ApolloProvider,
ApolloClient,
InMemoryCache,
HttpLink,
} from '@apollo/client';
import { setContext } from '@apollo/link-context';
import { useAuth0 } from '@auth0/auth0-react';
const ApolloProviderWithAuth0 = ({ children }) => {
const { getAccessTokenSilently } = useAuth0();
const httpLink = new HttpLink({
uri: process.env.REACT_APP_GRAPHQL_URI,
});
const authLink = setContext(async (_, { headers, ...rest }) => {
let token;
try {
token = await getAccessTokenSilently();
} catch (error) {
console.log(error);
}
if (!token) return { headers, ...rest };
return {
...rest,
headers: {
...headers,
authorization: `Bearer ${token}`,
},
};
});
const client = React.useRef();
if (!client.current) {
client.current = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache(),
});
}
return (
<ApolloProvider client={client.current}>
{children}
</ApolloProvider>
);
};
export { ApolloProviderWithAuth0 };
然后在您的 App 组件中将其用作 Provider。
我正在尝试在 React js 中向 apollo 客户端添加授权令牌,让用户登录...
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import { ThemeProvider } from 'react-jss';
import Theme from 'resources/theme';
import Routes from 'routes';
import './index.css';
import * as serviceWorker from './serviceWorker';
import { Auth0Provider } from "@auth0/auth0-react";
import 'bootstrap/dist/css/bootstrap.min.css';
import ReactNotification from 'react-notifications-component'
import './components/orders/fonts/NotoSansJP-Regular.otf'
import 'react-notifications-component/dist/theme.css'
import { ApolloProvider , ApolloClient, InMemoryCache } from '@apollo/client';
import { useAuth0 } from "@auth0/auth0-react";
const client = new ApolloClient({
uri: process.env.REACT_APP_API_BACK ,
headers: {
Authorization: `Bearer ${accessToken}` // doesn’t work
},
cache: new InMemoryCache()
});
ReactDOM.render(
<Auth0Provider
domain= {process.env.REACT_APP_AUTH0_DOMAIN }
clientId= {process.env.REACT_APP_AUTH0_CLIENT_ID}
redirectUri={window.location.origin}
audience={process.env.REACT_APP_AUTH0_AUDIENCE}
scope="warehouse"
>
<ApolloProvider client={client}>
<ThemeProvider theme={Theme}>
<Router>
<ReactNotification />
<Routes />
</Router>
</ThemeProvider>,
</ApolloProvider>
</Auth0Provider>,
document.getElementById('root')
);
serviceWorker.unregister();
获取我需要导入的令牌:
import { useAuth0 } from "@auth0/auth0-react";
添加这行:
const { getAccessTokenSilently } = useAuth0();
但这不能在 index.js 中完成,我认为
获取令牌:
const accessToken = await getAccessTokenSilently
这是我在文档和 google 搜索中找到的,但我认为在我的情况下无法完成,大多数教程都展示了如何在个人资料页面中获取用户数据(包括令牌)但这不是我想要的。
我想将它传递给index.js
中的客户端您需要为
创建专用组件function useToken() {
const { getAccessTokenSilently } = useAuth0();
const [token, setToken] = useState(null);
useEffect(() => { getAccessTokenSilently().then(setToken) }, [])
return token;
}
function MyApolloProvider({ children }) {
const token = useToken();
// useRef instead of useMemo to make sure client is not re-created randomly
const clientRef = useRef(null);
if (token && !clientRef.current) {
// This code should only be executed once.
clientRef.current = new ApolloClient(/**/)
}
if (!clientRef.current) {
// Now we have to wait until client is initialized with token, so you might want to add some spinner
return null;
}
return <ApolloClient client={clientRef.current} >{children}</ApolloClient>
}
然后你用它来代替原来的 ApolloProvider ReactDOM.render。
如果令牌发生变化,那么事情就会变得有点困难。 https://www.apollographql.com/docs/react/networking/authentication/#header
你还在用类似的方法:
function useToken() { /* should return actual token and update it if changed */ }
function MyApolloProvider({ children }) {
const token = useToken();
const tokenRef = useRef(token);
const clientRef = useRef(null);
tokenRef.current = token; // make sure that tokenRef always has up to date token
if (!clientRef.current) {
// This function is called on each request individually and it takes token from ref
const authLink = setContext((_, { headers }) => {
// similar to documentation example, but you read token from ref
const token = tokenRef.current;
return {
headers: {
...headers,
authorization: `Bearer ${token}`,
}
}
});
clientRef.current = new ApolloClient(
link: authLink.concat(httpLink),
// ...
)
}
}
在index.js
中的用法,无论第一种还是第二种情况:
ReactDOM.render(
<Auth0Provider /* options */>
<MyApolloProvider>
{/* ... */}
</MyApolloProvider>
</Auth0Provider>,
document.getElementById("root")
);
这里的主要内容是 MyApolloProvider
应该在 Auth0Provider
之内才能访问令牌。
这就是我最后做的事情:
import {
ApolloProvider,
ApolloClient,
InMemoryCache,
HttpLink,
} from '@apollo/client';
import { setContext } from '@apollo/link-context';
import { useAuth0 } from '@auth0/auth0-react';
const ApolloProviderWithAuth0 = ({ children }) => {
const { getAccessTokenSilently } = useAuth0();
const httpLink = new HttpLink({
uri: process.env.REACT_APP_GRAPHQL_URI,
});
const authLink = setContext(async (_, { headers, ...rest }) => {
let token;
try {
token = await getAccessTokenSilently();
} catch (error) {
console.log(error);
}
if (!token) return { headers, ...rest };
return {
...rest,
headers: {
...headers,
authorization: `Bearer ${token}`,
},
};
});
const client = React.useRef();
if (!client.current) {
client.current = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache(),
});
}
return (
<ApolloProvider client={client.current}>
{children}
</ApolloProvider>
);
};
export { ApolloProviderWithAuth0 };
然后在您的 App 组件中将其用作 Provider。