带有IdentityServer4和oidc-client-js的ReactJS错误:“无代码响应”

时间:2019-08-30 20:28:13

标签: reactjs identityserver4 oidc-client-js

我试图通过oidc-client-js库使ReactJS与IdentityServer4一起使用。

问题

我单击登录按钮,然后重定向到IdentityServer4,登录后,我重定向到/login-callback,然后从那里重定向到/,但是在控制台中出现以下错误:

reactjs error no state in response

我不确定自己在做什么错,但是我尝试了各种尝试,但似乎没有任何效果。

代码

所有代码均为开源代码,sits here

App.jsx

// other code ommited, but this is a route
<AuthHandshake path="/login-callback" />

AuthHandshake.jsx

import React from "react";
import { AuthConsumer } from "../AuthProvider/AuthProvider";

function AuthHandshake() {
  return <AuthConsumer>{value => value.loginCallback()}</AuthConsumer>;
}

export default AuthHandshake;

AuthProvider.jsx

import React, { useState } from "react";
import { navigate } from "@reach/router";
import { UserManager, WebStorageStateStore } from "oidc-client";
import AuthContext from "../../contexts/AuthContext";
import { IDENTITY_CONFIG } from "../../utils/authConfig";

IDENTITY_CONFIG.userStore = new WebStorageStateStore({
  store: window.localStorage
});

const userManager = new UserManager(IDENTITY_CONFIG);

const login = () => {
  console.log("Login button click handled.");
  userManager.signinRedirect();
};

const logout = () => {
  userManager.signoutRedirect();
};

export function AuthProvider(props) {
  const [user, setUser] = useState(null);

  const loginCallback = () => {
    userManager.signinRedirectCallback().then(
      user => {
        window.history.replaceState(
          {},
          window.document.title,
          window.location.origin
        );
        setUser(user);
        navigate("/");
      },
      error => {
        console.error(error);
      }
    );
  };

  const providerValue = {
    login: login,
    logout: logout,
    loginCallback: loginCallback,
    isAuthenticated: user
  };

  const Provider = () => {
    if (user) {
      return (
        <AuthContext.Provider value={providerValue}>
          {props.children}
        </AuthContext.Provider>
      );
    } else {
      return <div className="auth-provider">{props.children}</div>;
    }
  };

  return (
    <>
      <AuthContext.Provider value={providerValue}>
        {props.children}
      </AuthContext.Provider>
    </>
  );
}

export const AuthConsumer = AuthContext.Consumer;

在IdentityServer端,我将登出注销重定向设置为同一件事/login-callback

new Client
{
  ClientId = "bejebeje-react-local",
  ClientName = "Bejebeje ReactJS SPA Client",
  AllowedGrantTypes = GrantTypes.Code,
  RequirePkce = true,
  RequireClientSecret = false,
  RequireConsent = false,
  RedirectUris = { "http://localhost:1234/login-callback" },
  PostLogoutRedirectUris = { "http://localhost:1234/logout-callback" },
  AllowedCorsOrigins = { "http://localhost:1234" },
  AllowedScopes = { "openid", "profile", "bejebeje-api-local" },
  AllowOfflineAccess = true,
  RefreshTokenUsage = TokenUsage.ReUse,
}

我要去哪里错了?

2 个答案:

答案 0 :(得分:2)

我必须将export default { plugins: [ .... { src: '~/plugins/socketio.js', mode: 'client' }, // only on client side ... ] } 添加到response_mode: 'query'

UserManager

答案 1 :(得分:1)

在这里尝试。 https://github.com/JwanKhalaf/Bejebeje.React/blob/bug/fix-no-code-response-on-redirect/src/components/AuthProvider/AuthProvider.jsx#L15

基本上,当您从客户端(OIDC-client.js)发送登录请求时,客户端会在URL中随登录请求一起发送唯一的标识符(State)。客户端将此值保存在您选择的存储选项(本地/会话)中。成功登录后,服务器在响应重定向URL中发布令牌,并且还包括最初在登录请求中发送的唯一标识符客户端。在chrome开发人员工具中观看登录请求网址和响应网址。

当OIDC客户端库receives the sign-in response时,它从URL中获取唯一标识符,并与登录请求时保存在本地/会话存储中的值匹配。如果它们不匹配,则客户端将不接受服务器发出的令牌。

这只是确保用户不接受任何随机服务器发出的任何令牌或任何带有书签的URL的额外安全性的一级。

希望这会有所帮助!!

usermanager.signinRedirect({ state: { bar: 15 } });