react-oidc-контекст перенаправляет на исходный маршрут после успешного входа с auth0

#reactjs #react-router #openid-connect #react-oidc

#reactjs #react-маршрутизатор #OpenID-connect #react-oidc

Вопрос:

Привет, я пытаюсь использовать react-oidc-context для аутентификации с помощью auth0, и у меня есть одна проблема. После успешной аутентификации с помощью auth0 я всегда перенаправляюсь обратно на маршрут, на котором я был, когда нажал кнопку входа. В приложении есть 2 незащищенных маршрута / login и / public, и я могу быть на любом из них, когда нажимаю login в заголовке страницы. Я всегда перенаправляюсь на любую из этих страниц, на которых я был изначально. Кнопка login вызывает login из перехвата useReactOidc. Я хочу быть перенаправленным на маршрут /home и попытался выполнить history.push(‘/home’) перед вызовом login(), но безуспешно.

В случае страницы входа в систему я мог бы включить логику для перенаправления на /home, если мы вошли в систему, поскольку нам не нужно там быть, но в случае /public у вас может быть причина находиться на странице, если вы вошли в систему или нет.

Я не совсем понимаю, как redirect_uri в конфигурации вписывается в это, я пытался настроить маршрут для этого, но он никогда не совпадает ( Если у кого-нибудь есть какие-либо предложения о том, как перенаправить на определенный маршрут после успешного входа в систему, это было бы с благодарностью, надеюсь, я только что пропустил что-то очевидное. Спасибо, и вот код:

configuration.js

 const tenancy = 'https://dev-xxxxxxxxxxxxxx.eu.auth0.com';
const clientId = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

export const configuration = {
  client_name: 'My App',
  client_id: clientId,
  scope: 'openid profile',
  response_type: 'code',
  authority: `${tenancy}`,
  redirect_uri: 'http://localhost:3000/authentication/callback',
  // post_logout_redirect_uri: 'http://localhost:3000', // Auth0 uses returnTo
  silent_redirect_uri: 'http://localhost:3000/authentication/silent_callback',
  automaticSilentRenew: true,
  loadUserInfo: true,
  metadata: {
    issuer: `${tenancy}/`,
    authorization_endpoint: `${tenancy}/authorize`,
    token_endpoint: `${tenancy}/oauth/token`,
    userinfo_endpoint: `${tenancy}/userinfo`,
    end_session_endpoint: `${tenancy}/v2/logout?returnTo=${encodeURIComponent('http://localhost:3000')}amp;client_id=${clientId}`
  }
};
  

index.js

 import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { AuthenticationProvider, oidcLog, InMemoryWebStorage } from '@axa-fr/react-oidc-context';
import { configuration } from './configuration';

ReactDOM.render(
  <React.StrictMode>
    <AuthenticationProvider
      configuration={configuration}
      loggerLevel={oidcLog.DEBUG}
      isEnabled={true}
      callbackComponentOverride={() => (<></>)}
      UserStore={InMemoryWebStorage}>
      <App />
    </AuthenticationProvider>
  </React.StrictMode>,
  document.getElementById('root')
);
  

App.js

 import React from 'react';
import { useReactOidc } from '@axa-fr/react-oidc-context';
import { BrowserRouter as Router, Link, Redirect, Route, Switch } from 'react-router-dom';
import SecuredRoute from './SecuredRoute';
import { PageHeader, Space } from 'antd';

import './App.css';

const Login = () => <h3>Login Page - use the Login button top right</h3>;
const Home = () => <h3>Home Page</h3>;
const Public = () => <h3>Public Page</h3>;

const Header = () => {
  const { oidcUser, login, logout } = useReactOidc();

  return (
    <PageHeader style={{ textAlign: "right", margin: "8px" }}>
      { oidcUser ? (
        <button onClick={logout}>Log Out</button>
      ) : (
          <button onClick={login}>Log in</button>
        )}
    </PageHeader>
  );
};

const DefaultPage = () => {
  const { oidcUser } = useReactOidc();

  return (
    oidcUser ? (
      <Redirect to="/home" />
      ) : (
      <Redirect to="/login" />
    )
  );
};

const App = () => {
  return (
    <div className="App">
      <Router>
        <Header />
        <Switch>
          <Route path='/' exact component={DefaultPage} />
          <Route path='/login' component={Login} />
          <Route path='/public' component={Public} />
          <SecuredRoute path='/home' component={Home} />
          <SecuredRoute path='/authentication/callback' component={Home} />
        </Switch>
        <Space>
          <Link to="/home">Home Page (you must be logged in to access this)</Link>
          <br/>
          <Link to="/public">Public Page (you don't need to be logged in to access this)</Link>
        </Space>
      </Router>
    </div>
  );
};

export default App;
  

SecuredRoute.js

 import React from 'react';
import { Redirect, Route } from 'react-router-dom';
import { useReactOidc } from '@axa-fr/react-oidc-context';

const SecuredRoute = ({ component: Component, ...rest }) => {
  const { oidcUser } = useReactOidc();
  
  return (
    <Route {...rest} render={(props) => (
      oidcUser
        ? <Component {...props} />
        : <Redirect to={{ pathname: '/', state: { from: props.location }}} />
    )} />
  );
};
  

экспорт защищенного маршрута по умолчанию;

Версии

 "dependencies": {
"@axa-fr/react-oidc-context": "^3.1.6",
"@axa-fr/react-oidc-context-fetch": "^3.1.6",
"@testing-library/jest-dom": "^5.11.5",
"@testing-library/react": "^11.1.1",
"@testing-library/user-event": "^12.2.0",
"antd": "^4.8.0",
"oidc-client": "^1.10.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.0",
"web-vitals": "^0.2.4"
},
  

Ответ №1:

Я не могу вам помочь с react-oidc-context, так что это может быть только частичным ответом. Мне кажется, что вам нужен некоторый контроль над следующими областями:

ТРЕБОВАНИЕ 1: КОНТРОЛЬ ПЕРЕД ПЕРЕНАПРАВЛЕНИЕМ

Возможность делать такие вещи, как сохранение состояния и местоположения пользователя в хранилище HTML5 перед перенаправлением.

ТРЕБОВАНИЕ 2: УПРАВЛЕНИЕ ПОСЛЕ ОБРАБОТКИ ОТВЕТА НА ВХОД

Возможность при необходимости восстановить состояние из хранилища, а затем управлять местоположением после входа в систему.

ТРЕБОВАНИЕ 3: КОНТРОЛЬ ИСТЕЧЕНИЯ СРОКА ДЕЙСТВИЯ

Если пользователь оставляет свой браузер включенным на ночь, а токены истекли, пользовательскому интерфейсу может потребоваться вызвать перенаправление входа в систему в результате неудачного вызова API.

КЛИЕНТ OIDC

Эта библиотека полностью поддерживает описанное выше поведение. Если вы не можете получить тот же элемент управления с помощью react-oidc-context, то одним из решений, которое будет работать, является прямое использование библиотеки — это может быть на один уровень меньше для управления.

ПРИМЕР КОДА

Я бы хотел иметь пару функций, как в этом моем коде, которые дают вам необходимый контроль до и после входа в систему.

КОД РЕАКЦИИ

Мое личное предпочтение — использовать React только для представлений и простых классов для вызовов API и Open Id Connect. Здесь также приведен мой пример, который следует этому подходу, хотя этот пример немного сложнее.

Комментарии:

1. Извините за поздний ответ и спасибо за ссылку на ваш код. react-oidc-context использует oidc-client под капотом, поэтому похоже, что прямое использование базового пакета обеспечит необходимый уровень контроля, спасибо за вашу помощь.