跳过内容

Better Auth Integration

GitHub

Better Auth 与 @capgo/capacitor-social-login 当您希望在设备上拥有原生登录功能,但仍希望 Better Auth 在您的后端创建和管理会话时,Better Auth 就会发挥作用。

本页面重点介绍了两个最合适的集成模式:

  • 原生令牌传递,适用于Google、Apple和Facebook
  • Better Auth通用OAuth,适用于Auth0、Okta、Keycloak和自定义OIDC服务器

使用哪种模式

标题:使用哪种模式

使用原生令牌传递

标题:使用原生令牌传递

使用 SocialLogin.login() 首先,然后将返回的令牌发送到Better Auth中 authClient.signIn.social() 当您使用时:

  • Google
  • Apple
  • Facebook

使用更好的认证通用OAuth

标题:使用更好的认证通用OAuth

当您使用时,让更好的认证完全控制OAuth重定向流程:

  • Auth0
  • Okta
  • Keycloak
  • GitHub
  • OneLogin
  • 任何自定义OAuth2或OIDC提供商

这保持会话交换在更好的认证侧,并避免在两个系统之间重复重定向逻辑。

更好的认证服务器设置

标题:更好的认证服务器设置

首先配置Better Auth支持的社交提供商:

import { betterAuth } from 'better-auth';
export const auth = betterAuth({
baseURL: process.env.BETTER_AUTH_URL,
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
},
apple: {
clientId: process.env.APPLE_CLIENT_ID as string,
clientSecret: process.env.APPLE_CLIENT_SECRET as string,
appBundleIdentifier: process.env.APPLE_APP_BUNDLE_IDENTIFIER as string,
},
facebook: {
clientId: process.env.FACEBOOK_CLIENT_ID as string,
clientSecret: process.env.FACEBOOK_CLIENT_SECRET as string,
},
},
trustedOrigins: ['https://appleid.apple.com'],
});

标题:Better Auth客户端设置

复制到剪贴板
import { createAuthClient } from 'better-auth/client';
export const authClient = createAuthClient({
baseURL: 'https://auth.example.com',
});

Google示例

这是原生移动设备上的Google登录的最干净的集成路径:

import { SocialLogin } from '@capgo/capacitor-social-login';
import { authClient } from '@/lib/auth-client';
const googleResult = await SocialLogin.login({
provider: 'google',
options: {
scopes: ['profile', 'email'],
},
});
if (googleResult.result.responseType !== 'online' || !googleResult.result.idToken) {
throw new Error('Google online mode with idToken is required for Better Auth.');
}
await authClient.signIn.social({
provider: 'google',
idToken: {
token: googleResult.result.idToken,
accessToken: googleResult.result.accessToken?.token,
},
callbackURL: '/dashboard',
});

对于苹果,传递相同的nonce给native登录请求和Better Auth:

import { SocialLogin } from '@capgo/capacitor-social-login';
import { authClient } from '@/lib/auth-client';
const nonce = crypto.randomUUID();
const appleResult = await SocialLogin.login({
provider: 'apple',
options: {
scopes: ['email', 'name'],
nonce,
},
});
if (!appleResult.result.idToken) {
throw new Error('Apple idToken is required for Better Auth.');
}
await authClient.signIn.social({
provider: 'apple',
idToken: {
token: appleResult.result.idToken,
nonce,
accessToken: appleResult.result.accessToken?.token,
},
callbackURL: '/dashboard',
});

Better Auth文档了两种Facebook手动模式:

  • iOS Limited Login:传递 idToken
  • 访问令牌流:传递访问令牌作为 tokenaccessToken

与此响应形状一起工作 @capgo/capacitor-social-login:

import { SocialLogin } from '@capgo/capacitor-social-login';
import { authClient } from '@/lib/auth-client';
const facebookResult = await SocialLogin.login({
provider: 'facebook',
options: {
permissions: ['email', 'public_profile'],
},
});
const betterAuthToken = facebookResult.result.idToken
? {
token: facebookResult.result.idToken,
}
: facebookResult.result.accessToken?.token
? {
token: facebookResult.result.accessToken.token,
accessToken: facebookResult.result.accessToken.token,
}
: null;
if (!betterAuthToken) {
throw new Error('Facebook idToken or access token is required for Better Auth.');
}
await authClient.signIn.social({
provider: 'facebook',
idToken: betterAuthToken,
callbackURL: '/dashboard',
});

通用 OAuth 提供商

标题:通用 OAuth 提供商

对于 Auth0、Okta、Keycloak、GitHub、Microsoft Entra ID 和类似提供商,Better Auth 的 Generic OAuth 插件通常比从 SocialLogin.login({ provider: 'oauth2' }).

Better Auth 服务器

标题:Better Auth 服务器
import { betterAuth } from 'better-auth';
import { genericOAuth } from 'better-auth/plugins';
export const auth = betterAuth({
plugins: [
genericOAuth({
config: [
{
providerId: 'keycloak',
discoveryUrl: 'https://sso.example.com/realms/mobile/.well-known/openid-configuration',
clientId: process.env.KEYCLOAK_CLIENT_ID as string,
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET as string,
},
],
}),
],
});

