亚马逊AWS官方博客

自建 IdP 实现 Amazon Quick SSO 对接实战 — SAML 2.0 + OIDC + PKCE 双协议对接完整指南

摘要:Amazon Quick 分 Web 与 Desktop 两个端,分别使用 SAML 2.0 与 OIDC + PKCE 两种认证协议,二者必须收敛到同一个身份提供方(IdP)才能实现单点登录SSO)。本文面向自建 IdP 的开发方,给出用自建 IdP 打通Amazon Quick 两端SSO 的完整对接实战:Desktop 侧复用现有 OIDC 能力,Web 侧为 IdP 增补 SAML 2.0 直连。


ℹ️ 前提: Amazon Quick 账号认证方式为 IAM Federation(控制台选项”Password-based or Single Sign-On”,对应 API 的 IAM_AND_QUICKSIGHT);适用对象为自建 IdP 的开发方。

1. Quick 认证的两端

Amazon Quick 有两个端,认证协议不同,但都要收敛到同一个 IdP 才能一次登录:

认证协议 自建 IdP 现状
Amazon Quick Desktop OIDC + PKCE ✅ 已支持,已跑通
Amazon Quick Web SAML 2.0 ❌ 缺,导致 Web 端退回 Quick 原生密码页

根因:Desktop 登录内含一次 Web 认证。Web 端如果没有 SAML 通道 → 退回原生密码 → 用户被卡。要解决这个问题,IdP 必须额外实现 SAML 2.0 IdP 能力,且发出 AWS 联邦专用格式的断言。

⚠️ 通用 SAML ≠ AWS 联邦 SAML。断言里必须带 AWS 专用属性(见第 4 节),否则 AWS STS 直接拒绝。

2. 整体架构

Amazon Quick Web     → SAML → ┐
                              ├→ 自建 IdP → 飞书
Amazon Quick Desktop → OIDC → ┘   (Web 走新增的 SAML,Desktop 走现有 OIDC)

Web 端通过 AWS AssumeRoleWithSAML 换临时凭证进入Amazon Quick;两端都靠 email 锚定为同一个用户。

3. AWS 侧配置(在客户 AWS 账号里做,一次性)

以下用占位符<ACCOUNT_ID> = 12 位 AWS 账号 ID。

3.1 Step 1 — 建 SAML Provider(上传 IdP 的 metadata)

aws iam create-saml-provider \
  --name your-idp-saml \
  --saml-metadata-document file://your-idp-metadata.xml
# 产出: arn:aws:iam::<ACCOUNT_ID>:saml-provider/your-idp-saml

3.2 Step 2 — 建 IAM Role(信任该 Provider + Quick 开通权限)

信任策略(trust policy):

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Federated": "arn:aws:iam::<ACCOUNT_ID>:saml-provider/your-idp-saml"},
    "Action": "sts:AssumeRoleWithSAML",
    "Condition": {"StringEquals": {"SAML:aud": "https://signin.aws.amazon.com/saml"}}
  }]
}

权限策略(inline policy,决定用户自动开通为哪种角色):

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["quicksight:CreateAdmin"],
    "Resource": "arn:aws:quicksight::<ACCOUNT_ID>:user/${aws:userid}"
  }]
}

JIT 自动开通:配好后首次登录自动创建用户,无需手工 invite。按权限最高级别开通(有CreateAdmin 建 admin;只给CreateUser 建 author;CreateReader 建 reader)。

限制:JIT 只能建非 Pro 角色(Admin/Author/Reader),Pro 需事后升级;IdP 侧角色变更不会反向同步到Amazon Quick

4. IdP 必须发出的 SAML 断言

每个 SAML 响应必须满足下列全部条件,缺一即被 AWS 拒绝。属性 Name 大小写敏感,必须一字不差。

元素 硬性要求
XML 签名 断言(或响应)必须用 X.509 证书做XML-DSig 数字签名。证书需登记在 Step 1 的 metadata 里。⚠️ 签名规范化(canonicalization)是自研实现最易翻车处
Recipient / Audience SubjectConfirmationDataRecipientAudienceRestrictionAudience = https://signin.aws.amazon.com/saml
NameID 格式为 persistent / transient / emailAddress 之一
Role 属性 Name="https://aws.amazon.com/SAML/Attributes/Role" ,值为<role_arn>,<provider_arn>逗号对
RoleSessionName 属性 Name="https://aws.amazon.com/SAML/Attributes/RoleSessionName" ,值 2–64 字符,仅允许字母数字 _ . , + = @ - ,不能含空格,建议用 email
email(Quick 匹配用户) 通过 NameID(emailAddress 格式)或 PrincipalTag 传递,且必须与Amazon Quick 用户 email 完全一致(区分大小写)

