未处理的拒绝ClientAuthError:需要用户登录对于静默呼叫,请求必须包含sid或login_hint

问题描述

我正在React中制作一个应用程序,并使用“ react-aad-msal”库(https://www.npmjs.com/package/react-aad-msal),该库已使用AzureAD进行了身份验证和授权,然后从API接收数据(列表任务)(如 我以https://github.com/Azure-Samples/ms-identity-javascript-angular-spa-dotnetcore-webapi-roles-groups/tree/master/chapter2/TodoListAPI为例。我具有以下组件:authProvider.js,TodoConstants.js,TodoActions.js,TodoReducer.js,TodoContainer.js,TodoSaga.js。当我添加const token = await authProvider.getAccesstoken()以从TodoSaga.js中的API请求数据时,我开始收到错误消息:未处理的拒绝(ClientAuthError):需要用户登录。对于静呼叫,请求必须包含sid或login_hint。如果在authenticationParameters中将loginHint:“ myMail@domain.com”添加到authProvider.js,则它将开始正常工作并可以直接进入身份验证阶段,但是尚不清楚如何正确指定loginHint或sid。请告诉我在这种情况下如何正确获取loginHint或sid?哪个参数更合适?

authProvider.js

import { MsalAuthProvider,LoginType } from "react-aad-msal";
import { Logger,LogLevel } from "msal";

const config = {
  auth: {
    clientId: "xxxx-xxxx-xxxx-xxxx",authority:
      "https://login.microsoftonline.com/yyyy-yyyy-yyyy-yyyy",validateAuthority: true,redirectUri: "http://localhost:3000",postlogoutRedirectUri: "http://localhost:3000",navigatetoLoginRequestUrl: true,},cache: {
    cacheLocation: "localStorage",storeAuthStateInCookie: true,};

const authenticationParameters = {
  scopes: [
    "openid","profile","api://iiii-iiii-iiii-iiii/access_as_user",],// loginHint: loginHint,<---- How to get it correctly?
  // sid: sid,<---- How to get it correctly?
};

const options = {
  loginType: LoginType.Popup,tokenRefreshUri: window.location.origin + "/auth.html",};

export const authProvider = new MsalAuthProvider(
  config,authenticationParameters,options
);

TodoConstants.js

export const TodoDATASOURCE_API_CALL_REQUEST = "TodoDATASOURCE_API_CALL_REQUEST";
export const TodoDATASOURCE_API_CALL_SUCCESS = "TodoDATASOURCE_API_CALL_SUCCESS";
export const TodoDATASOURCE_API_CALL_FAILURE = "TodoDATASOURCE_API_CALL_FAILURE";

TodoActions.js

import * as types from "./TodoConstants";

export const fetchTodoDataSourceRequest = () => {
  return {
    type: types.TodoDATASOURCE_API_CALL_REQUEST
  };
};

export const fetchTodoDataSourceSuccess = response => {
  return {
    type: types.TodoDATASOURCE_API_CALL_SUCCESS,data: response,};
};

export const fetchTodoDataSourceFail = () => {
  return {
    type: types.TodoDATASOURCE_API_CALL_FAILURE
  };
};

TodoReducer.js

import * as types from "./TodoConstants";

const initialState = {
  fetching: false,data: null,error: null,};

export default function reducer(state = initialState,action) {
  switch (action.type) {
    case types.TodoDATASOURCE_API_CALL_REQUEST:
      return { ...state,fetching: true,error: null };
    case types.TodoDATASOURCE_API_CALL_SUCCESS:
      return {
        ...state,fetching: false,data: action.data,};
    case types.TodoDATASOURCE_API_CALL_FAILURE:
      return {
        ...state,error: action.error
      };

    default:
      return state;
  }
}

TodoContainer.js

import React from "react";
import TodoView from "../../views/TodoView";
import { connect } from "react-redux";
import * as actions from "./TodoActions";
// import { bindActionCreators } from "redux";
import { bindActionCreators } from "redux";

class TodoDataSourceContainer extends React.PureComponent {
  componentDidMount() {
    this.props.fetchTodoDataSourceRequest();
  }
  render() {
    return (
      <React.Fragment>
        <TodoDataSourceView {...this.props} />
      </React.Fragment>
    );
  }
}

const mapStatetoProps = ({
  TodoDataSourceContainerReducerState: { fetching,data,error},}) => {
  return {
    fetching: fetching,data: data,error: error,};
};

const mapdispatchToProps = (dispatch) => {
  const {
    fetchTodoDataSourceRequest: fetchTodoDataSourceRequest,} = bindActionCreators(actions,dispatch);
  return {
    fetchTodoDataSourceRequest: fetchTodoDataSourceRequest,};
};

export default connect(
  mapStatetoProps,mapdispatchToProps
)(TodoDataSourceContainer);

TodoSaga.js

import { takeLatest,call,put } from "redux-saga/effects";
import * as types from "./TodoConstants";
import * as actions from "./TodoActions";
import { authProvider } from "../../../utils/Auth/authProvider";

const request = async (url) => {
  const token = await authProvider.getAccesstoken(); // <---- After adding this,an error appears and the need for loginHint or sid

  const response = await fetch(url,{
    method: "GET",headers: {
      Authorization: "Bearer " + token.accesstoken,"Content-Type": "application/json",});

  if (response.ok) {
    let result = await response.json();
    return result;
  } else {
    alert("Error HTTP: " + response.status);
  }
};

export default function* watcherSaga() {
  yield takeLatest(types.TodoDATASOURCE_API_CALL_REQUEST,workerSaga);
}

function* workerSaga() {
  try {
    const response = yield request("https://localhost:44351/api/todolist");
    yield put(actions.fetchTodoDataSourceSuccess(response));
  } catch (error) {
    yield put(actions.fetchTodoDataSourceFail(error));
  }
}

enter image description here

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)