# @aws-blocks/bb-auth-oidc 中文文档

规范地址：https://npmcn.com/package/%40aws-blocks/bb-auth-oidc/

版本：0\.3\.0
npm 元数据更新时间：2026-11-02T10:25:56.078Z
中文译文更新时间：2026-11-07T13:32:16.868Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40aws-blocks/bb-auth-oidc
原文对照：https://npmcn.com/package/%40aws-blocks/bb-auth-oidc/?lang=original
项目主页：https://github.com/aws-devtools-labs/aws-blocks/tree/main/packages/bb-auth-oidc#readme
源码仓库：https://github.com/aws-devtools-labs/aws-blocks

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：1 MB，129 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：9 个
- peer 依赖：constructs ^10\.6\.0，aws-cdk-lib ^2\.257\.0
- 首次发布：2026-06-15T23:39:31.199Z
- 最新版本发布：2026-11-02T10:25:55.703Z
- 近 30 天下载量：63561（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：17（近 12 个月 17 个）

## 中文简介

AWS Blocks应用程序的OIDC登录入门. 会话是长寿并透明地刷新的——用户在 IdP ~ 1- hour ID sident TTL 之前保持签名,而退出则实际上使会话服务器端无效. 与Google, GitHub, Okta, Auth0合作,

## 安装

```sh
npm install @aws-blocks/bb-auth-oidc
```

也可以使用：`pnpm add @aws-blocks/bb-auth-oidc`、`yarn add @aws-blocks/bb-auth-oidc`、`bun add @aws-blocks/bb-auth-oidc`

## README

# `@aws-blocks/bb-auth-oidc`

AWS Blocks应用程序的OIDC登录入门. 会话是长寿并透明地刷新的——用户在 IdP ~ 1- hour ID sident TTL 之前保持签名,而退出则实际上使会话服务器端无效. 与Google,GitHub,Okta,Auth0,Microsoft Entra以及任何OIDC兼容的身份提供商合作. 指向现有的 Cognito 用户库也是一条支持的路径 .