4.1 SAML 响应断言XML 范例(替换尖括号占位符)

<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
  <saml:Subject>
    <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
      user@example.com
    </saml:NameID>
    <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
      <saml:SubjectConfirmationData
        NotOnOrAfter="2026-07-18T15:30:00Z"
        Recipient="https://signin.aws.amazon.com/saml"/>
    </saml:SubjectConfirmation>
  </saml:Subject>

  <saml:Conditions NotBefore="2026-07-18T14:50:00Z" NotOnOrAfter="2026-07-18T15:30:00Z">
    <saml:AudienceRestriction>
      <saml:Audience>https://signin.aws.amazon.com/saml</saml:Audience>
    </saml:AudienceRestriction>
  </saml:Conditions>

  <saml:AttributeStatement>
    <!-- Role: role_arn,provider_arn 逗号对 -->
    <saml:Attribute Name="https://aws.amazon.com/SAML/Attributes/Role">
      <saml:AttributeValue>arn:aws:iam::&lt;ACCOUNT_ID&gt;:role/your-federation-role,arn:aws:iam::&lt;ACCOUNT_ID&gt;:saml-provider/your-idp-saml</saml:AttributeValue>
    </saml:Attribute>

    <!-- RoleSessionName: 用 email,不能有空格 -->
    <saml:Attribute Name="https://aws.amazon.com/SAML/Attributes/RoleSessionName">
      <saml:AttributeValue>user@example.com</saml:AttributeValue>
    </saml:Attribute>

    <!-- 可选: 作为 principal tag 传 email,便于 Quick 匹配 -->
    <saml:Attribute Name="https://aws.amazon.com/SAML/Attributes/PrincipalTag:Email">
      <saml:AttributeValue>user@example.com</saml:AttributeValue>
    </saml:Attribute>
  </saml:AttributeStatement>
</saml:Assertion>

上面<saml:Assertion>整体必须被签名(<ds:Signature>元素,此处省略)。

⚠️ 一旦断言里传了 PrincipalTag:*(如上面的 PrincipalTag:Email),被 assume 的 Role 信任策略必须额外允许 sts:TagSession,否则 AWS STS 会拒绝。配套写法见第 9 节 §9.2 的信任策略(含 sts:TagSession 声明)。

5. Amazon Quick 侧配置(SP-initiated federation)

Amazon Quick 管理台 → Manage Amazon Quick → Single sign-on (IAM federation):

字段
IdP URL IdP 的 SAML SSO 发起地址(SP-initiated 入口)
RelayState parameter RelayState (具体参数名由 IdP 决定)

先用页面 Test 链接验证,通过后再把 Status 设为 ON。

6. 常见错误对照(AWS STS 返回)

报错 原因
RoleSessionName is required in AuthnResponse 断言缺 RoleSessionName 属性
RoleSessionName must match [a-zA-Z_0-9+=,.@-]{2,64} 值含空格/非法字符(别用带空格的显示名)
InvalidIdentityToken / audience 不匹配 Recipient/Audience 不是https://signin.aws.amazon.com/saml
assume 失败 / Role 无效 Role 属性的role_arn,provider_arn 顺序或 ARN 写错
签名校验失败 XML 签名规范化/证书与 metadata 不一致
登录成功进不去 Quick email 与 Quick 用户不一致(区分大小写)

7. IAM 资源 ARN 根因补充(region 必须留空)

客户现象:Role 权限策略 Resource 写成带 region 的arn:aws:quicksight:us-east-1:<ACCOUNT_ID>:user/${aws:userid}时登录失败,只有改成"*"才通。

根因(已用 IAM Policy Simulator 验证):QuickSight 联邦 JIT 发起CreateAdmin 时,针对的 user ARN 是无 region 的(quicksight::两个冒号)。策略写了 region → 与真实请求资源不匹配 → implicitDeny

策略 Resource 请求资源 ARN 判定
带 region 带 region allowed
region 留空 region 留空 allowed
带 region region 留空(真实情况) implicitDeny

正解:不要放宽成 *,把 ARN 的 region 段留空即可:

