Аутентификация с помощью oidc-client.js и Identityserver4 в интерфейсе React

В последнее время я пытаюсь настроить аутентификацию с использованием IdentityServer4 с клиентом React. Я следовал учебнику Adding a JavaScript client (частично) документации IdentityServer: https://media.readthedocs.org/pdf/identityserver4/release/identityserver4.pdf также использовал файл Quickstart7_JavaScriptClient.

Недостатком является то, что я использую React в качестве внешнего интерфейса, и мои знания React не достаточно хороши для реализации той же функциональности, которая использовалась в руководстве с использованием React.

Тем не менее, я начинаю читать и все равно пытаюсь начать. Мой проект IdentityServer и API настроены и, кажется, работают правильно (также протестировано с другими клиентами).

Я начал с добавления oidc-client.js в мой проект Visual Code. Затем я создал страницу, которая визуализируется с самого начала (она называется Authentication.js), и это место, где включены кнопки входа в систему, API вызова и выхода из системы. Эта страница (Authentication.js) выглядит следующим образом:

import React, { Component } from 'react';
import {login, logout, api, log} from '../../testoidc'
import {Route, Link} from 'react-router';

export default class Authentication extends Component {
    constructor(props) {
      super(props);
    }

    render() {
      return (
        <div>
            <div>  
                <button id="login" onClick={() => {login()}}>Login</button>
                <button id="api" onClick={() => {api()}}>Call API</button>
                <button id="logout" onClick={() => {logout()}}>Logout</button>

                <pre id="results"></pre>

            </div>  

            <div>
                <Route exact path="/callback" render={() => {window.location.href="callback.html"}} />

                {/* {<Route path='/callback' component={callback}>callback</Route>} */}
            </div>
        </div>
      );
    }
  }

В файле testoidc.js (который импортируется выше) я добавил все используемые функции oidc (app.js в примерах проектов). Часть маршрута должна сделать callback.html доступным, я оставил этот файл как есть (что, вероятно, неправильно).

Файл testoidc.js содержит следующие функции:

import Oidc from 'oidc-client'


export function log() {
  document.getElementById('results').innerText = '';

  Array.prototype.forEach.call(arguments, function (msg) {
      if (msg instanceof Error) {
          msg = "Error: " + msg.message;
      }
      else if (typeof msg !== 'string') {
          msg = JSON.stringify(msg, null, 2);
      }
      document.getElementById('results').innerHTML += msg + '\r\n';
  });
}

var config = {
  authority: "http://localhost:5000",
  client_id: "js",
  redirect_uri: "http://localhost:3000/callback.html",
  response_type: "id_token token",
  scope:"openid profile api1",
  post_logout_redirect_uri : "http://localhost:3000/index.html",
};
var mgr = new Oidc.UserManager(config);

mgr.getUser().then(function (user) {
  if (user) {
      log("User logged in", user.profile);
  }
  else {
      log("User not logged in");
  }
});

export function login() {
  mgr.signinRedirect();
}

export function api() {
  mgr.getUser().then(function (user) {
      var url = "http://localhost:5001/identity";

      var xhr = new XMLHttpRequest();
      xhr.open("GET", url);
      xhr.onload = function () {
          log(xhr.status, JSON.parse(xhr.responseText));
      }
      xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
      xhr.send();
  });
}

export function logout() {
  mgr.signoutRedirect();
} 

Есть несколько вещей, которые идут не так. Когда я нажимаю кнопку входа в систему, меня перенаправляют на страницу входа в систему identityServer (что хорошо). Когда я вхожу в систему с действительными учетными данными, меня перенаправляют в приложение React: http://localhost:3000/callback.html#id_token=Token

Этот клиент в проекте Identity определен следующим образом:

new Client
                {
                    ClientId = "js",
                    ClientName = "JavaScript Client",
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowAccessTokensViaBrowser = true,

                    // where to redirect to after login
                    RedirectUris = { "http://localhost:3000/callback.html" },

                    // where to redirect to after logout
                    PostLogoutRedirectUris = { "http://localhost:3000/index.html" },

                    AllowedCorsOrigins = { "http://localhost:3000" },
                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "api1"
                    }

                }

Хотя кажется, что функция обратного вызова никогда не вызывается, она просто остается в URL обратного вызова с очень длинным токеном позади нее.

Кроме того, функция getUser продолжает отображать "Пользователь не вошел в систему" после входа в систему, а кнопка "Вызов API" постоянно сообщает, что токена нет. Итак, очевидно, что вещи не работают правильно. Я просто не знаю, по каким пунктам все идет не так. При проверке я вижу, что в локальном хранилище сгенерирован токен:

enter image description here

Кроме того, когда я нажимаю кнопку выхода из системы, меня перенаправляют на страницу выхода из системы Identity Host, но когда я нажимаю кнопку "Выйти", я не перенаправляюсь на мой клиент.

Мои вопросы:

  • Я на правильном пути, реализуя oidc-клиент в сочетании с IdentityServer4?
  • Использую ли я правильные библиотеки или мне нужны другие библиотеки, кроме oidc-client.js.
  • Есть ли какое-нибудь руководство, где используется интерфейс реагирования в сочетании с IdentityServer4 и oidc-клиентом (без приведения), я не смог найти ни одного.
  • Как/где добавить callback.html, следует ли его переписать?

Может ли кто-нибудь направить меня в правильном направлении, скорее всего, здесь что-то идет не так, но в данный момент я просто застрял в том, с чего начать.

Ответы