> 设计与模拟等价细节 : [设计](https://npmcn.com/package/%40aws-blocks/bb-auth-oidc/DESIGN.md)

## 快速启动

后端( E)`aws-blocks/index.ts`:

```typescript
import { Scope, ApiNamespace } from '@aws-blocks/core';
import { KVStore } from '@aws-blocks/bb-kv-store';
import { AppSetting } from '@aws-blocks/bb-app-setting';
import { AuthOIDC, google } from '@aws-blocks/bb-auth-oidc';

const app = new Scope('quickstart');

const profiles = new KVStore<{ email: string | null; name: string | null }>(app, 'profiles');

const googleClientId = new AppSetting(app, 'google-client-id', { secret: true });
const googleSecret   = new AppSetting(app, 'google-client-secret', { secret: true });

const auth = new AuthOIDC(app, 'auth', {
    providers: [
        google({
            clientId:     () => googleClientId.get(),
            clientSecret: () => googleSecret.get(),
        }),
    ],
    onSignIn: async (user) => {
        await profiles.put(user.userId, { email: user.email, name: user.name });
    },
});

export const api = new ApiNamespace(scope, 'api', (ctx) => ({
    async me() {
        const user = await auth.requireAuth(ctx);
        return profiles.get(user.userId);
    },
}));

export const authApi = auth.createApi();
```

浏览器 :

```tsx
import { authApi } from 'aws-blocks';

const auth = await authApi.getClient();

<button onClick={() => auth.signIn('google')}>Sign in with Google</button>
<button onClick={() => auth.signOut()}>Sign out</button>
```

`signIn()` 运行客户端启动的 PKCE 流程: 它导航到 IDP, 返回时, 页面调用 `auth.handleRedirectCallback()` 完成交换。 默认情况下, IDP 重定向到 **当前页面**对于在专用线路上处理回调的SPA,通过 `redirectPath`数字 :

```tsx
// IdP returns to /auth-return; that page calls handleRedirectCallback()
auth.signIn('google', { redirectPath: '/auth-return' });
```

`redirectPath` 成为 OAuth `redirect_uri`,所以它必须是页 您的前端服务 **财务报告和审定财务报表** a 重新定向在提供者注册的 URI( stub IdP 接受任何 HTTPS 或 localhost URL, 所以 local/ sandbox 不需要注册) .

`createApi()` 揭露国家机器API—— `getAuthState()` 财务报告和审定财务报表 `setAuthState()` 双向返回 [`AuthState`](https://npmcn.com/package/%40aws-blocks/auth-common/README.md#authstate)。 。 。 . `AuthOIDC` 不再导出该类型; 从 `@aws-blocks/auth-common`此软件包的直接依赖性 :

```typescript
import type { AuthState } from '@aws-blocks/auth-common';
```

### 重新在登录( React SPA) 上提交用户界面

`signIn()` 财务报告和审定财务报表 `handleRedirectCallback()` 驱动 OIDC 交换; 将您的应用程序完成后重新发送, 订阅认证状态更改 。 有两个辅助钩:

-   **`auth.onAuthStateChange(cb)`** ——这个OIDC客户端自己的听众. 启用此客户端实例 `signIn()` 开球,成功 `handleRedirectCallback()`,然后继续 `signOut()`。 。 。 .
-   **`onAuthChange(authApi, cb)`** 从 `@aws-blocks/blocks/ui` ——共享 `@aws-blocks/auth-common` 背书订阅 `<AuthenticatedContent>`它更新 **跨组件和浏览器标签**。 。 。 .

一个成功的 `handleRedirectCallback()` 通知 **两者**:它叫当地听众 _财务报告和审定财务报表_ 桥接入 `@aws-blocks/auth-common` 拨打 `broadcastAuthChange(user)` 为了你,所以 `onAuthChange` 消费者(和 `<AuthenticatedContent>`)在客户端-PKCE登录上重新签名——而不仅仅是在服务器启动的登录上. 你不打电话 `broadcastAuthChange()` 自己签入;客户有。 因为它点燃了两个, 一个组件订阅 **两者** `auth.onAuthStateChange()` 财务报告和审定财务报表 `onAuthChange()` 将会在单个客户端- PKCE 的签名上两次引用它的处理器 —— 如果您的处理器是同能的, 但偏好每个组件一个.

```tsx
import { useEffect, useState } from 'react';
import { authApi } from 'aws-blocks';
import { onAuthChange } from '@aws-blocks/blocks/ui';

// Dedicated callback route (e.g. /auth-return) — completes the PKCE exchange.
export function AuthCallback() {
    useEffect(() => {
        authApi.getClient()
            .then((auth) => auth.handleRedirectCallback())
            .catch((err) => console.error('OIDC callback failed', err));
    }, []);
    return <p>Signing you in…</p>;
}

// Any component — re-renders when auth state changes (this tab + other tabs).
export function useUser() {
    const [user, setUser] = useState(null);
    // onAuthChange returns an unsubscribe fn; returning it cleans up on unmount.
    useEffect(() => onAuthChange(authApi, setUser), []);
    return user;
}

export function SignInButton() {
    const user = useUser();
    if (user) return <span>Hi, {user.username}</span>;
    return (
        <button onClick={async () => (await authApi.getClient()).signIn('google')}>
            Sign in with Google
        </button>
    );
}
```

`onAuthChange` 引用您的回电 **同步** 与当前用户(从共享缓存中)一起进行第一次涂料,然后在认证状态改变时再次返回,并返回一个未订阅的函数——从中返回 `useEffect` 电线清理。 同样的广播也到达了其他开放的分页,因此在一个分页中签入(或出)更新了全部. 不过,在以上专门召回模式中, `handleRedirectCallback()` _广播_ 而不是刺激共享缓存,所以 `useUser()` 该挂载 **之后** 发射的回调从缓存误差开始: 它画过一次签名出局, 然后在它自己的自动同步时自行校正 `getAuthState()` 解决——一种预期的瞬间闪出.

### 要使用的流量

-   **服务器启动** (单位:千美元)`GET /aws-blocks/auth/signin/<provider>` - 链接或 `<Authenticator>` 按钮:后端拥有回调和设置会话 cookie。 这是默认 **原产地** apps(前端和API一个来源:本地dev,单部署来源,或沙盒前门).
-   **客户端 PKCE** (单位:千美元)`auth.signIn()` 上面):浏览器处理回调和 POST 到 `/aws-blocks/auth/exchange`。用于 SPA, 当前端和 API 打开时需要 **不同来源**。同源SPA也可以使用,但必须通过前端 `redirectPath` (默认的当前页面重定向可避免后端) `/aws-blocks/auth/callback`) (中文(简体) ).
-   **中继** (本土/CLI):见 [本地登录](https://npmcn.com/package/%40aws-blocks/bb-auth-oidc/#readme-relay-flow-for-native-sign-in)。 。 。 .

### 服务器启动的登录`GET /aws-blocks/auth/signin/<provider>`(中文(简体) )

每个配置的提供者一个路由,由块挂起. 它根本不需要客户端代码: 没有PKCE验证器,没有 `getClient()`,没有回调组件。 浏览器指向它,整个流量运行在服务器侧方向:

```html
<a href="/aws-blocks/auth/signin/google">Sign in with Google</a>
```

1.  `GET /aws-blocks/auth/signin/google` → `302` 到 IDP 授权的 URL,加 a `Set-Cookie` 与寿命短的待发-自动饼干(它携带PKCE验证器和nace服务器侧).
2.  IDP 认证用户并重定向到 `GET /aws-blocks/auth/callback?code=…&state=…`。 。 。 .
3.  回调看到待发饼干,交换代码,运行 `onSignIn`,设置会话饼干,以及 `302`升为 `postSignInPath` (默认) `/`) (中文(简体) ).

