如何获取 AccessToken
How to fetch AccessToken
我在 React 中使用以下插件 (@axa-fr/react-oidc-context) 以启用 AzureAd 身份验证。现在我需要在身份验证完成后访问 ApolloClient 中的 access_token。我不确定如何在像 ApolloClient 这样的非反应组件中获取 access_token。
这就是我正在做的事情。
App.js
import React from "react";
import { HashRouter, Route, Switch } from "react-router-dom";
import { AuthenticationProvider, withOidcSecure } from "@axa-fr/react-oidc-context";
import { IDENTITY_CONFIG } from "./utils/configuration";
// components
import Layout from "./Layout";
export default function App() {
return (
<AuthenticationProvider configuration={IDENTITY_CONFIG}>
<HashRouter>
<Switch>
<Route path="/" component={withOidcSecure(Layout)} />
</Switch>
</HashRouter>
</AuthenticationProvider>
);
}
Layout.js
import React from "react";
import { Route, Switch, withRouter } from "react-router-dom";
import { ApolloProvider } from "@apollo/react-hooks";
import client from "./apollo";
import Dashboard from "./pages/dashboard";
function Layout(props) {
return (
<>
<ApolloProvider client={client}>
<Switch>
<Route exact path="/" component={Dashboard} />
</Switch>
</ApolloProvider>
</>
);
}
export default withRouter(Layout);
apollo.js
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloClient } from "apollo-client";
import { ApolloLink, split } from "apollo-link";
import { setContext } from "apollo-link-context";
import { HttpLink } from "apollo-link-http";
import { WebSocketLink } from "apollo-link-ws";
import { getMainDefinition } from "apollo-utilities";
import { useReactOidc } from "@axa-fr/react-oidc-context";
const { oidcUser } = useReactOidc();
console.log(oidcUser.access_token)
const httpUri = process.env.REACT_APP_SERVER_URL
? process.env.REACT_APP_SERVER_URL
: "https://48p1r2roz4.sse.codesandbox.io";
const wsUri = httpUri.replace(
/^https?/,
process.env.REACT_APP_ENV === "dev" ? "ws" : "wss"
);
const httpLink = new HttpLink({
uri: httpUri
});
const wsLink = new WebSocketLink({
uri: wsUri,
options: {
lazy: true,
reconnect: true
// connectionParams: () => {
// return { headers: { Authorization: getAuthHeader() } };
// }
}
});
const authLink = setContext((_, { headers }) => {
// const auth = getAuthHeader()
return {
headers: {
...headers
// Authorization: auth,
}
};
});
const terminatingLink = split(
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === "OperationDefinition" && operation === "subscription";
},
wsLink,
authLink.concat(httpLink)
);
const link = ApolloLink.from([terminatingLink]);
const cache = new InMemoryCache();
const client = new ApolloClient({
link,
cache
});
export default client;
我试图在 apollo.js 文件中提取访问令牌,但它抛出错误,提示我无法访问非 React 组件中的 React Hooks。
以前从未使用过这个库,但看起来它正在使用 higher order component 将 props 传递给您要传递给 withOidcSecure
的包装组件。您应该能够访问通过 Layout
组件中的 props
提供的任何数据。尝试在其中使用 console.log(props)
并查看它 returns,我不确定到底传递了什么数据。
由于令牌信息在身份验证后存储在 session 存储中,我能够从 session 存储中提取 access_token 信息并分配为授权 Header 到我的 ApolloClient.
如果有更好的解决方案请告诉我。
更新:
我们可以使用 useReactOidc 获取 access_token 作为传递给 Apollo Client 的道具,而不是获取 session 存储的令牌。请查看更新后的代码。
Layout.js
import React from "react";
import { Route, Switch, withRouter } from "react-router-dom";
import { ApolloProvider } from "@apollo/react-hooks";
import { useReactOidc } from "@axa-fr/react-oidc-context";
import client from "./apollo";
import Dashboard from "./pages/dashboard";
function Layout(props) {
const { oidcUser } = useReactOidc();
return (
<>
<ApolloProvider client={client(oidcUser.access_token)}>
<Switch>
<Route exact path="/" component={Dashboard} />
</Switch>
</ApolloProvider>
</>
);
}
export default withRouter(Layout);
apollo.js
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloClient } from "apollo-client";
import { ApolloLink, split } from "apollo-link";
import { setContext } from "apollo-link-context";
import { HttpLink } from "apollo-link-http";
import { WebSocketLink } from "apollo-link-ws";
import { getMainDefinition } from "apollo-utilities";
const httpUri = process.env.REACT_APP_SERVER_URL
? process.env.REACT_APP_SERVER_URL
: "http://localhost:8080/v1/graphql";
const wsUri = httpUri.replace(
/^https?/,
process.env.REACT_APP_ENV === "dev" ? "ws" : "wss"
);
const httpLink = new HttpLink({
uri: httpUri
});
const wsLink = token =>
new WebSocketLink({
uri: wsUri,
options: {
lazy: true,
reconnect: true,
connectionParams: () => {
return { headers: { Authorization: `Bearer ${token}` } };
}
}
});
const authLink = token =>
setContext((_, { headers }) => {
return {
headers: {
...headers,
Authorization: `Bearer ${token}`
}
};
});
const terminatingLink = token =>
split(
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === "OperationDefinition" && operation === "subscription";
},
wsLink(token),
authLink(token).concat(httpLink)
);
const link = token => ApolloLink.from([terminatingLink(token)]);
const cache = new InMemoryCache();
const client = token =>
new ApolloClient({
link: link(token),
cache: cache
});
export default client;
我在 React 中使用以下插件 (@axa-fr/react-oidc-context) 以启用 AzureAd 身份验证。现在我需要在身份验证完成后访问 ApolloClient 中的 access_token。我不确定如何在像 ApolloClient 这样的非反应组件中获取 access_token。
这就是我正在做的事情。
App.js
import React from "react";
import { HashRouter, Route, Switch } from "react-router-dom";
import { AuthenticationProvider, withOidcSecure } from "@axa-fr/react-oidc-context";
import { IDENTITY_CONFIG } from "./utils/configuration";
// components
import Layout from "./Layout";
export default function App() {
return (
<AuthenticationProvider configuration={IDENTITY_CONFIG}>
<HashRouter>
<Switch>
<Route path="/" component={withOidcSecure(Layout)} />
</Switch>
</HashRouter>
</AuthenticationProvider>
);
}
Layout.js
import React from "react";
import { Route, Switch, withRouter } from "react-router-dom";
import { ApolloProvider } from "@apollo/react-hooks";
import client from "./apollo";
import Dashboard from "./pages/dashboard";
function Layout(props) {
return (
<>
<ApolloProvider client={client}>
<Switch>
<Route exact path="/" component={Dashboard} />
</Switch>
</ApolloProvider>
</>
);
}
export default withRouter(Layout);
apollo.js
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloClient } from "apollo-client";
import { ApolloLink, split } from "apollo-link";
import { setContext } from "apollo-link-context";
import { HttpLink } from "apollo-link-http";
import { WebSocketLink } from "apollo-link-ws";
import { getMainDefinition } from "apollo-utilities";
import { useReactOidc } from "@axa-fr/react-oidc-context";
const { oidcUser } = useReactOidc();
console.log(oidcUser.access_token)
const httpUri = process.env.REACT_APP_SERVER_URL
? process.env.REACT_APP_SERVER_URL
: "https://48p1r2roz4.sse.codesandbox.io";
const wsUri = httpUri.replace(
/^https?/,
process.env.REACT_APP_ENV === "dev" ? "ws" : "wss"
);
const httpLink = new HttpLink({
uri: httpUri
});
const wsLink = new WebSocketLink({
uri: wsUri,
options: {
lazy: true,
reconnect: true
// connectionParams: () => {
// return { headers: { Authorization: getAuthHeader() } };
// }
}
});
const authLink = setContext((_, { headers }) => {
// const auth = getAuthHeader()
return {
headers: {
...headers
// Authorization: auth,
}
};
});
const terminatingLink = split(
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === "OperationDefinition" && operation === "subscription";
},
wsLink,
authLink.concat(httpLink)
);
const link = ApolloLink.from([terminatingLink]);
const cache = new InMemoryCache();
const client = new ApolloClient({
link,
cache
});
export default client;
我试图在 apollo.js 文件中提取访问令牌,但它抛出错误,提示我无法访问非 React 组件中的 React Hooks。
以前从未使用过这个库,但看起来它正在使用 higher order component 将 props 传递给您要传递给 withOidcSecure
的包装组件。您应该能够访问通过 Layout
组件中的 props
提供的任何数据。尝试在其中使用 console.log(props)
并查看它 returns,我不确定到底传递了什么数据。
由于令牌信息在身份验证后存储在 session 存储中,我能够从 session 存储中提取 access_token 信息并分配为授权 Header 到我的 ApolloClient.
如果有更好的解决方案请告诉我。
更新:
我们可以使用 useReactOidc 获取 access_token 作为传递给 Apollo Client 的道具,而不是获取 session 存储的令牌。请查看更新后的代码。
Layout.js
import React from "react";
import { Route, Switch, withRouter } from "react-router-dom";
import { ApolloProvider } from "@apollo/react-hooks";
import { useReactOidc } from "@axa-fr/react-oidc-context";
import client from "./apollo";
import Dashboard from "./pages/dashboard";
function Layout(props) {
const { oidcUser } = useReactOidc();
return (
<>
<ApolloProvider client={client(oidcUser.access_token)}>
<Switch>
<Route exact path="/" component={Dashboard} />
</Switch>
</ApolloProvider>
</>
);
}
export default withRouter(Layout);
apollo.js
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloClient } from "apollo-client";
import { ApolloLink, split } from "apollo-link";
import { setContext } from "apollo-link-context";
import { HttpLink } from "apollo-link-http";
import { WebSocketLink } from "apollo-link-ws";
import { getMainDefinition } from "apollo-utilities";
const httpUri = process.env.REACT_APP_SERVER_URL
? process.env.REACT_APP_SERVER_URL
: "http://localhost:8080/v1/graphql";
const wsUri = httpUri.replace(
/^https?/,
process.env.REACT_APP_ENV === "dev" ? "ws" : "wss"
);
const httpLink = new HttpLink({
uri: httpUri
});
const wsLink = token =>
new WebSocketLink({
uri: wsUri,
options: {
lazy: true,
reconnect: true,
connectionParams: () => {
return { headers: { Authorization: `Bearer ${token}` } };
}
}
});
const authLink = token =>
setContext((_, { headers }) => {
return {
headers: {
...headers,
Authorization: `Bearer ${token}`
}
};
});
const terminatingLink = token =>
split(
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === "OperationDefinition" && operation === "subscription";
},
wsLink(token),
authLink(token).concat(httpLink)
);
const link = token => ApolloLink.from([terminatingLink(token)]);
const cache = new InMemoryCache();
const client = token =>
new ApolloClient({
link: link(token),
cache: cache
});
export default client;