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

配置Azure AD多租户应用解决Teams SSO登录匹配错误

Teams多租户应用SSO认证失败:资源与iframe源不匹配

问题背景

我们基于VS Code Teams Toolkit的React模板开发一款将发布到Teams应用商店的应用,原本用Toolkit创建的单租户Azure AD应用实现了SSO登录功能,登录代码如下:

import { TeamsUserCredential } from "@microsoft/teamsfx";
import { useNavigate } from "react-router-dom";

interface IProps {
    teamsUserCredential?: TeamsUserCredential
}

const LoginPage = (props: IProps) => {
    const navigate = useNavigate();

    const login = async () => {
        try {
            await props.teamsUserCredential?.login(["User.Read", "User.ReadBasic.All"]);
            navigate("/home");
        } catch(e: any) {
            console.log("User did not logged", e);
        }
    }
    
    return (
        <div >
            <p>You need to login</p>
            <button onClick={login}>Login</button>
        </div>
    )
}

export default LoginPage;

由于Toolkit创建的应用无法启用多租户,我们手动创建了新的多租户Azure AD应用,并修改了Teams应用Manifest匹配该应用,但之后SSO认证失效,点击登录按钮触发错误:
Get SSO token failed with error: App resource defined in manifest and iframe origin do not match

应用托管在Azure存储账户,访问URL为https://m365tabxxxxxx.z6.web.core.windows.net,以下是两个Manifest内容:

Teams应用Manifest

{
    "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.12/MicrosoftTeams.schema.json",
    "version": "1.0.15",
    "manifestVersion": "1.12",
    "id": "myappid",
    "packageName": "fr.mycompanyname.myappname",
    "name": {
        "short": "myappname",
        "full": "myappname"
    },
    "developer": {
        "name": "mycompanyname",
        "mpnId": "0000000",
        "websiteUrl": "https://www.mycompanyname.fr/en/",
        "privacyUrl": "https://www.mycompanyname.fr/privacy-policy/",
        "termsOfUseUrl": "https://www.mycompanyname.fr/en/legal-informations/"
    },
    "description": {
        "short": "My app is nice",
        "full": "My app is nice but longer..."
    },
    "icons": {
        "outline": "outline.png",
        "color": "color.png"
    },
    "accentColor": "#FFFFFF",
    "staticTabs": [
        {
            "entityId": "index0",
            "name": "Personal Tab",
            "contentUrl": "https://m365tabxxxxxx.z6.web.core.windows.net/index.html#/tab",
            "websiteUrl": "https://m365tabxxxxxx.z6.web.core.windows.net/index.html#/tab",
            "scopes": [
                "personal"
            ]
        }
    ],
    "validDomains": [
        "myappname.mycompanyname.fr",
        "m365tabxxxxxx.z6.web.core.windows.net"
    ],
    "webApplicationInfo": {
        "id": "myMultiTenantAzureADAppId",
        "resource": "api://myappname.mycompanyname.fr/myMultiTenantAzureADAppId"
    },
    "localizationInfo": {
        "defaultLanguageTag": "en-us",
        "additionalLanguages": [
            {
                "languageTag": "fr",
                "file": "fr.json"
            }
        ]
    },
    "publisherDocsUrl": "https://www.mycompanyname.fr/en/help-page/"
}

Azure AD应用注册Manifest