供应商名称是 URL 编码,所以一个供应商呼叫 `my provider` 处于 `/aws-blocks/auth/signin/my%20provider`。因为每个 _配置_ 提供者,一个你从未申报过的名字 根本没有路由 `404`s; 数据 `ProviderNotConfiguredException` 用于未知提供者的表面 `getSignInUrl()` (RPC路径),不是从这里。 构建授权 URL 失败, 例如 IDP 发现返回 JSON (`{"error":"...","name":"..."}`)与错误的状态而不是方向.

这是该区块自己的集成测试驱动器的路径,因为它是可脚本的结尾,除了结束 `fetch` 和手动重定向:

```bash
# 1. kickoff, keeping the pending-auth cookie
curl -i -c cookies.txt http://localhost:3000/aws-blocks/auth/signin/google
# → 302 Location: /aws-blocks/auth/idp/google/authorize?...   (stubIdp provider)

# 2. follow the IdP redirect (stubIdp auto-approves)
curl -i -b cookies.txt -c cookies.txt "<authorize URL from step 1>"
# → 302 Location: /aws-blocks/auth/callback?code=...&state=...

# 3. the callback sets the session cookie and sends you back to the app
curl -i -b cookies.txt -c cookies.txt "<callback URL from step 2>"
# → 302 Location: /   + Set-Cookie: oidc_<instance>_session=...

# 4. the session cookie now authenticates RPC calls
curl -b cookies.txt -X POST http://localhost:3000/aws-blocks/api \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","method":"api.whoami","params":[],"id":1}'
```

上面的每一项答复都是断言的,而不仅仅是描述的. `test-apps/comprehensive/test/oidc-auth.test.ts` 同一三个方向方向 `full sign-in flow via HTTP redirects — google` (并再次反对OIDC供应商) `corporate` 变量),检查 `302` 链条、待发和会话饼干、 `Location: /` 那个 `postSignInPath` 生产,以及随后经过认证的RPC呼叫。 这个 `404`s 对于未申报的提供者和 `GET` 签出路由上在同一文件中坚持; 默认 `postSignInPath` 编辑 `%20` 供应商编码由 `path configuration` 测试 `packages/bb-auth-oidc/src/index.test.ts`。 。 。 .

用于服务器发送和零JS页面,用于 `<a>`\- 登入,并进行整合测试。 联系客户端 PKCE API 而不是前端和 API 不同来源,或者当 SPA 想要留在自己的路线上并自行处理回调时. 两种流都写同一个会话饼干,所以 `requireAuth` 编号 : `getAuthState` 不管哪个用户签了名 签出是同一路线 无论是哪种方式: `POST /aws-blocks/auth/signout` 联合国 `GET` 通常通过 `auth.signOut()`。 。 。 .

## BB条款

添加中 `AuthOIDC` 对您的应用条款:

-   个人行为 `RawRoute` 处理者 : `/aws-blocks/auth/callback`, (中文(简体) ), `/aws-blocks/auth/signout` (只通过电话) `auth.signOut()`; 获取返回 404 `/aws-blocks/auth/exchange` (针对客户发起的PCE)
-   提供方路线: `/aws-blocks/auth/signin/<provider>` (服务器启动的起跑)和 `/aws-blocks/auth/authorize-params/<provider>` (客户发起的PKCE发现;也接受POST用于中继流)
-   用于 cookie 签名的单一 SSM 安全结构参数
-   一个 DynamoDB 表格(通过 `KVStore`用于会话存储

所有路线来自 `callbackPath` (默认) `/aws-blocks/auth/callback`) (中文(简体) ). 习惯 `callbackPath` 将整个设置一起移动——例如. `callbackPath: '/aws-blocks/auth/real/callback'` 开球 `/aws-blocks/auth/real/signin/<provider>`交换 `/aws-blocks/auth/real/exchange`,等等。 (笑声).

