我开发了一个使用Netlify CMS创建博客的Gatsby应用程序。现在,我想添加一个使用Okta进行身份验证的“帐户”部分。我观看了Add authentication to your apps with Okta并尝试在那里实现逻辑。我可以使用它,但是当需要身份验证时,我很难渲染Sign-In Widget。
我遇到的问题是,当我点击/ account端点时,Okta的登录小部件无法显示。这是帐户页面:
import React from 'react'
import { Router } from '@reach/router'
import { Link } from 'gatsby'
const Home = () => <p>Home</p>;
const Settings = () => <p>Settings</p>;
const isAuthenticated = () => {
if (typeof window !== 'undefined') {
return localStorage.getItem('isAuthenticated') === 'true';
} else {
return false;
}
};
const Account = () => {
if (!isAuthenticated()) {
return (
<>
<p>Please sign in to continue...</p>
<div id="signIn"/>
</>
);
}
return (
<>
<nav>
<Link to="/">Home</Link>{' '}
<Link to="/account">My Account</Link>{' '}
<Link to="/account/settings">Settings</Link>{' '}
</nav>
<h1>My Account</h1>
<Router>
<Home path="/account"/>
<Settings path="/account/settings"/>
</Router>
</>
)
};
export default Account
[您可以看到当用户未登录时会显示<div id="signIn"/>
。在gatsby-browser.js
中,我具有呈现登录小部件并在用户登录时显示用户信息的逻辑。
import OktaSignIn from '@okta/okta-signin-widget';
import '@okta/okta-signin-widget/dist/css/okta-sign-in.min.css';
import React from 'react';
import { navigate } from '@reach/router';
const config = {
baseUrl: 'https://dev-133320.okta.com',
logo: '//logo.clearbit.com/gatsbyjs.org',
redirectUri: window.location.origin + '/account',
clientId: '0oa2apgdomrOSH74w357',
el: '#signIn',
authParams: {
pkce: true,
responseType: ['token', 'id_token'],
}
};
class AuthWrapper extends React.Component {
constructor(props) {
super(props);
this.state = {
user: false
};
this.signIn = new OktaSignIn(config);
this.logout = this.logout.bind(this);
}
async componentDidMount() {
const authClient = this.signIn.authClient;
const session = await authClient.session.get();
console.log('session.status', session.status);
// Session exists, show logged in state.
if (session.status === 'ACTIVE') {
// clear parameters from browser window
window.location.hash = '';
// set username in state
this.setState({user: session.login});
localStorage.setItem('isAuthenticated', 'true');
// get access and ID tokens
authClient.token.getWithoutPrompt({
scopes: ['openid', 'email', 'profile'],
}).then((tokens) => {
tokens.forEach(token => {
if (token.idToken) {
authClient.tokenManager.add('idToken', token);
}
if (token.accessToken) {
authClient.tokenManager.add('accessToken', token);
}
});
// Say hello to the person who just signed in
authClient.tokenManager.get('idToken').then(idToken => {
console.log(`Hello, ${idToken.claims.name} (${idToken.claims.email})`);
});
}).catch(error => console.error(error));
return;
}
// todo: figure out why it won't display after logout
this.signIn.renderEl({el: '#signIn'})
}
logout = () => {
this.signIn.authClient.signOut().then((error) => {
if (error) {
console.error(error);
return;
}
localStorage.setItem('isAuthenticated', 'false');
this.setState({user: false});
navigate('/');
})
};
render() {
return (
<React.Fragment>
{this.state.user ? (
<React.Fragment>
<p>Welcome, {this.state.user}. <button onClick={this.logout}>Logout</button></p>
</React.Fragment>
) : null}
{this.props.children}
</React.Fragment>
)
}
}
export const wrapRootElement = ({element}) => (
<AuthWrapper>{element}</AuthWrapper>
);
我发现,唯一有效的方法是直接点击http://localhost:8000/account,或者到达目的地后刷新。我相信这是因为在<div id="signIn"/>
中执行componentDidMount()
时gatsby-browser.js
不存在。
我尝试将wrapRootElement
中的wrapPageElement
更改为gatsby-browser.js
。根据我与之交谈的Gatsby专家的说法,当路线更改时,此[[does重新安装。我尝试将一些日志记录添加到componentDidMount()
,但导航更改时似乎不会触发。我相信,如果这样做的话,可以解决我的问题。