"Resource": ["arn:aws:quicksight::<ACCOUNT_ID>:user/${aws:userid}"]

quicksight:: 是两个连续冒号,account 前的 region 位置空着。)

8. “登录两次”问题分析(SAML + OIDC session 未共享)

现象:客户改好后能登录,但要认证两次——先 SAML(Web),再 OIDC(Desktop)。两次的 authorize URL 分别是:

  • 第一次(SAML/Web):https://<idp>/auth/oauth/authorize?client_id=...&redirect_uri=.../auth/saml/.../callback
  • 第二次(OIDC/Desktop):https://<idp>/auth/oidc/oauth2/authorize?...&scope=...offline_access...&code_challenge=...

根因判断:两次走的是客户 IdP 里两条不同端点(/auth/oauth/...给 SAML,/auth/oidc/oauth2/...给 OIDC)。虽然同一套账号,但客户 IdP 把这两条协议链路当成了两条独立会话,没有共享SSO session,所以各要认证一次。

是否正常:Desktop 登录内含 Web 认证是产品设计,但“内含”本应复用已有会话、无感通过。现在没复用 → 说明客户 IdP 两条链路的 session 没打通。这属于客户 IdP 侧要修,不是 Quick 或我方能改。

给客户的排查问题:SAML 链路( /auth/oauth/authorize)与 OIDC 链路( /auth/oidc/oauth2/authorize)是否共享同一 SSO session/cookie?能否做到用户在一条链路登录后,另一条凭会话静默通过、不再要求二次登录?

解决方向:只要让两条链路共享同一份SSO 会话即可——用户在其中一条登录后,IdP 为其建立会话 cookie,另一条链路凭该 cookie 静默通过,无需二次认证。这需要客户 IdP 侧把 SAML、OIDC 两条端点收敛到同一套会话机制上。

9. AWS 控制台配置

以下为 AWS 控制台侧的分步配置截图。URL 中的{region}、{账号}、{认证域名}、{认证应用 KEY}均为占位符,请替换为实际值。

9.1 创建身份提供者(Identity providers)

控制台入口:https://{region}.console.aws.amazon.com/iam/home?region={region}#/identity_providers

1. 创建身份提供者。

[图 1. 创建身份提供者入口]

2. 上传 IdP metadata 完成创建。

[图 2. 上传 IdP metadata]

3. 记录身份提供者的 ARN,统一认证应用那边配置应与此一致。

[图 3. 身份提供者 ARN]

9.2 创建 SAML Role

创建一个绑定身份提供者的角色。入口:https://{region}.console.aws.amazon.com/iam/home?region={region}#/roles

1. 新建角色,选择 SAML 2.0 federation 并绑定前面创建的身份提供者。

[图 4. 新建角色并选择 SAML 联邦]

2. 继续角色创建流程。

[图 5. 角色创建流程]

3. 配置角色权限策略,内容固定如下,需要修改成正确的账号。此处用CreateAdmin 锁定默认角色为 admin(与第 3 节一致;如需开通 author/reader,改成CreateUser/CreateReader,且只保留一个Create*动作以避免歧义):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Action": [
                "quicksight:CreateAdmin",
                "quicksight:DescribeUser",
                "quicksight:ListUserGroups",
                "quicksight:GetGroupMapping",
                "quicksight:SearchDirectoryGroups",
                "quicksight:GetDashboardEmbedUrl",
                "quicksight:GetSessionEmbedUrl",
                "quicksight:GenerateEmbedUrlForRegisteredUser",
                "quicksight:GenerateEmbedUrlForAnonymousUser"
            ],
            "Resource": [
                "arn:aws:quicksight::{账号}:user/${aws:userid}"
            ]
        }
    ]
}
⚠️ 注意 Resourcequicksight:: 为两个连续冒号,region 段必须留空(详见第 7 节)。

[图 6. 角色权限策略]

4. 编辑角色详情,编辑好直接创建。

[图 7. 编辑角色详情]

5. 修改信任策略,找到前面创建的角色。

[图 8. 进入信任策略编辑]

6. 信任策略内容改成以下代码(同时授予 AssumeRoleWithSAML 与 TagSession):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::{账号}:saml-provider/{provider名称}"
            },
            "Action": "sts:AssumeRoleWithSAML",
            "Condition": {
                "StringEquals": {
                    "SAML:aud": "https://signin.aws.amazon.com/saml"
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::{账号}:saml-provider/{provider名称}"
            },
            "Action": "sts:TagSession",
            "Condition": {
                "StringLike": {
                    "aws:RequestTag/Email": "*@邮箱后缀"
                }
            }
        }
    ]
}