会话商店持有刷新令牌并核实债权. 饼干带有一个不透明的会话ID 键入本表. 一个闲置的DynamoDB台的成本为~0.25美元/月,会话通过自动刷新活到ID符~1小时TTL之外.

## 饼干和会议

会话饼干是一种 `HttpOnly`,在服务器侧会话存储处签名指针。 默认是 `SameSite=Lax` (单位:千美元) `Secure` 在 AWS 运行时; 在模拟运行时在 plain-HTTP localhost 上投放), 这对同源应用程序和本地 dev 代理正确 .

设定 `crossDomain: true` 只在前端和API从 **不同的可注册域** 在生产中(例如Vercel上的前端,AWS上的API). 这样一来,会话和待发饼干就换成 `SameSite=None; Secure; Partitioned` 因此,他们经受住了跨地点的要求:

```typescript
const auth = new AuthOIDC(app, 'auth', {
    providers: [google({ clientId, clientSecret })],
    crossDomain: true,
});
```

## 核心概念

### `userId = ${iss}:${sub}`

平稳的人类/IdP。 在自己的表格中将此作为外国密钥使用 。 与 Google 和 GitHub 签约 `userId`s 对于同一个人类——身份链接是应用码关注,而不是BB.

### 生命周期钩

-   `onSignIn(user, ctx)` 每一次成功登机都要开火 抛出以失败登录( 回调回500分,没有饼干).
-   `onSignOut(user, ctx)` ——明确签出点火. 抛掷被记录,但不会挡住饼干.

### 会话管理

会话比IDP的ID代号活得快——用户不会每小时被踢出. BB 提供了它需要的会话存储自动( 无配置) , 到期时刷新背景中的访问符, 并通过比较和扫描协议协调容器之间的同步刷新, 这样一个请求破裂不会堆积在 IDP 的符号端点上 。 签出会话服务器端无效, 而不仅仅是客户端端 .

### 提供者助手

-   `google({ clientId, clientSecret, scopes? })` - 税务总局.
-   `github({ clientId, clientSecret, scopes? })` —— OAuth 2. 0(无ID令牌;用户info获取了+自动映射).
-   `customOidc({ name, issuerUrl, clientId, clientSecret, scopes?, attributeMapping? })` ——任何OIDC发行商(Okta, Auth0, Cognitto User Pools, Entra).
-   `customOauth2({ name, authUrl, tokenUrl, userInfoUrl, clientId, clientSecret, scopes, mapClaims })` 赤出OAuth 2.0,配有客户提供的索赔映射仪.
-   `stubIdp({ name })` ——一个真实的,在流程中的OIDC供应商,用于零配置本地登录. 有定型用户的自动审批,不需要真实的资质,下线工作. 明确的选入: 它只处理向您声明的提供者的登录 `stubIdp()`永远不要以沉默代替真正的供应商 也是你用来换E2E的 仅部署当地和沙箱。 见 [地方发展](https://npmcn.com/package/%40aws-blocks/bb-auth-oidc/#readme-local-development)。 。 。 .

### 指向已有的 Cognto 用户库

```typescript
customOidc({
    name: 'cognito',
    issuerUrl: 'https://cognito-idp.us-east-1.amazonaws.com/us-east-1_abc123',
    clientId:     () => poolClientId.get(),
    clientSecret: () => poolSecret.get(),
});
```

## 地方发展

配置给其提供者的谈话 **每个环境中的真正IPP,包括: `npm run dev`**A级 `google()` 供应商点击本地真实的谷歌; a `customOidc({ issuerUrl })` 提供商在本地攻击发行商.

启动时, 每个提供者记录它是如何解决的, 因此路径永远不会沉默 :

```
[auth] provider "google" → https://accounts.google.com (real IdP)
[auth] provider "corporate" → AWS Blocks stub IdP (local sign-in, no real credentials)
```

### 在当地运行一个真正的提供者

在任何环境下,你都承担同样的一次性设置 IDP 需要:

-   **重定向URI / HTTPS.** 注册本地召回( N)`http://localhost:3000/aws-blocks/auth/callback`)与"IDP". 谷歌接受 `http://localhost`; Okta, Auth0, Entra, and GitHub 需要在其控制台中添加本地主机回调.
-   **秘密存在.** 这个 `clientId` 编号 : `clientSecret` 关闭必须满足以下实际价值: `.bb-data`如果证书不能解决, 注册失败 `ProviderNotConfigured` 出错——没有沉默倒向假用户.
-   **连通.** 签入后给IDP打电话,所以它需要网络访问.

