Я создал простое приложение React
с Redux
, React Router
и Auth0
, которое обрабатывает аутентификации пользователей.
Я пытаюсь создать это базовое c поведение для контроля доступа:
- Все неаутентифицированные пользователи будут автоматически отправлены на
/public
- Аутентифицированные пользователи может получить доступ ко всем другим частям приложения
- Как только пользователь аутентифицируется с помощью
Auth0
, я хочу обработать access_token
и отправить пользователя на /
, который является Home
компонентом
Все "почти" работает так, как должно. У меня проблема в том, что функция render()
в App.jsx
выполняется ДО того, как у lock.on('authenticated')
слушателя даже есть шанс обработать токены, возвращаемые Auth0
. В результате токены никогда не сохраняются, и пользователь всегда кажется не прошедшим аутентификацию. Если я отправляю пользователя на /login
, все работает нормально, потому что я не проверяю, прошел ли аутентификация пользователя перед рендерингом компонента Login
.
Я думаю, что для работы с защищенными маршрутами нужны изменить. Любые предложения о том, как обрабатывать защищенные маршруты?
Я предоставляю код, который вам нужен здесь. Если вы хотите увидеть все приложение, от go до https://github.com/imsam67/react-redux-react-router-auth0-lock
Ниже приводится App.jsx
:
class App extends Component {
render() {
const isAuthed = isAuthenticated();
return (
<div>
<Switch>
<Route exact path="/" render={ props => isAuthed ? <Home {...props} /> : <Redirect to="/public" /> } />
<Route exact path="/login">
<Login />
</Route>
<Route path="/public">
<Public />
</Route>
</Switch>
</div>
);
}
}
Это AuthWrapper
компонент, где я обрабатываю Auth0
:
class AuthWrapper extends Component {
constructor(props) {
super(props);
this.onAuthenticated = this.onAuthenticated.bind(this);
this.lock = new Auth0Lock('my_auth0_client_id', 'my_domain.auth0.com', {
auth: {
audience: 'https://my_backend_api_url',
redirectUrl: 'http://localhost:3000/',
responseType: 'token id_token',
sso: false
}
});
this.onAuthenticated();
}
onAuthenticated() {
debugger; // After successful login, I hit this debugger
this.lock.on('authenticated', (authResult) => {
debugger; // But I never hit this debugger
let expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
sessionStorage.setItem('access_token', authResult.accessToken);
sessionStorage.setItem('id_token', authResult.idToken);
sessionStorage.setItem('expires_at', expiresAt);
});
}
render() {
return(
<AuthContext.Provider value={{ lock: this.lock }}>
{this.props.children}
</AuthContext.Provider>
);
}
}
А вот index.js
на тот случай, если вам нужно его увидеть:
import App from './components/App';
import AuthWrapper from './components/auth/AuthWrapper';
// Store
import appStore from './store/app-store';
const store = appStore();
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<AuthWrapper>
<App />
</AuthWrapper>
</BrowserRouter>
</Provider>,
document.getElementById('root')
);