@aws-blocks/bb-auth-oidc
AWS Blocks应用程序的OIDC登录入门. 会话是长寿并透明地刷新的——用户在 IdP ~ 1- hour ID sident TTL 之前保持签名,而退出则实际上使会话服务器端无效. 与Google,GitHub,Okta,Auth0,Microsoft Entra以及任何OIDC兼容的身份提供商合作. 指向现有的 Cognito 用户库也是一条支持的路径 .
设计与模拟等价细节 : 设计
快速启动
后端( E)aws-blocks/index.ts:
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();
浏览器 :
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数字 :
// 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。 。 。 . AuthOIDC 不再导出该类型; 从 @aws-blocks/auth-common此软件包的直接依赖性 :
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 的签名上两次引用它的处理器 —— 如果您的处理器是同能的, 但偏好每个组件一个.
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):见 本地登录。 。 。 .
服务器启动的登录GET /aws-blocks/auth/signin/<provider>(中文(简体) )
每个配置的提供者一个路由,由块挂起. 它根本不需要客户端代码: 没有PKCE验证器,没有 getClient(),没有回调组件。 浏览器指向它,整个流量运行在服务器侧方向:
<a href="/aws-blocks/auth/signin/google">Sign in with Google</a>
GET /aws-blocks/auth/signin/google→302到 IDP 授权的 URL,加 aSet-Cookie与寿命短的待发-自动饼干(它携带PKCE验证器和nace服务器侧).- IDP 认证用户并重定向到
GET /aws-blocks/auth/callback?code=…&state=…。 。 。 . - 回调看到待发饼干,交换代码,运行
onSignIn,设置会话饼干,以及302升为postSignInPath(默认)/) (中文(简体) ).
供应商名称是 URL 编码,所以一个供应商呼叫 my provider 处于 /aws-blocks/auth/signin/my%20provider。因为每个 配置 提供者,一个你从未申报过的名字 根本没有路由 404s; 数据 ProviderNotConfiguredException 用于未知提供者的表面 getSignInUrl() (RPC路径),不是从这里。 构建授权 URL 失败, 例如 IDP 发现返回 JSON ({"error":"...","name":"..."})与错误的状态而不是方向.
这是该区块自己的集成测试驱动器的路径,因为它是可脚本的结尾,除了结束 fetch 和手动重定向:
# 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呼叫。 这个 404s 对于未申报的提供者和 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 因此,他们经受住了跨地点的要求:
const auth = new AuthOIDC(app, 'auth', {
providers: [google({ clientId, clientSecret })],
crossDomain: true,
});
核心概念
userId = ${iss}:${sub}
平稳的人类/IdP。 在自己的表格中将此作为外国密钥使用 。 与 Google 和 GitHub 签约 userIds 对于同一个人类——身份链接是应用码关注,而不是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的 仅部署当地和沙箱。 见 地方发展。 。 。 .
指向已有的 Cognto 用户库
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 devA级 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()数字 :
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的.
你可以自由地混合两者;代码是每个环境中真理的来源:
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 决定授权请求的后果
土地:
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(没有人可以点击),自动认可为第一个用户:
stubIdp({ name: 'google', onAuthorize: (req) => req.users[0] })
当地身份users.json(中文(简体) )
默认情况下, 目录是单一的决定性用户
(单位:千美元)stub-<provider>-user) (中文(简体) ). 要定义多个本地身份,请放弃一个
users.json 实例模拟数据目录中的数组
(单位:千美元).bb-data/<auth-id>/users.json:
[
{ "sub": "alice", "email": "[email protected]", "name": "Alice" },
{ "sub": "bob", "email": "[email protected]", "name": "Bob" }
]
这些用户充电 req.users 和登录屏幕的取账器。 没有
文件,使用单个默认用户,所以已有的应用程序不变.
错误分类
所有错误都跟着 <Name>Exception 命名公约和与 isBlocksError()。 。 。 .
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()数字 :
aws ssm put-parameter --name /<fullId> --type SecureString --value '<google-client-secret>' --overwrite
在第一次部署时, 框架种子每个带有随机占位符的秘密参数, 因此, 如果您在设定占位符的真实值之前就部署 IDP 注册符, 而签名失败于提供者 —— 设定真实值并重新部署 。 注册重新读取每个 cdk deploy,因此设置或旋转证书在下一次部署时生效(每次部署更新时显示的自定义资源;更新是一元数据).
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 })()—— 中继流 不需要,因为redirect_uri是后端的 HTTPS 调用, 自定义方案只是relayTo目标; - 自定义域名超出主域名(只有主应用程序来源自动注册);
- 位于端口以外的沙盒 dev 服务器
3000。 。 。 .
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 }) 提供者(参见 地方发展);在沙盒/部署中锻炼真正的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端点被挂载用于更新符号
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 当访问符过期时 :
// 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数字 :
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 如何驱动流量 :
- 邮政
/aws-blocks/auth/authorize-params/<provider>与{ csrf, relayTo: 'myapp://auth', appState? }— 服务器返回{ authorizeUrl, clientId, scopes, state, nonce } - 在系统浏览器中打开 IDP 授权 URL
redirect_uri设置到 备份 HTTPS 回调( 不是自定义方案) - IDP 的用户认证 ~ IDP 重定向到
/aws-blocks/auth/callback?code=...&state=... - 后端解码已签名的状态信封,查看中继目标,并发布
302 Location: myapp://auth?code=...&state=... - OS 将自定义化学 URI 运行到本地应用程序
- 应用程序摘要
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。 。 。 .