### 沙盒( E)`npm run sandbox`)和基于方向的登录

在沙盒中,前端在当地服务,而后端作为部署的API Gateway + Lambda运行. 针对 **前门** 来源( 来源)`http://localhost:3000/aws-blocks/auth/callback`),与 `npm run dev` - 不是说 `execute-api` URL (中文(简体) ). 然后签入后以本地方式完成;不需要额外的配置.

### 零配置本地登录 `stubIdp()`

当你不希望任何这种设置——下线,决定性,没有证书——使用时 `stubIdp()`数字 :

```typescript
import { AuthOIDC, google, stubIdp, getDeploymentType } from '@aws-blocks/blocks';

const providers = getDeploymentType() === 'production'
    ? [google({ clientId, clientSecret })]
    : [stubIdp({ name: 'google' })];

const auth = new AuthOIDC(app, 'auth', { providers });
```

`stubIdp()` 限于地方发展`npm run dev`)和沙盒(`npm run sandbox`() 部署:当任何其他部署配置 a时,合成失败 `stubIdp()` 提供商和部署的计算器 只在沙盒中服务 IdP 线路. `getDeploymentType()` 返回时 `'local'`, (中文(简体) ), `'sandbox'`,或 `'production'` 并在合成和运行时报告相同值,因此选择提供方与它保持一致。 在合成时,它报告后端模块中的部署类型(一旦) `BlocksStack` 编号 : `BlocksBackend` `create()` 已开始导入;运行时它报告已部署的计算。 区块配置和上下文不存在的地方(在 `create()`,在普通脚本中,或者在非Brocks计算上)返回 `'local'`,因此从后端模块中调用它,如上面的例子。 根茎发出的授权代码 以每次部署的密钥签名 从实例的 cookie-signing secret.

`stubIdp()` 是一个真实的,符合规格的OIDC供应商,在进程中运行:RS256用一个真实的键盘签名,一个JWKS端点,OIDC发现,与PKCE的授权码授予,刷新-托肯旋转,以及RFC 7009撤销. 引擎运行相同的发现+验证它针对真实的IDP使用的代码路径. 它只是标出决定性的本地用户,而不是认证一个人. 它是一个明确的选择 坐在你真正的提供者旁边 `providers` 数组——它从不默默地替换一个。 它也是你用来做E2E的.

你可以自由地混合两者;代码是每个环境中真理的来源:

```typescript
providers: [
    google({ clientId, clientSecret }),  // real Google everywhere, incl. local
    // AWS Blocks stub for local and sandbox; a real provider in production
    getDeploymentType() === 'production'
        ? customOidc({ name: 'corporate', issuerUrl, clientId: corpClientId, clientSecret: corpClientSecret })
        : stubIdp({ name: 'corporate' }),
]
```

#### 登录屏幕和 `onAuthorize`

默认, `stubIdp()` 为交互式取账员服务 `/authorize` 端点——您看到一个真正的登录屏幕并选择一个用户,形状与签名相同 在一个主机IP. `onAuthorize` 决定授权请求的后果 土地:

```typescript
stubIdp({
    name: 'google',
    // return a user    → sign in as them, skip the screen
    // return undefined → show the interactive login screen (the default)
    // throw            → deny the authorize (negative-path testing)
    onAuthorize: (req) => req.users.find((u) => u.email === req.loginHint),
})
```

`req` 实值 `{ provider, scopes, redirectUri, state, nonce, loginHint?, users }`时 `users` 是本地身份目录,并且 `loginHint` 是标准 OIDC `login_hint` 一、导 言 对于E2E(没有人可以点击),自动认可为第一个用户:

```typescript
stubIdp({ name: 'google', onAuthorize: (req) => req.users[0] })
```

#### 当地身份`users.json`(中文(简体) )

默认情况下, 目录是单一的决定性用户 (单位:千美元)`stub-<provider>-user`) (中文(简体) ). 要定义多个本地身份,请放弃一个 `users.json` 实例模拟数据目录中的数组 (单位:千美元)`.bb-data/<auth-id>/users.json`:

