Как вытянуть JWT токен из Auth0 в состояние Mobx без применения хуков (React)

Приложение разрабатывается на React + Mobx следуя паттерну Model-View-Controller. Хуки используются, но для утилитарных задач представления: не хотелось бы писать код сомнительного качества, который перебрасывал бы JWT токен из React в Mobx.

import React from "react";
import { useAuth0 } from "@auth0/auth0-react";

const Profile = () => {
  const { user, isAuthenticated, isLoading } = useAuth0();

  if (isLoading) {
    return <div>Loading ...</div>;
  }

  return (
    isAuthenticated && (
      <div>
        <img src={user.picture} alt={user.name} />
        <h2>{user.name}</h2>
        <p>{user.email}</p>
      </div>
    )
  );
};

export default Profile;

Для авторизации официальный пример использует следующий код

import React from "react";
import { useAuth0 } from "@auth0/auth0-react";

const LoginButton = () => {
  const { loginWithRedirect } = useAuth0();

  return <button onClick={() => loginWithRedirect()}>Log In</button>;
};

export default LoginButton;

Подскажите, возможно ли вынести авторизацию в специально выделенный сервис?


Ответы (1 шт):

Автор решения: Трипольский Пётр

В итоге я решил вопрос следующим способом

На момент написания документация оставляла желать лучшего

import createAuth0Client, { Auth0Client } from '@auth0/auth0-spa-js';

...

const createClient = () => createAuth0Client({
  domain: AUTH0_DOMAIN,
  client_id: AUTH0_ID,
  redirect_uri: window.location.origin,
});

...

export class AuthService {

  constructor(
    public sessionService: SessionService,
    public alertService: AlertService,
    public userService: UserService,
  ) {
    makeObservable(this, {
      sessionService: observable,
      alertService: observable,
      userService: observable,
      authPopup: action.bound,
      authRedirect: action.bound,
      _handleNewToken: action.bound,
      init: action.bound,
    });
    this.init();
  }

  async _handleNewToken(auth0: Auth0Client) {
    const {
      _raw: jwt,
      nickname,
      picture,
      email,
    } = await auth0.getIdTokenClaims();
    nickname && this.userService.setNickname(nickname);
    picture && this.userService.setPicture(picture);
    email && this.userService.setEmail(email);
    this.sessionService.setSessionId(jwt);
    //                               ^^^
  }

  async authPopup() {
    let token: string | false = false;
    try {
      const auth0 = await createClient();
      await auth0.loginWithPopup();
      await this._handleNewToken(auth0);
      this.alertService.push('Signed in successfully');
    } catch (e) {
      console.log(e);
      this.alertService.push('Authorization failed');
    } finally {
      return token;
    }
  }

  async authRedirect() {
    try {
      const auth0 = await createClient();
      await auth0.loginWithRedirect();
      await sleep(5_000);
    } catch(e) {
      console.log(e);
      this.alertService.push('Authorization failed');
    }
  }

  async init() {
    try {
      const auth0 = await createClient();
      await auth0.handleRedirectCallback();
      await this._handleNewToken(auth0);
      this.alertService.push('Signed in successfully');
    } catch (e) {
      console.log(e);
    }
  }

};

...

const handleButtonClick = () => {
        await authService.authRedirect();
        ...
};

→ Ссылка