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

集成MSAL的Ionic+React应用SSO遇AADSTS700009错误求助

问题

在Ionic + React应用中基于MSAL实现单点登录(SSO),使用依赖:

@azure/msal-browser: ^3.26.1
@azure/msal-react: ^3.0.5

MSAL配置:

const msalConfig: Configuration = {
  auth: {
    clientId: '328xxxa-3x44-43x5-8x9d-6ec67xxxx',
    authority: 'https://login.microsoftonline.com/organizations',
    redirectUri: 'msauth.net.myApp.pckgApp://auth'
  },
  cache: {
    cacheLocation: 'localStorage',
    storeAuthStateInCookie: false
  },
  loggerOptions: {
    loggerCallback: (level: LogLevel, message: string, containsPii: boolean) => {
      if (!containsPii) {
        console.log(`[${LogLevel[level]}]: ${message}`);
      }
    },
    piiLoggingEnabled: false,
    logLevel: LogLevel.Verbose
  }
};

const msalInstance = new PublicClientApplication(msalConfig);

登录函数:

public async login() {
  console.log('Using codeChallenge:', codeChallange.codeChallenge);

  const loginRequest = {
    scopes: ['user.read', 'openid', 'profile'],
    prompt: 'select_account',
    redirectUri: 'msauth.net.myApp.pckgApp://auth',
    extraQueryParameters: {
      code_challenge: codeChallange.codeChallenge,
      code_challenge_method: 'S256'
    }
  };

  try {
    msalInstance.addEventCallback(event => {
      console.log(event, 'msalInstance.addEventCallback');
      if (event.eventType === EventType.HANDLE_REDIRECT_START) {
        console.log("Redirect handling started");
      }
      if (event.eventType === EventType.HANDLE_REDIRECT_END) {
        console.log("Redirect handling complete");
      }
    });
    await msalInstance.loginRedirect(loginRequest).catch((error) => {
      console.error('Login error:', error);
    });

  } catch (error) {
    console.error('Login error:', error);
    throw error;
  }
}

本地生成了code_challenge,登录流程看似正常,但处理重定向并尝试获取令牌时遇到错误:

AADSTS700009: Reply address must be provided when presenting an authorization code requested with an explicit reply address.

处理重定向及获取令牌的代码:

useEffect(() => {
  const handleDeepLink = async (event: any) => {
    console.log(handleRedirect, "Redirect URL received:", event.url);
    const urlObj = new URL(event.url);
    const fragment = urlObj.hash.substring(1); // Remove the # symbol
    const params = new URLSearchParams(fragment);
    const authCode = params.get("code");
    console.log(authCode, 'authCode got');

    const result = await msalInstance.acquireTokenByCode({
      code: authCode as string,
      scopes: ['user.read', 'openid', 'profile'],
      redirectUri: 'msauth.net.myApp.pckgApp://auth',
      codeVerifier: localStorage.getItem('codeVerifier') as string,
    }).catch((error) => {
      console.error(error, 'acquireTokenByCode error');
    });
    console.log(result, 'result of token');
    
    // Call handleRedirectPromise after getting the URL
    const response = await msalInstance.handleRedirectPromise();
    console.log(response, 'response');
    if (response) {
      console.log("✅ Login successful! Token response:", response);
    } else {
      console.error("⚠️ No authentication response found.");
    }
  };

  App.addListener("appUrlOpen", handleDeepLink);

  return () => {
    App.removeAllListeners();
  };
}, []);

info.plist已配置正确重定向Scheme:

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleTypeRole</key>
    <string>Editor</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>msauth.net.dnaofsafetydev.blueprintapp</string>
    </array>
  </dict>
</array>

已验证:

  • MSAL配置和登录请求中的redirectUri与info.plist中的URL Scheme一致
  • code_challenge和code_verifier已正确生成并存储
  • 重定向URL Scheme已在MSAL配置和应用中正确注册

需要分析错误原因及解决方案,确认是否需要修改MSAL配置或其他设置以确保授权码能正确兑换为令牌。


原因分析

  1. 重复处理重定向流程:同时手动调用acquireTokenByCode和MSAL内置的handleRedirectPromise,二者都是处理授权码兑换令牌的逻辑,手动调用会干扰MSAL的内置上下文,导致参数传递异常。
  2. 授权码提取方式错误:从URL hash中手动提取授权码不符合MSAL预期,handleRedirectPromise会自动处理重定向URL并提取完整的授权上下文,手动提取可能遗漏关键参数。
  3. 上下文关联缺失:手动调用acquireTokenByCode时,MSAL实例无法关联原登录请求的完整上下文,导致AAD验证时认为reply address不匹配。

解决方案

1. 移除手动处理逻辑,依赖MSAL内置的handleRedirectPromise

修改重定向处理代码,去掉手动提取授权码和调用acquireTokenByCode的部分,直接使用MSAL的内置方法:

useEffect(() => {
  const handleDeepLink = async (event: any) => {
    console.log("Redirect URL received:", event.url);
    
    // 直接用MSAL内置方法处理重定向流程
    const response = await msalInstance.handleRedirectPromise();
    console.log(response, 'response');
    if (response) {
      console.log("✅ Login successful! Token response:", response);
      // 这里可添加登录成功后的业务逻辑,比如获取用户信息、存储令牌等
    } else {
      console.error("⚠️ No authentication response found.");
    }
  };

  App.addListener("appUrlOpen", handleDeepLink);

  return () => {
    App.removeAllListeners();
  };
}, []);

2. 统一redirectUri配置

登录请求中可省略redirectUri,直接使用MSAL实例配置的默认值,避免重复设置导致不一致:

const loginRequest = {
  scopes: ['user.read', 'openid', 'profile'],
  prompt: 'select_account',
  extraQueryParameters: {
    code_challenge: codeChallange.codeChallenge,
    code_challenge_method: 'S256'
  }
};

3. 验证Azure AD应用注册的重定向URI

登录Azure门户,进入目标应用注册的身份验证页面,确认已添加msauth.net.myApp.pckgApp://auth作为重定向URI,且类型设置为移动和桌面应用。

4. 简化PKCE流程管理

无需手动传递codeVerifier,MSAL会自动管理PKCE流程的参数存储与读取,确保生成的codeVerifier在localStorage中正常存储即可。


内容的提问来源于stack exchange,提问作者Ragesh Pikalmunde

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 02:10:54