```jsonc
[
    { "sub": "alice", "email": "alice@example.com", "name": "Alice" },
    { "sub": "bob",   "email": "bob@example.com",   "name": "Bob" }
]
```

这些用户充电 `req.users` 和登录屏幕的取账器。 没有 文件,使用单个默认用户,所以已有的应用程序不变.

## 错误分类

所有错误都跟着 `<Name>Exception` 命名公约和与 `isBlocksError()`。 。 。 .

```typescript
import { isBlocksError } from '@aws-blocks/core';
import { AuthOIDCErrors } from '@aws-blocks/bb-auth-oidc';

try { await auth.requireAuth(ctx); }
catch (e) {
    if (isBlocksError(e, AuthOIDCErrors.NotAuthenticated)) return redirectToSignIn();
    throw e;
}
```

`NotAuthenticated`, (中文(简体) ), `TokenExpired`, (中文(简体) ), `InvalidState`, (中文(简体) ), `InvalidCallback`, (中文(简体) ), `ProviderNotConfigured`, (中文(简体) ), `IdpError`, (中文(简体) ), `InvalidRelay`, (中文(简体) ), `SdkOutdated`。 。 。 .

`SdkOutdated` 表面从 `/aws-blocks/auth/callback` 当一个中继状态信封版本未识别时——客户端SDK比后端预期的要老并应当更新.

与密码提供者不同,OIDC的登录是浏览器重定向到IDP,所以没有 `setAuthState` 错分路径在这里 – 对必须的 API 错误作出反应 `isBlocksError` 如上所示。 (对于返回的`AuthState` 密码提供者的平话,见 `hasAuthError` 输入 `bb-auth-basic` 编号 : `bb-auth-cognito` 读取。 )

## 认知调解联合会

将 OIDC 流程指定为 Cognitto 用户池 。 Cognoto处理PKCE, 象征性的核查, MOFA, 和野蛮力量的保护。 你的Lambda只交换代码 并读会话.

`cognitoFederated()` 带 `AppSetting` idP 证书的例子(不是关闭)。 IdP 在用户库注册 : **部署时间自定义资源**: Lambda在部署时通过SDK读取并解密这些安全 String参数,并呼叫Cognito's `CreateIdentityProvider`.(当地人 `AWS::Cognito::UserPoolIdentityProvider` 无法使用资源 — CloudFormation 拒绝 `{{resolve:ssm-secure}}` 它将需要在 `ProviderDetails`. ) (中文(简体) ). 因此,证书值从未出现在CloudFormation模板中.

**设定证书值 .** A 类 `secret: true` `AppSetting` 是一个 SSM 安全串 `/<appSetting.fullId>` —— 说 **没有** aWS 秘密管理器条目,所以 `blocks secret` CLI(管理机密管理器)在此不适用. 直接或通过 `AppSetting`运行时间 `put()`数字 :

```bash
aws ssm put-parameter --name /<fullId> --type SecureString --value '<google-client-secret>' --overwrite
```

在第一次部署时, 框架种子每个带有随机占位符的秘密参数, 因此, 如果您在设定占位符的真实值之前就部署 IDP 注册符, 而签名失败于提供者 —— 设定真实值并重新部署 。 注册重新读取每个 `cdk deploy`,因此设置或旋转证书在下一次部署时生效(每次部署更新时显示的自定义资源;更新是一元数据).

```typescript
import { AuthOIDC, cognitoFederated } from '@aws-blocks/bb-auth-oidc';
import { AppSetting } from '@aws-blocks/bb-app-setting';

const googleClientId = new AppSetting(app, 'google-client-id', { secret: true });
const googleSecret   = new AppSetting(app, 'google-client-secret', { secret: true });

const auth = new AuthOIDC(app, 'auth', {
    providers: [
        cognitoFederated({
            name: 'google',
            identityProvider: 'Google',
            cognitoDomain: 'myapp',
            region: 'us-east-1',
            clientId:     googleClientId,
            clientSecret: googleSecret,
        }),
    ],
});
```

