
Nhost nhost-js Auth 模块详解Nhost 认证服务的 TypeScript 客户端实战指南【免费下载链接】nhostThe Open Source Firebase Alternative with GraphQL.项目地址: https://gitcode.com/GitHub_Trending/nh/nhost本篇基于 Nhost 仓库中的官方参考文档 auth.md系统讲解nhost/nhost-js的 Auth 模块如何导入并创建认证客户端、55 个 API 方法的完整能力图谱邮箱/密码、匿名、OTP、Passkey、OAuth2/OIDC、PAT 等、FetchError错误处理机制以及底层的 PKCE 工具与请求中间件链实现。读完本文你可以直接在项目里落地 Nhost 的注册、登录、会话刷新、二次认证与令牌交换等完整认证流程。模块定位与两种导入方式Auth 模块是与 Nhost Auth 服务交互的核心模块封装了用户注册/登录、会话管理、多因素认证MFA、WebAuthn 安全密钥、个人访问令牌PAT以及完整的 OAuth2/OpenID Connect 标准端点。源码位于 client.ts约 5500 行的类型化 API 客户端模块入口 index.ts 通过export * from ./client和export * from ./pkce同时导出 API 客户端与 PKCE 工具函数。有两种使用方式通过主 Nhost 客户端间接使用推荐nhost.auth属性会携带会话刷新、令牌挂载等中间件适合绝大多数场景直接导入 auth 子模块适合只需要调用认证 API、不依赖完整 SDK 组合的特定用例。包 package.json 中通过exports字段声明了独立的子路径入口./auth、./fetch、./session等支持 ESMimport与 CJSrequire双格式运行时要求 Node.js 22// 方式一通过子模块直接导入 import { createAPIClient } from nhost/nhost-js/auth; // 方式二通过主客户端使用文档示例写法 import { createClient } from nhost/nhost-js;创建客户端与首次注册调用典型用法是通过createClient传入项目的subdomain与regionSDK 会据此构造 auth 服务的 baseURL源码中由generateServiceUrl(auth, subdomain, region, authUrl)完成见 nhost.ts然后调用nhost.auth.signUpEmailPassword完成邮箱密码注册import { createClient } from nhost/nhost-js; const nhost createClient({ subdomain, region, }); await nhost.auth.signUpEmailPassword({ email, password, });若需要绕过主客户端auth 子模块还导出低层工厂函数createAPIClient可指定任意 baseURL 并注入自定义中间件链function createAPIClient( baseURL: string, chainFunctions?: ChainFunction[], ): Client;chainFunctions默认为空数组每个ChainFunction的签名为(next: FetchFunction) FetchFunction用于拦截和改写请求/响应日志、重试、自定义请求头等。错误处理FetchError 与自动消息提取这是文档中非常实用的一节必须掌握。SDK 在大多数操作中只要请求返回状态码 300 或请求彻底失败如网络错误都会抛出FetchErrorErrorResponse类型的错误import { createClient } from nhost/nhost-js; import { FetchError } from nhost/nhost-js/fetch; const nhost createClient({ subdomain, region, }); try { await nhost.auth.signInEmailPassword({ email, password, }); } catch (err) { if (!(err instanceof FetchError)) { throw err; // Re-throw if its not a FetchError } console.log(Error:, err); // Error: { // body: { // error: invalid-email-password, // message: Incorrect email or password, // status: 401 // }, // status: 401, // headers: { // content-length: 88, // content-type: application/json, // date: Mon, 12 May 2025 08:08:28 GMT // } // } // error handling... }FetchError的三个关键成员在 fetch.ts 中定义成员类型说明bodyT此处为ErrorResponse原始响应体statusnumberHTTP 状态码headersHeaders响应头由于FetchError extends Errorerr.message已被自动提取为人类可读文案。提取逻辑见 extractMessage它依次尝试message字段、字符串型error字段、嵌套的error.message对象以及 GraphQL 风格的errors[].message数组多条以逗号拼接全部不匹配时回退为An unexpected error occurred。因此只关心文案时按标准Error处理即可try { await nhost.auth.signInEmailPassword({ email, password, }); } catch (err) { if (!(err instanceof Error)) { throw err; // Re-throw if its not an Error } console.log(Error:, err.message); // Error: Incorrect email or password }对应的ErrorResponse结构包含error错误码字符串、message描述与status状态码三个字段例如上例中的invalid-email-password/ 401。Client 方法全景按能力域梳理文档中Client接口共列出 55 个方法全部返回PromiseFetchResponseT少数重定向类方法返回 URL 字符串。FetchResponseT统一携带body、status、headers三个字段fetch.ts。以下按能力域完整梳理签名与返回值均以文档为准。账号登录Sign-in方法签名简化说明signInEmailPassword(body: SignInEmailPasswordRequest, options?) PromiseFetchResponseSignInEmailPasswordResponse邮箱 密码登录启用 TOTP MFA 时返回 MFA challenge 而非直接会话signInAnonymous(body?: SignInAnonymousRequest, options?) PromiseFetchResponseSessionPayload匿名登录总是创建新用户不受AUTH_DISABLE_AUTO_SIGNUP门控而是由AUTH_DISABLE_SIGNUP与AUTH_ANONYMOUS_USERS_ENABLED控制signInIdToken(body: SignInIdTokenRequest, options?) PromiseFetchResponseSessionPayload使用 Apple/Google ID token 登录用户不存在且未设置AUTH_DISABLE_AUTO_SIGNUP时自动注册signInOTPEmail(body: SignInOTPEmailRequest, options?) PromiseFetchResponseOK发起邮箱 OTP 登录向邮箱发送一次性密码signInPasswordlessEmail(body: SignInPasswordlessEmailRequest, options?) PromiseFetchResponseOK魔法链接magic link登录signInPasswordlessSms(body: SignInPasswordlessSmsRequest, options?) PromiseFetchResponseOK手机号免密登录发送 SMS OTPsignInPAT(body: SignInPATRequest, options?) Promise...用 Personal Access Token 登录自动化系统signInProviderURL返回string构造 OAuth2 第三方登录的授权跳转 URLsignInWebauthn(body: SignInWebauthnRequest, options?) Promise...发起 Passkey/WebAuthn 登录返回 challenge注意signInIdToken、signInOTPEmail、signInPasswordlessEmail等方法文档中均明确写道当服务端启用AUTH_DISABLE_AUTO_SIGNUP后未注册用户必须先走对应的/signup/...端点注册这是配置 Auth 服务时需要了解的重要行为分叉。账号注册Sign-up方法说明signUpEmailPassword(body: SignUpEmailPasswordRequest, options?)邮箱密码注册返回SessionPayloadsignUpIdToken(body: SignUpIdTokenRequest, options?)Apple/Google ID token 注册signUpOTPEmail(body: SignUpOTPEmailRequest, options?)邮箱 OTP 注册signUpPasswordlessEmail(body: SignUpPasswordlessEmailRequest, options?)魔法链接注册signUpPasswordlessSms(body: SignUpPasswordlessSmsRequest, options?)手机号免密注册signUpProviderURL(params, options?)构造第三方登录的注册跳转 URLsignUpWebauthn(body: SignUpWebauthnRequest, options?)发起 Passkey 注册返回PublicKeyCredentialCreationOptions会话、令牌与验证方法说明refreshToken(body: RefreshTokenRequest, options?)用刷新令牌换新 JWT旧刷新令牌被吊销并颁发新的轮换机制返回SessionsignOut(body: SignOutRequest, options?)登出/吊销会话tokenExchange(body: TokenExchangeRequest, options?)PKCE 授权码换会话code重定向获得的授权码codeVerifier43–128 字符verifyToken(body: VerifyTokenRequest, options?)校验访问令牌有效性verifyTicketURL(params?)构造验证链接如邮箱验证、密码重置的跳转 URLgetJWKs(options?)获取 JWKS 公钥集用于客户端验证 JWT 签名verifySignInMfaTotp/verifySignInOTPEmail/verifySignInPasswordlessSms/verifySignInWebauthn/verifySignUpWebauthn/verifyElevateWebauthn/verifyAddSecurityKey/verifyChangeUserMfa/verifyChangeUserPhoneNumber各验证流程的第二步提交 TOTP 码、邮箱 OTP、SMS OTP、WebAuthn 断言等完成验证用户信息变更需 elevated 权限方法说明getUser(options?)获取当前用户资料角色、元数据、账号状态返回UserchangeUserEmail(body: UserEmailChangeRequest, options?)修改邮箱向新邮箱发验证邮件changeUserPassword(body: UserPasswordRequest, options?)修改密码该操作会原子地吊销包括当前请求在内的一切会话客户端必须视为已登出并重新登录changeUserPhoneNumber(body: UserPhoneNumberChangeRequest, options?)修改手机号向新号码发 SMS OTP验证通过前原号码不变changeUserMfa(options?)生成 TOTP 密钥返回TotpGenerateResponseQR 码图片 URL 密钥明文用于开启/切换 MFAdeanonymizeUser(body: UserDeanonymizeRequest, options?)匿名用户转正补充邮箱可选密码凭据deanonymizeUserSms(body: UserDeanonymizeSmsRequest, options?)匿名用户转正补充手机号后续通过/signin/passwordless/sms/otp完成验证sendPasswordResetEmail(body: UserPasswordResetRequest, options?)发送密码重置邮件sendVerificationEmail(body: UserEmailSendVerificationEmailRequest, options?)发送邮箱验证链接linkIdToken(body: LinkIdTokenRequest, options?)用 ID token 把当前账号与外部 OAuth 提供方账号绑定请求体中的约束值得注意来源 client.ts密码字段password/newPassword长度为 3–50 字符见UserPasswordRequestUserDeanonymizeRequest中signInMethod取值为email-password | passwordless多个验证类请求UserEmailChangeRequest、SignUpWebauthnVerifyRequest、UserDeanonymizeRequest等都支持可选的codeChallenge字段——PKCE code challenge (S256)提供且需要邮箱验证时验证重定向中返回授权码而不是刷新令牌模式为^[A-Za-z0-9_-]{43}$。WebAuthn / 安全密钥方法说明addSecurityKey(options?)初始化添加 WebAuthn 安全密钥返回PublicKeyCredentialCreationOptionschallenge需 elevated 权限verifyAddSecurityKey(body, options?)提交CredentialCreationResponse完成密钥绑定elevateWebauthn(options?)为已登录用户生成提权 challengePublicKeyCredentialRequestOptionsverifyElevateWebauthn(body, options?)完成提权相关类型如AuthenticatorAssertionResponse的authenticatorData/clientDataJSON/signature均为 Base64url 编码AuthenticatorAttestationResponse额外含attestationObject、publicKeyAlgorithm、transports等用于对接浏览器的navigator.credentialsAPI。PATPersonal Access TokencreatePAT(body: CreatePATRequest, options?): PromiseFetchResponseCreatePATResponse;生成可用于自动化系统的长期令牌可替代常规认证流程需 elevated 权限。配合signInPAT使用。OAuth2 / OpenID Connect 标准端点Auth 服务自身也是一套完整的 OAuth2 授权服务器SDK 完整暴露了 RFC 标准端点方法RFC / 说明oauth2AuthorizeURL(params?)/oauth2AuthorizePostURL(body, options?)授权端点GET/POST返回跳转 URL 字符串oauth2Token(body: OAuth2TokenRequest, options?)令牌端点支持authorization_code与refresh_token两种 grantoauth2Introspect(body, options?)RFC 7662 令牌自省oauth2Revoke(body, options?)RFC 7009 令牌吊销oauth2UserinfoGet/oauth2UserinfoPostUserInfo 端点GET/POSToauth2Jwks(options?)OAuth2/OIDC 签名公钥 JWKSgetOpenIDConfiguration(options?)/getOAuthAuthorizationServer(options?)OpenID Provider Metadata 与授权服务器元数据RFC 8414两者内容相同oauth2LoginGet(params?)/oauth2LoginPost(body, options?)供同意consentUI 调用的内部端点获取授权请求详情 / 完成登录并回调授权码OAuth2AuthorizeParams包含标准授权参数OAuth2TokenRequest的grant_type为authorization_code | refresh_token枚举见文档类型定义节。第三方 Provider 令牌方法说明getProviderTokens(provider: SignInProvider, options?)OAuth 回调后立即拉取提供方令牌access token / refresh token / 过期信息会话在数据库中被清除必须紧接着回调调用用户需自行安全存储如 localStoragerefreshProviderToken(provider, body, options?)用 refresh token 刷新提供方访问令牌避免用户重复认证linkIdToken(body, options?)见用户信息变更小节服务诊断healthCheckGet()返回OK、healthCheckHead()返回void、getVersion()返回GetVersionResponse200用于探活与版本探测。此外还有pushChainFunction(chainFunction: ChainFunction): void——向该客户端的 fetch 中间件链追加一个自定义中间件见下文中间件链一节。核心数据结构速览文档Interfaces一节定义了 60 余个类型这里摘取最关键的几组完整定义见 auth.md 与 client.ts会话三件套Session刷新令牌接口返回包含新访问令牌、刷新令牌与用户信息SessionPayload多数登录/注册接口返回SignInEmailPasswordResponse邮箱密码登录专用返回可能带 MFA challengeMFAChallengePayload。用户模型Userclient.ts#L1382-L1457export interface User { avatarUrl: string; // 头像 URL createdAt: string; // date-time defaultRole: string; // 默认授权角色如 user displayName: string; email?: string; // email 格式 emailVerified: boolean; id: string; // UUID isAnonymous: boolean; locale: string; // 2-3 字符语言码 metadata: Recordstring, unknown | null; phoneNumber?: string; phoneNumberVerified: boolean; roles: string[]; // 如 [user,customer] activeMfaType?: string; // 当前启用的 MFA 类型 }MFA 相关TotpGenerateResponse含imageUrlQR 码 data URL形如data:image/png;base64,...与totpSecret用于手动输入密钥UserMfaRequest的activeMfaType为totp | ——传空字符串即关闭 MFA。OAuth/OIDC 类型OAuth2DiscoveryResponse、OAuth2TokenRequest/Response、OAuth2IntrospectRequest/Response含token_type_hint、OAuth2RevokeRequest、OAuth2UserinfoResponse、ProviderSession等WebAuthn 类型PublicKeyCredentialCreationOptions/RequestOptions、AuthenticatorSelectionauthenticatorAttachment、residentKey、userVerification等、AuthenticatorAttestationResponse、AuthenticatorAssertionResponse以及JWK/JWKSet、ErrorResponse、OKResponse字面量OK等。PKCE 工具generatePKCEPair 与实现细节auth 子模块还导出三个 PKCEProof Key for Code ExchangeRFC 7636工具函数用于邮箱验证等重定向中携带授权码的场景function generateCodeVerifier(): string; // 43 个 base64url 字符的随机 verifier function generateCodeChallenge(verifier: string): Promisestring; // 由 verifier 派生 S256 challenge function generatePKCEPair(): Promise{ verifier: string; challenge: string };实现见 pkce.tsgenerateCodeVerifier用crypto.getRandomValues生成 32 字节随机数后转为 base64url替换//并去掉尾部正好得到 43 字符与codeChallenge字段的正则^[A-Za-z0-9_-]{43}$对齐generateCodeChallenge用crypto.subtle.digest(SHA-256, ...)对 verifier 做 S256 摘要再 base64url 编码。文件头注释说明其依赖 Web Crypto API因此适用于浏览器、Node.js 19、Bun 与 Deno 等运行时。相关行为有测试覆盖pkce.test.ts。典型用法注册时调用generatePKCEPair()把challenge传给signUpEmailPassword/sendVerificationEmail等的codeChallenge字段verifier保存在本地验证重定向回来后携带授权码code与verifier调用tokenExchange换取会话。中间件链与主客户端的会话管理文档中Client的方法表里有pushChainFunction()它背后是 createEnhancedFetch 实现的洋葱模型中间件中间件数组通过reduceRight反向包裹原生fetch按声明顺序执行每个中间件都能在调用next前后分别拦截请求与响应。主客户端工厂在 nhost.ts 中定义了三组开箱即用的配置函数它们会把中间件同时挂到auth、storage、graphql、functions四个客户端上withClientSideSessionMiddlewareL50-L69客户端场景默认使用链式为sessionRefreshMiddleware令牌临近过期自动刷新→updateSessionFromResponseMiddleware响应带来新令牌时更新会话存储→attachAccessTokenMiddleware为所有服务请求挂载 Authorization 头。createClient()会自动注入这一配置withServerSideSessionMiddleware服务端场景刻意去掉自动刷新中间件以避免并发请求下的竞态条件createServerClient()必须显式传入storage如基于 cookie 的实现withAdminSession(adminSession)/withChainFunctions(fns)前者用 admin secret 为 storage/graphql/functions 客户端附加特权会话源码注释明确警告切勿用于客户端代码后者向全部客户端追加自定义中间件。会话本身由sessionStorage持久化主客户端暴露getUserSession()、refreshSession(marginSeconds 60)提前 N 秒刷新传 0 强制刷新与clearSession()浏览器下默认使用 localStorage其他环境降级为内存存储也可通过storage: new CookieStorage({...})等自定义后端替换见 session/ 模块。文档与源码的对应关系这份参考文档并非手写维护的散文而是与源码严格同步的生成物模块级说明直接引用了 docstrings.test.ts 中的测试代码片段{includeCode ...}指令auth.md里的 Usage 与 Error handling 示例即取自该测试文件每个方法的签名、参数表与返回类型则由 OpenAPI 代码生成流程产出gen.sh 驱动devDependencies 含openapi3-ts。因此当你发现文档与行为不一致时优先核对 client.ts 的 JSDoc 与__tests__目录下的测试它们是第一手依据。实践要点小结常规应用用createClient({ subdomain, region })即可获得带自动会话管理的nhost.auth只需认证 API 时可用nhost/nhost-js/auth的createAPIClient(baseURL, chainFunctions)统一用instanceof FetchError分支错误处理需要状态码/原始响应体看err.status/err.body只需文案直接用err.message注意changeUserPassword会吊销全部会话成功后必须重新登录邮箱验证等重定向流程建议配合generatePKCEPair()codeChallengetokenExchange避免刷新令牌直接暴露在重定向 URL 中涉及自动注册的行为受服务端环境变量影响AUTH_DISABLE_AUTO_SIGNUP、AUTH_DISABLE_SIGNUP、AUTH_ANONYMOUS_USERS_ENABLED部署前应在 Auth 服务配置中确认其取值包要求 Node.js 22package.jsonengines字段PKCE 工具依赖 Web CryptoNode 侧需 19 的globalThis.crypto。【免费下载链接】nhostThe Open Source Firebase Alternative with GraphQL.项目地址: https://gitcode.com/GitHub_Trending/nh/nhost创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考