Google Sign In bindings for Perry.
| Target | Implementation |
|---|---|
| iOS 16+ | Native — Swift bridge over the GoogleSignIn SDK. |
| macOS 13+ | Native — same Swift bridge. |
| Android 7+ | Native — Kotlin bridge over androidx.credentials.CredentialManager with GetGoogleIdOption. |
| Linux / Windows | Stub — every call resolves with {"success":false,"error":"unsupported-platform"}. |
| tvOS / watchOS / visionOS | Stub — no first-party Google Sign In SDK on these platforms. |
Closes PerryTS/perry#1138 (follow-up to #674).
npm install @perryts/google-authThe package targets perry-ffi ABI v0.5 (perry.nativeLibrary.abiVersion: "0.5" in package.json). Perry validates compatibility at build time.
Add a [google_auth] block to your perry.toml:
[google_auth]
ios_client_id = "1234567890-abcdefghijklmnopqrstuvwxyz.apps.googleusercontent.com"
android_client_id = "1234567890-zyxwvutsrqponmlkjihgfedcba.apps.googleusercontent.com"
server_client_id = "1234567890-server.apps.googleusercontent.com"
default_scopes = ["openid", "email", "profile"]Perry's compile pipeline:
- iOS / macOS: writes
GIDClientID, optionalGIDServerClientID, andGIDDefaultScopesinto the generatedInfo.plist, plus aCFBundleURLSchemesentry derived from the reversed client ID (required for the OAuth redirect). - Android: writes the server client ID into
res/values/strings.xmlasgoogle_auth_server_client_id. The Kotlin bridge reads it viaR.string.google_auth_server_client_idand passes it toGetGoogleIdOption.Builder().setServerClientId(...). Perry merges the required gradle dependencies (androidx.credentials:credentials,androidx.credentials:credentials-play-services-auth,com.google.android.libraries.identity.googleid:googleid,kotlinx-coroutines-android) into the app'sbuild.gradle.kts.
The Swift bridge guards every SDK call with #if canImport(GoogleSignIn). Without the SDK on the swiftc framework search path, all three entry points resolve with {"success":false,"error":"framework-not-linked"}. To wire the real SDK:
- Install the GoogleSignIn Swift package or CocoaPod.
- Set
PERRY_GOOGLE_SIGN_IN_FRAMEWORK_DIR=/path/to/Frameworksat build time, where/path/to/FrameworkscontainsGoogleSignIn.frameworkand its dependencies (GTMSessionFetcher,GoogleUtilities,AppAuth). - Perry forwards
-F $PERRY_GOOGLE_SIGN_IN_FRAMEWORK_DIRto swiftc and adds-framework GoogleSignInto the link line automatically.
import {
js_google_auth_sign_in,
js_google_auth_silent_sign_in,
js_google_auth_sign_out,
type GoogleSignInResult,
} from "@perryts/google-auth";
// First-launch flow: try the silent path first; fall back to
// interactive on no-cached-session.
async function ensureSignedIn(): Promise<GoogleSignInResult> {
const silent = JSON.parse(
await js_google_auth_silent_sign_in(),
) as GoogleSignInResult;
if (silent.success) return silent;
if (silent.error === "no-cached-session") {
return JSON.parse(await js_google_auth_sign_in()) as GoogleSignInResult;
}
// missing-client-id, framework-not-linked, jvm-unavailable, etc. —
// surface upstream rather than re-prompting.
return silent;
}
const result = await ensureSignedIn();
if (result.success) {
// result.idToken → server-side verification
// result.email, result.userId, result.name, result.pictureUrl → UI
} else if (result.cancelled) {
// user dismissed the sheet
} else {
console.error("sign-in failed:", result.error);
}Every promise resolves; failures arrive via the { success: false, error } shape. Recognized slugs:
| Slug | Meaning |
|---|---|
cancelled |
User dismissed the system sign-in sheet (also sets cancelled: true). |
missing-client-id |
[google_auth] ios_client_id / android_client_id not set in perry.toml. |
no-cached-session |
Silent sign-in found no stored credentials. |
framework-not-linked |
Apple build done without the GoogleSignIn SDK on the framework path. |
no-presenting-view-controller |
iOS bridge couldn't locate the key window's root VC. |
no-presenting-window |
macOS bridge couldn't locate keyWindow / mainWindow. |
no-user-returned |
SDK returned without error but no GIDGoogleUser. |
sign-in-failed |
Generic Apple SDK failure (network, server-config, etc.). |
android-credential-failed |
Android CredentialManager surfaced a non-cancel error. |
unsupported-platform |
Linux / Windows / tvOS / watchOS / visionOS stub. |
jvm-unavailable |
Android JNI bridge couldn't reach the JavaVM (host-link misconfigured). |
not-installed |
Android bridge missing application context (host didn't call install). |
null-result-from-bridge |
Internal — Swift bridge returned a null pointer. |
non-utf8-result-from-bridge |
Internal — bridge returned bytes that weren't valid UTF-8. |
Prior to v0.5.1015, @perryts/google-auth shipped inside the perry workspace as perry-ext-google-auth and was a not-yet-implemented stub. Replace the implicit binding with an explicit install:
npm install @perryts/google-authThe import { js_google_auth_sign_in, ... } from "@perryts/google-auth" surface is unchanged.
MIT