{
    "id": "MyAADAppObjectId",
    "acceptMappedClaims": null,
    "accessTokenAcceptedVersion": 2,
    "addIns": [],
    "allowPublicClient": true,
    "appId": "myMultiTenantAzureADAppId",
    "appRoles": [],
    "oauth2AllowUrlPathMatching": false,
    "createdDateTime": "2023-12-12T16:41:59Z",
    "description": null,
    "certification": null,
    "disabledByMicrosoftStatus": null,
    "groupMembershipClaims": null,
    "identifierUris": [
        "api://myappname.mycompanyname.fr/myMultiTenantAzureADAppId"
    ],
    "informationalUrls": {
        "termsOfService": "https://www.mycompanyname.fr/en/legal-informations/",
        "support": null,
        "privacy": "https://www.mycompanyname.fr/privacy-policy/",
        "marketing": null
    },
    "keyCredentials": [],
    "knownClientApplications": [],
    "logoUrl": "https://mylogourl",
    "logoutUrl": null,
    "name": "myappname-multi-tenant",
    "notes": null,
    "oauth2AllowIdTokenImplicitFlow": true,
    "oauth2AllowImplicitFlow": true,
    "oauth2Permissions": [
        {
            "adminConsentDescription": "Allows Teams to call the app's web APIs as the current user.",
            "adminConsentDisplayName": "Teams can access app's web APIs",
            "id": "my_access_as_user_id",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "type": "User",
            "userConsentDescription": "Enable Teams to call this app's web APIs with the same rights that you have",
            "userConsentDisplayName": "Teams can access app's web APIs and make requests on your behalf",
            "value": "access_as_user"
        }
    ],
    "oauth2RequirePostResponse": false,
    "optionalClaims": null,
    "orgRestrictions": [],
    "parentalControlSettings": {
        "countriesBlockedForMinors": [],
        "legalAgeGroupRule": "Allow"
    },
    "passwordCredentials": [
        {
            "customKeyIdentifier": null,
            "endDate": "2025-12-12T10:10:24.569Z",
            "keyId": "myKeyId",
            "startDate": "2023-12-13T10:10:24.569Z",
            "value": null,
            "createdOn": "2023-12-13T10:10:42.6188671Z",
            "hint": "---",
            "displayName": "Password uploaded on Wed Dec 13 2023"
        }
    ],
    "preAuthorizedApplications": [
        {
            "appId": "5e3ce6c0-2b1f-4285-8d4b-75ee78787346", /*Microsoft Teams Web Client*/
            "permissionIds": [
                "my_access_as_user_id"
            ]
        },
        {
            "appId": "1fec8e78-bce4-4aaf-ab1b-5451cc387264", /*Microsoft Teams*/
            "permissionIds": [
                "my_access_as_user_id"
            ]
        }
    ],
    "publisherDomain": "mycompanyname.fr",
    "replyUrlsWithType": [
        {
            "url": "https://m365tabxxxxxx.z6.web.core.windows.net",
            "type": "Web"
        },
        {
            "url": "https://m365tabxxxxxx.z6.web.core.windows.net/blank-auth-end.html",
            "type": "Spa"
        },
        {
            "url": "https://m365tabxxxxxx.z6.web.core.windows.net/auth-end.html",
            "type": "Web"
        }
    ],
    "requiredResourceAccess": [
        {
            "resourceAppId": "00000003-0000-0000-c000-000000000000", /*Microsoft Graph*/
            "resourceAccess": [
                {
                    "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d", /*User.Read*/
                    "type": "Scope"
                },
                {
                    "id": "b340eb25-3456-403f-be2f-af7a0d370277", /*User.ReadBasic.All*/
                    "type": "Scope"
                }
            ]
        }
    ],
    "samlMetadataUrl": null,
    "signInUrl": "https://www.mycompanyname.fr/en",
    "signInAudience": "AzureADandPersonalMicrosoftAccount",
    "tags": [],
    "tokenEncryptionKeyId": null
}

问题排查与解决方案

核心原因

错误提示的本质是Teams应用Manifest中定义的webApplicationInfo.resource域名,与应用实际运行的iframe源域名不匹配。你的应用当前从Azure存储账户域名m365tabxxxxxx.z6.web.core.windows.net加载,但resource配置的是自定义域名myappname.mycompanyname.fr,Teams的SSO机制会验证这两个域名的一致性,从而拒绝令牌请求。

解决方案(二选一)

方案1:临时使用Azure存储账户域名测试

适用于不需要自定义域名的开发测试阶段:

  1. 修改Teams应用Manifest的webApplicationInfo.resource:
    "webApplicationInfo": {
        "id": "myMultiTenantAzureADAppId",
        "resource": "api://m365tabxxxxxx.z6.web.core.windows.net/myMultiTenantAzureADAppId"
    }
    
  2. 登录Azure门户,找到对应的多租户AD应用,更新identifierUris为相同值:
    "identifierUris": [
        "api://m365tabxxxxxx.z6.web.core.windows.net/myMultiTenantAzureADAppId"
    ]
    
  3. 重新打包Teams应用并上传到Teams管理中心,清除Teams客户端缓存后测试。

方案2:使用自定义域名正式部署

如果要使用myappname.mycompanyname.fr作为访问域名:

  1. 将自定义域名映射到Azure存储账户的静态网站终结点(需在Azure门户配置自定义域名绑定)。
  2. 修改Teams应用Manifest中的contentUrl和websiteUrl为自定义域名地址:
    "staticTabs": [
        {
            "contentUrl": "https://myappname.mycompanyname.fr/index.html#/tab",
            "websiteUrl": "https://myappname.mycompanyname.fr/index.html#/tab"
        }
    ]
    
  3. 确保validDomains已包含自定义域名(你的配置中已满足)。
  4. 更新Azure AD应用的replyUrlsWithType,添加自定义域名的回调地址:
    "replyUrlsWithType": [
        // 保留原有存储账户地址,新增以下项
        {
            "url": "https://myappname.mycompanyname.fr",
            "type": "Web"
        },
        {
            "url": "https://myappname.mycompanyname.fr/blank-auth-end.html",
            "type": "Spa"
        },
        {
            "url": "https://myappname.mycompanyname.fr/auth-end.html",
            "type": "Web"
        }
    ]
    
  5. 重新打包上传Teams应用,清除缓存测试。

额外检查项

  1. 确认.env配置文件中:
    • REACT_APP_CLIENT_ID设置为多租户AD应用的appId
    • REACT_APP_OAUTH_AUTHORITY设置为多租户权威地址https://login.microsoftonline.com/common(单租户为租户ID,多租户必须用common)
  2. 检查TeamsUserCredential初始化是否使用了正确的参数:
    const teamsUserCredential = new TeamsUserCredential({
      clientId: process.env.REACT_APP_CLIENT_ID,
      authority: process.env.REACT_APP_OAUTH_AUTHORITY
    });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 22:59:52