Better Auth 客户端

标题:Better Auth 客户端
import { createAuthClient } from 'better-auth/client';
import { genericOAuthClient } from 'better-auth/client/plugins';
export const authClient = createAuthClient({
baseURL: 'https://auth.example.com',
plugins: [genericOAuthClient()],
});
await authClient.signIn.oauth2({
providerId: 'keycloak',
callbackURL: '/dashboard',
});

Better Auth Generic OAuth 提供商的示例

Section titled “Better Auth Generic OAuth Provider Examples”

Better Auth 提供了多个提供商的预配置助手。这些助手与社交登录插件文档中看到的额外提供商示例非常相似。

import { betterAuth } from 'better-auth';
import { auth0, genericOAuth } from 'better-auth/plugins';
export const auth = betterAuth({
plugins: [
genericOAuth({
config: [
auth0({
providerId: 'auth0',
domain: 'dev-example.eu.auth0.com',
clientId: process.env.AUTH0_CLIENT_ID as string,
clientSecret: process.env.AUTH0_CLIENT_SECRET as string,
scopes: ['openid', 'profile', 'email', 'offline_access'],
}),
],
}),
],
});
await authClient.signIn.oauth2({
providerId: 'auth0',
callbackURL: '/dashboard',
});
import { betterAuth } from 'better-auth';
import { genericOAuth, microsoftEntraId } from 'better-auth/plugins';
export const auth = betterAuth({
plugins: [
genericOAuth({
config: [
microsoftEntraId({
providerId: 'entra',
tenantId: 'common',
clientId: process.env.AZURE_CLIENT_ID as string,
clientSecret: process.env.AZURE_CLIENT_SECRET as string,
scopes: ['openid', 'profile', 'email', 'User.Read'],
}),
],
}),
],
});
await authClient.signIn.oauth2({
providerId: 'entra',
callbackURL: '/dashboard',
});
import { betterAuth } from 'better-auth';
import { genericOAuth, okta } from 'better-auth/plugins';
export const auth = betterAuth({
plugins: [
genericOAuth({
config: [
okta({
providerId: 'okta',
issuer: 'https://dev-12345.okta.com/oauth2/default',
clientId: process.env.OKTA_CLIENT_ID as string,
clientSecret: process.env.OKTA_CLIENT_SECRET as string,
scopes: ['openid', 'profile', 'email', 'offline_access'],
}),
],
}),
],
});
await authClient.signIn.oauth2({
providerId: 'okta',
callbackURL: '/dashboard',
});

Keycloak

Keycloak
import { betterAuth } from 'better-auth';
import { genericOAuth, keycloak } from 'better-auth/plugins';
export const auth = betterAuth({
plugins: [
genericOAuth({
config: [
keycloak({
providerId: 'keycloak',
issuer: 'https://sso.example.com/realms/mobile',
clientId: process.env.KEYCLOAK_CLIENT_ID as string,
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET as string,
scopes: ['openid', 'profile', 'email', 'offline_access'],
}),
],
}),
],
});
await authClient.signIn.oauth2({
providerId: 'keycloak',
callbackURL: '/dashboard',
});

GitHub使用手动通用OAuth配置

GitHub使用手动通用OAuth配置

GitHub在通用OAuth页面上没有Better Auth助手,因此使用手动配置:

import { betterAuth } from 'better-auth';
import { genericOAuth } from 'better-auth/plugins';
export const auth = betterAuth({
plugins: [
genericOAuth({
config: [
{
providerId: 'github',
clientId: process.env.GITHUB_CLIENT_ID as string,
clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
authorizationUrl: 'https://github.com/login/oauth/authorize',
tokenUrl: 'https://github.com/login/oauth/access_token',
userInfoUrl: 'https://api.github.com/user',
scopes: ['read:user', 'user:email'],
pkce: true,
},
],
}),
],
});
await authClient.signIn.oauth2({
providerId: 'github',
callbackURL: '/dashboard',
});
  1. 使用 Google 在线模式 Better Auth 需要 idToken, 因此 google.mode: 'offline' 不是适合此手动流程的正确选择。

  2. 重新使用 Apple nonce 生成一次,发送到 Apple 原生登录,然后将相同的值发送到 Better Auth。

  3. 根据平台处理 Facebook 不同 iOS 上的有限登录会给你一个 ID 令牌。其他流程可能只给你一个访问令牌。

  4. 不要混合通用 OAuth 流,除非有原因 如果 Better Auth 拥有 OAuth 提供商配置,则让 Better Auth 拥有重定向流程。

进一步阅读

进一步阅读

继续使用Better Auth Integration

继续从Better Auth Integration中进行

如果您正在使用 更好的认证集成 为了规划身份验证和账户流程,连接它 使用@capgo/capacitor社交登录 为使用@capgo/capacitor-social-login的原生能力 @capgo/capacitor-social-login 为@capgo/capacitor-social-login的实现细节 @capgo/capacitor-passkey 为@capgo/capacitor-passkey的实现细节 @capgo/capacitor-native-biometric 为@capgo/capacitor-native-biometric的实现细节, 和 双因素认证 为双因素认证的实现细节。