然后更新。

[图 9. 更新信任策略]

7. 记录角色的 ARN,统一认证应用那边配置应与此一致。

[图 10. 角色 ARN]

10. Amazon Quick 管理端配置

管理端地址:https://{region}.quicksight.aws.amazon.com/sn/admin

10.1 账户(Account)创建

需要配置账户名(名称有限制,只能英文,例如zixun)。

10.2 SSO 配置

地址:https://{region}.quicksight.aws.amazon.com/sn/account/{账户}/admin/single-sign-on

按步骤开启:

  1. 开启 Email Syncing for Federated Users,登录时默认使用邮箱登录
  2. 开启 Service Provider Initiated SSO 前,必须先配置 Configuration:
    • IdP URL:https://{认证域名}/saml/{认证应用 KEY}/sso
    • IdP redirect URL parameter 固定值:RelayState

[图 11. SSO 配置(IdP URL 与 RelayState)]

10.3 管理 Extension access(Desktop OIDC)

1. 进入 Extension access 管理。

[图 12. Extension access 管理入口]

2. 创建新的 Extension access。

[图 13. 创建 Extension access]

3. 选择服务类型。

[图 14. 选择服务类型]

4. 填写配置信息(Name 自定义,后面会用到):

  • Issuer URL:https://{认证域名}/oidc
  • Authorization Endpoint:https://{认证域名}/oidc/oauth2/authorize
  • Token Endpoint:https://{认证域名}/oidc/oauth2/token
  • JWKS URI:https://{认证域名}/oidc/.well-known/jwks.json
  • Client ID:认证应用 KEY

[图 15. Extension access 配置信息]

10.4 账户 Account 管理扩展

1. 点击进入账户扩展管理。

[图 16.账户扩展管理入口]

2. 添加 Extensions。

[图 17. 添加 Extensions]

3. 选择要添加的扩展。

[图 18. 选择扩展]

4. 创建 extension。

[图 19. 创建 extension]

5. 确认 extension 配置。

[图 20. 确认 extension 配置]

6. 查看扩展状态。

[图 21. 扩展状态]

11. 桌面端登录演示

1. 选择 Continue with SSO 进行登录。

[图 22. 选择 Continue with SSO]

2. 输入Amazon Quick 账户名称(前面账户创建出来的名称)。

[图 23. 输入 Quick 账户名称]

3. 跳转统一认证。

[图 24. 跳转统一认证]

12. 官方参考

➡️ 下一步行动:

相关产品:

  • Amazon Quick — 人工智能助手,用于研究、业务洞察、自动化和无代码应用程序构建
  • Amazon IAM — 身份管理和访问权限
  • Amazon QuickSight — 高速业务分析服务

相关文章:

*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。

本篇作者

邓文杰

亚马逊云科技客户解决方案经理,Edge TFC成员,在亚马逊云科技主要支持游戏和零售等行业的用户。专注于促进亚马逊云科技用户解决方案落地,提升上云体验,帮助用户实现自身的业务价值。

陈映初

亚马逊云科技解决方案架构师,专注于 Agentic AI 与生成式 AI 应用在 AWS 上的架构设计与落地实践。拥有 12 年以上软件研发经验,精通前后端全栈开发,兼具 DevOps 实战经验。Apache DevLake(ASF 顶级项目)PMC 成员。

廖良茂

亚马逊云科技解决方案架构师,负责基于亚马逊云科技云计算方案架构的咨询和设计,在国内推广亚马逊云科技云平台技术和解决方案,目前专注于韧性和数据库领域。在加入亚马逊云科技之前就职于微软、甲骨文公司,熟悉数据库、备份和容灾等解决方案

李一鸣

现任亚马逊云科技(AWS)客户解决方案经理(Customer Solutions Manager),常驻中国上海。凭借多年深耕医疗健康与生命科学(HCLS)及零售行业的丰富经验,他长期为客户提供专业咨询,协助其加速云价值实现、最大化人工智能投资回报。他致力于帮助各类组织成功采用并规模化应用人工智能,切实推动可衡量的业务成果落地。


AWS 架构师中心:云端创新的引领者

探索 AWS 架构师中心,获取经实战验证的最佳实践与架构指南,助您高效构建安全、可靠的云上应用