Как сохранить статус входа Auth0 в браузере для React SPA - PullRequest
0 голосов
/ 28 февраля 2019

В настоящее время, когда я создаю свои маршруты, я проверяю метод Auth0 - isAuthenticated () - чтобы определить, следует ли возвращать защищенную страницу или перенаправлять для входа в систему.Однако это состояние существует только в памяти и не сохраняет пользователя на его странице после обновления браузера, и я хотел бы сделать это.

Это приложение React / RR4 / React Context, и мои методы Auth0 перечисленыв Auth.js (ниже).

Крайне нежелательно хранить состояние входа в систему в localStorage.И если я сохраню свои токены Auth0 в файлах cookie, я не уверен, как бы я проверил токены, поскольку не настроена проверка сервера.Какое правильное условие, чтобы проверить, будет ли включено безопасное сохранение данных?

ProtectedRoutes.jsx:

   <Route
      exact
      key={route.path}
      path={route.path}
      render={() => (
        // CONDITION TO CHECK
        context.auth.isAuthenticated()
          ? (
            <div>
              <route.component />
            </div>
          ) : <Redirect to="/login" />
        )}
      />

Auth.js (добавлено для справки):

import auth0 from 'auth0-js';
import authConfig from './auth0-variables';

class Auth {
  accessToken;
  idToken;
  expiresAt;
  tokenRenewalTimeout;

  auth0 = new auth0.WebAuth({
    domain: authConfig.domain,
    clientID: authConfig.clientId,
    redirectUri: authConfig.callbackUrl,
    responseType: 'token id_token',
    scope: 'openid'
  });

  constructor() {
    this.scheduleRenewal();
    this.login = this.login.bind(this);
    this.logout = this.logout.bind(this);
    this.handleAuthentication = this.handleAuthentication.bind(this);
    this.isAuthenticated = this.isAuthenticated.bind(this);
    this.getAccessToken = this.getAccessToken.bind(this);
    this.getIdToken = this.getIdToken.bind(this);
    this.renewSession = this.renewSession.bind(this);
    this.scheduleRenewal = this.scheduleRenewal.bind(this);
  }

  login() {
    console.log('logging in!');
    this.auth0.authorize();
  }

  handleAuthentication() {
    return new Promise((resolve, reject) => {
      this.auth0.parseHash((err, authResult) => {
        if (err) return reject(err);
        console.log(authResult);
        if (!authResult || !authResult.idToken) {
          return reject(err);
        }
        this.setSession(authResult);
        resolve();
      });
    });
  }

  getAccessToken() {
    return this.accessToken;
  }

  getIdToken() {
    return this.idToken;
  }

  getExpiration() {
    return new Date(this.expiresAt);
  }

  isAuthenticated() {
    let expiresAt = this.expiresAt;
    return new Date().getTime() < expiresAt;
  }

  setSession(authResult) {
    localStorage.setItem('isLoggedIn', 'true');
    let expiresAt = (authResult.expiresIn * 1000) + new Date().getTime();
    this.accessToken = authResult.accessToken;
    this.idToken = authResult.idToken;
    this.expiresAt = expiresAt;
    this.scheduleRenewal();
  }

  renewSession() {
    this.auth0.checkSession({}, (err, authResult) => {
      if (authResult && authResult.accessToken && authResult.idToken) {
        this.setSession(authResult);
      } else if (err) {
        this.logout();
        console.log(`Could not get a new token. (${err.error}: ${err.error_description})`);
      }
    });
  }

  scheduleRenewal() {
    let expiresAt = this.expiresAt;
    const timeout = expiresAt - Date.now();
    if (timeout > 0) {
      this.tokenRenewalTimeout = setTimeout(() => {
        this.renewSession();
      }, timeout);
    }
  }

  logout() {
    this.accessToken = null;
    this.idToken = null;
    this.expiresAt = 0;
    localStorage.removeItem('isLoggedIn');
    clearTimeout(this.tokenRenewalTimeout);
    console.log('logged out!');
  }
}

export default Auth;

1 Ответ

0 голосов
/ 03 марта 2019

Вы можете использовать Тихая аутентификация , чтобы обновить токены при обновлении браузера.

Специально для вашего приложения SPA SPA

  • установить состояние, скажем tokenRenewedна false в вашем главном компоненте приложения
  • у вас уже есть renewToken метод в вашем auth.js, поэтому вызовите его в componentDidMount методе
componentDidMount() {
   this.auth.renewToken(() => {
      this.setState({tokenRenewed : true});
   })
}
  • обновите renewToken, чтобы принять обратный вызов cb как показано ниже
renewSession(cb) {
    this.auth0.checkSession({}, (err, authResult) => {
      if (authResult && authResult.accessToken && authResult.idToken) {
        this.setSession(authResult);
      } else if (err) {
        this.logout();
        console.log(`Could not get a new token. (${err.error}: ${err.error_description})`);
      }
      if(cb) cb(err, authResult);
    });
  }
  • Убедитесь, что вы не загружаете компонент приложения, если tokenRenewed не равен true, т.е.обновить действительные токены с помощью тихой аутентификации
render() {
    if(!this.state.tokenRenewed) return "loading...";
    return (
      // Your App component
    );
}

Примечания :

  1. Возможно, вы захотите убедиться, что у вас есть правильный Allowed Web Originsустановите в настройках приложения, чтобы это работало
  2. Автоматическая аутентификация имеет некоторые ограничения, так как для нее требуются сторонние файлы cookie, включенные в браузере, и в случае ITP для Safari.Вы должны настроить собственный домен, чтобы избежать этого.Обратитесь к официальным документам auth0, чтобы узнать больше здесь .
  3. Подробнее о том, как безопасно хранить токен здесь
...