You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 14集成Azure登录:个人账号无法登录并获取订阅详情

问题分析

当你在登录请求中直接包含https://management.azure.com/user_impersonation scope时,个人Microsoft账号会被拒绝登录——这是因为Azure管理API的权限机制默认对个人账号有更严格的限制:直接在登录阶段请求资源特定scope会触发权限校验,而仅请求OpenID基础身份信息(姓名、邮箱)时,个人账号可以正常通过身份验证。

解决方案

1. 拆分登录与Token获取流程

先完成基础身份登录(仅请求OpenID相关scope),再单独获取Azure管理API的访问Token,避免登录阶段触发资源权限校验:

修改LoginPage.tsx的handleLogin函数:

"use client";

import React from "react";
import { useMsal, InteractionRequiredAuthError } from "@azure/msal-react";
import axios from "axios";

export default function Login() {
  const { instance } = useMsal();

  const handleLogin = async () => {
    try {
      // 第一步:仅登录获取用户基础信息(姓名、邮箱)
      const loginResponse = await instance.loginPopup({
        scopes: ["openid", "profile", "email"],
      });
      console.log("Login Response:", loginResponse);
      instance.setActiveAccount(loginResponse.account);

      // 第二步:静默获取Azure管理API的访问Token
      const tokenResponse = await instance.acquireTokenSilent({
        account: loginResponse.account,
        scopes: ["https://management.azure.com/user_impersonation"],
      });

      fetchSubscriptions(tokenResponse.accessToken);
    } catch (error: any) {
      // 静默获取失败时,弹出窗口请求权限
      if (error instanceof InteractionRequiredAuthError) {
        const tokenResponse = await instance.acquireTokenPopup({
          scopes: ["https://management.azure.com/user_impersonation"],
        });
        fetchSubscriptions(tokenResponse.accessToken);
      } else {
        console.error("Login/Token Error:", error);
      }
    }
  };

  const fetchSubscriptions = async (accessToken: string) => {
    try {
      const response = await axios.get(
        "https://management.azure.com/subscriptions?api-version=2020-01-01",
        {
          headers: {
            Authorization: `Bearer ${accessToken}`,
          },
        }
      );

      if (response.data.value.length === 0) {
        console.log("当前个人账号未关联任何Azure订阅");
        // 可在此添加UI提示告知用户
      } else {
        console.log("Subscription Details:", response.data);
      }
    } catch (error: any) {
      if (error.response?.status === 403) {
        console.log("个人账号无权限访问Azure订阅,请确保账号已关联订阅且拥有对应权限");
      } else {
        console.error("Error fetching subscriptions:", error.response?.data || error.message);
      }
    }
  };

  return (
    <div className="flex flex-col gap-2">
      <button
        onClick={handleLogin}
        className="bg-blue-500 text-white px-4 py-2 rounded"
      >
        Login with Azure
      </button>
    </div>
  );
}

2. 确认Azure AD应用配置

  • 检查支持的账户类型是否设置为任何组织目录中的账户和个人Microsoft账户(例如Skype、Xbox)
  • 在API权限中,除了Azure Service Management的user_impersonation,需添加Microsoft Graph的openid、profile、email权限(用户同意即可,无需管理员批准)
  • 确认SPA重定向URI已正确配置为http://localhost:3000(生产环境替换为实际域名)

3. 处理个人账号订阅限制

个人Microsoft账号必须关联至少一个Azure订阅才能成功调用/subscriptions接口,否则会返回空列表或403错误。代码中已添加对应判断和提示,可根据需求补充UI层面的用户引导。

4. 可选:调整MSAL Authority配置(针对特殊场景)

如果上述方案仍有问题,可尝试显式指定支持的租户类型:

const msalConfig = {
  auth: {
    clientId: "<myclientid>", 
    authority: "https://login.microsoftonline.com/common", 
    redirectUri: "http://localhost:3000",
    knownAuthorities: ["login.microsoftonline.com"],
  },
};

内容的提问来源于stack exchange,提问作者Vishal Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 20:55:17