用户身份证在引擎开关之间是稳定的—— `userId = ${iss}:${sub}` 来源于原始的 IdP 身份(取自 Cognito's `identities` 并非来自科尼托的内部UUID.

CDK层自动提供 Cognitto 用户池, App 客户端, 域名, 以及身份提供者注册 。 不需要Cognitto CDK代码 .

### 回调和登录 URL

应用程序客户端的回调/登录 URL 为您注册: 应用程序的公有来源( 当是时) `https://`)和 API 网关 URL,每个网关 `/aws-blocks/auth/callback`附加时 `http://localhost:3000` 在沙盒模式下。 认知拒绝非本地主机 `http://` 调用回调 URL, 因此一个 plain- http 应用程序源头会被一个 `PlainHttpPublicOrigin` 合成警告.

使用 `additionalCallbackUrls` 编号 : `additionalLogoutUrls` 对于无法在合成时得到的重定向目标:

-   浏览器 PKCE SPA 重定向页面(SPA 页面 URL是应用特有);
-   本地应用自定义 URI 计划( 例如 ). `myapp://auth/callback`用作 `redirect_uri` (a) 客户直接发起的PKCE登录(`signIn(provider, { redirectPath })`()—— [中继流](https://npmcn.com/package/%40aws-blocks/bb-auth-oidc/#readme-relay-flow-for-native-sign-in) 不需要,因为 `redirect_uri` 是后端的 HTTPS 调用, 自定义方案只是 `relayTo` 目标;
-   自定义域名超出主域名(只有主应用程序来源自动注册);
-   位于端口以外的沙盒 dev 服务器 `3000`。 。 。 .

```typescript
cognitoFederated({
    name: 'google',
    identityProvider: 'Google',
    cognitoDomain: 'myapp',
    region: 'us-east-1',
    clientId:     googleClientId,
    clientSecret: googleSecret,
    additionalCallbackUrls: ['https://www.example.com/aws-blocks/auth/callback', 'myapp://auth/callback'],
    additionalLogoutUrls:   ['https://www.example.com/'],
}),
```

来自每个 `cognitoFederated()` 提供商被合并到一个共享的应用客户端并去复制;每个URL通过合成验证.

签名清除会话并取消刷新会话; 它不会通过 Cognito 的主机重定向 `/logout` 端点,所以登出 URL 注册为完整,但不为当前出站路径所使用.

**升级.** 应用程序客户端的回调和登录URL现在由Building Block管理. 在 CDK 外的 Cognitto 应用客户端中添加的 URL( 例如, 在控制台中作为工作绕行) 在下次部署时被替换—— 重新添加您仍然需要的任何内容 `additionalCallbackUrls` 编号 : `additionalLogoutUrls`。 。 。 .

当地 dev(`npm run dev`, (中文(简体) ), `cognitoFederated` 实值 **不详** - 认知联合会需要部署的用户库+应用程序客户证书,这些证书只有在 `npm run sandbox` 编号 : `npm run deploy`. 声明提供者不会屏蔽本地的dev,但一个认知-federed sign-in在明确消息下迅速失败. 对于本地登录,请添加一个明示 `stubIdp({ name })` 提供者(参见 [地方发展](https://npmcn.com/package/%40aws-blocks/bb-auth-oidc/#readme-local-development));在沙盒/部署中锻炼真正的Cognitto流.

### 何时使用Cognitto Federation vs 自办

-   **自办** (单位:千美元)`google()`, (中文(简体) ), `customOidc()`:更简单,更便宜,更快的部署. 你拥有安全表面.
-   **认知中介** (单位:千美元)`cognitoFederated()`: 管理安全(SOC 2,HIPAA合格),MFA关于社会签注,适应性认证,畜力保护. 添加 Cognitto MAU 定价 .

## 本地客户端( iOS, Android, 桌面)

默认情况下,会话是 cookie- only – 符号永远不会到达客户端. 这是网络应用的正确选择. 本地客户没有IP理解的饼干店,所以他们需要无记名标志.

启用 `allowBearerAuth: true` 获取 :

-   `POST /aws-blocks/auth/exchange` 返回时 `{ user, accessToken, refreshToken, expiresIn }`
-   `Authorization: Bearer <accessToken>` 作为会话饼干的替代品
-   `POST /aws-blocks/auth/refresh` 端点被挂载用于更新符号

```typescript
const auth = new AuthOIDC(app, 'auth', {
    providers: [google({ clientId, clientSecret })],
    allowBearerAuth: true,
});
```

客户端在OS keychain(iOS Keychain,Android Keystore,OS-native Credititive store)中存储了令牌,并将刷新令牌发布到 `/aws-blocks/auth/refresh` 当访问符过期时 :

```typescript
// Native client — pseudo-code
const { accessToken, refreshToken, expiresIn } = await fetch('/aws-blocks/auth/refresh', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ refreshToken: stored.refreshToken, provider: 'google' }),
}).then(r => r.json());

await keychain.save({ accessToken, refreshToken, expiresIn });
```

**安全权衡.** 启用此功能可以向客户端运行时间显示符号 。 对于网络应用,更喜欢默认的 cookie- only 模式,因此指使永远不会活在JavaScript的可及性中.

### 本地登录的中继流量

Major IdPs (Google, Microsoft Entra, Okta, Auth0) 拒绝自定义化学重定向 URI(`myapp://auth/callback`登记时。 本地客户不能直接向IDP注册他们的应用计划.

后端的 HTTPS 调用保留注册于 IDP. 在 IdP 返回后,后端302s 给本地应用的自定义-scheme URI,并附有认证码. PKCE保留客户端,IDP只见过HTTPS URL.

通过声明启用 `allowedRelayOrigins`数字 :

```typescript
import { AuthOIDC, google, relayOrigin } from '@aws-blocks/bb-auth-oidc';

const auth = new AuthOIDC(app, 'auth', {
    providers: [google({ clientId, clientSecret })],
    allowBearerAuth: true,
    allowedRelayOrigins: [
        relayOrigin('myapp://auth'),           // Android/iOS custom scheme
        relayOrigin('https://oauth.myapp.com'), // off-origin HTTPS helper (optional)
    ],
});
```

**本地 SDK 如何驱动流量 :**

1.  邮政 `/aws-blocks/auth/authorize-params/<provider>` 与 `{ csrf, relayTo: 'myapp://auth', appState? }` — 服务器返回 `{ authorizeUrl, clientId, scopes, state, nonce }`
2.  在系统浏览器中打开 IDP 授权 URL `redirect_uri` 设置到 **备份** HTTPS 回调( 不是自定义方案)
3.  IDP 的用户认证 ~ IDP 重定向到 `/aws-blocks/auth/callback?code=...&state=...`
4.  后端解码已签名的状态信封,查看中继目标,并发布 `302 Location: myapp://auth?code=...&state=...`
5.  OS 将自定义化学 URI 运行到本地应用程序
6.  应用程序摘要 `code` + 键 `state`,核实中国SRF,和POST `/aws-blocks/auth/exchange` + PKCE 验证器 + 得到 `{ user, accessToken, refreshToken, expiresIn }`

**隐含津贴** (无) `relayOrigin()` 需要的条目:

-   **循环** —— 说 `http://127.0.0.1:<any-port>` 财务报告和审定财务报表 `http://[::1]:<any-port>`. 覆盖使用 RFC 8252 §7.3 麻黄口图案的 CLI 工具.
-   **同一来源** ——后端自己的URL.

**外观.** 在方案 + 主机 + (如果被绑住, 端口) 上实现匹配 。 实际路径 `relayTo` 值通过302——允许列表不模式匹配路径保存.

**处理错误 .** 如果IDP返回出错(例如用户取消同意),后端通过中继转发: `302 Location: myapp://auth?error=access_denied&error_description=...&state=...`。本地 SDK 应当检查 `error` 在寻找之前 `code`。 。 。 .

## 常见问题

### @aws-blocks/bb-auth-oidc 是什么？

AWS Blocks应用程序的OIDC登录入门\. 会话是长寿并透明地刷新的——用户在 IdP ~ 1- hour ID sident TTL 之前保持签名,而退出则实际上使会话服务器端无效\. 与Google, GitHub, Okta, Auth0合作,

### 如何安装 @aws-blocks/bb-auth-oidc？

在项目目录运行 npm install @aws-blocks/bb-auth-oidc，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：constructs（^10\.6\.0）、aws-cdk-lib（^2\.257\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @aws-blocks/bb-auth-oidc 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @aws-blocks/bb-auth-oidc 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @aws-blocks/bb-auth-oidc 可以商用吗？

@aws-blocks/bb-auth-oidc 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @aws-blocks/bb-auth-oidc 的下载量有多少？

根据 npm 官方下载统计，@aws-blocks/bb-auth-oidc 在 2026/10/07 – 2026/11/05 这 30 天内被下载 63,561 次，日均约 2,119 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @aws-blocks/bb-auth-oidc 还在维护吗？

最新版本 0\.3\.0 发布于 2026/11/02（5 天前）；至今共发布 17 个版本，其中过去 12 个月发布了 17 个；首次发布于 2026/06/16。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

