# Google Sign-In Button in SwiftUI: Code and the Contracts

> By Lawrence Arya, Founder & CEO of VP0. Published 2026-06-07. 5 min read.
> Source: https://vp0.com/blogs/google-sign-in-button-swiftui-code

Two contracts come with the button: Google's branding rules and Apple's requirement for a privacy-equivalent sibling.

**TL;DR.** A Google sign-in button in SwiftUI carries two contracts: render it per Google's branding guidelines (official G logo, approved labels, no restyling) and satisfy Apple's guideline 4.8 by offering Sign in with Apple at equal prominence beside it. The default integration is the GoogleSignIn-iOS SDK behind a thin SwiftUI wrapper resolving a presentation anchor; the manual ASWebAuthenticationSession route trades the dependency for owning PKCE yourself. Either way, authentication happens server-side: the ID token gets verified for signature and audience before your backend mints a session. A free VP0 design covers the sign-in screen balanced for two to four options.

## What does adding Google sign-in actually commit you to?

Two contracts, one you expected and one you maybe did not. The expected one is Google's: the button renders per the [official branding guidelines](https://developers.google.com/identity/branding-guidelines), with the standard "G" logo, approved label text ("Sign in with Google" or "Continue with Google"), the prescribed light and dark treatments, and no creative recoloring. Brand-kit buttons are contracts; a teal Google button with a redrawn logo fails review with Google and reads as off-brand to users.

The unexpected contract is Apple's: under [App Review guideline 4.8](https://developer.apple.com/app-store/review/guidelines/), an app that signs users in with a third-party service must also offer a privacy-focused alternative, which in practice means Sign in with Apple, presented with equivalent prominence. Adding the Google button therefore adds the Apple button too, and the rejection that follows skipping it is routine enough to have its own checklist in [the Sign in with Apple rejection fix](/blogs/apple-sign-in-required-rejection-fix-swiftui/).

## Which integration route fits which app?

| Route | What you add | Most useful for |
| --- | --- | --- |
| [GoogleSignIn-iOS SDK](https://github.com/google/GoogleSignIn-iOS) | The official SDK, GIDSignIn flow | The default; handles token refresh and account UI |
| Manual OAuth via [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession) | No SDK; you run the OIDC dance | Dependency-averse teams comfortable with PKCE |
| Firebase Auth | SDK plus Firebase's session layer | Apps already on Firebase for backend |

The OAuth client itself costs $0; the spend is integration time, and the SDK route minimizes it: configure the client ID, add the URL scheme, and call the sign-in flow from a presentation anchor. The manual route trades the dependency for owning the nonce, PKCE, and token exchange yourself, which is a fine trade only when someone on the team can name why.

## What does the SwiftUI wiring look like?

The SDK is UIKit-shaped at the edges, so the SwiftUI work is a thin, honest wrapper:

```swift
struct GoogleSignInButton: View {
    let action: () -> Void
    var body: some View {
        Button(action: action) {
            HStack(spacing: 12) {
                Image("google_g")   // the official asset, unmodified
                    .resizable().frame(width: 20, height: 20)
                Text("Continue with Google")
                    .font(.system(size: 17, weight: .medium))
            }
            .frame(maxWidth: .infinity, minHeight: 50)
        }
        .buttonStyle(.bordered)
    }
}
```

The action resolves the presenting view controller (the SDK's one awkward requirement in SwiftUI: fetch the key window's root, or bridge through `UIViewControllerRepresentable`) and calls `GIDSignIn.sharedInstance.signIn(withPresenting:)`. On success you hold a user object whose **ID token is the only thing your backend should trust**: send it server-side, verify the signature and audience against your client ID, and mint your own session. Accepting the client's word that sign-in happened, without server-side token verification, is the integration's classic security hole.

Restore-previous-session belongs at launch (`restorePreviousSignIn`), so returning users skip the button entirely, and sign-out clears both the SDK state and your own session, since clearing only one produces the half-logged-in limbo users describe as "the app forgot me but not really."

## How should the button sit among its siblings?

With equal billing and honest order. The sign-in screen lists its options as peers, Apple and Google at matching size and visual weight (Apple's guideline language pushes parity, and mismatched prominence is a soft rejection trigger), with email/password where it belongs in your model. Auto-triggering the Google flow on screen appearance, pre-selecting it, or rendering competitors as ghost buttons all read as dark-pattern adjacent and buy nothing: the user's identity choice is the consent moment, the same principle that governs [state-operated identity buttons](/blogs/franceconnect-mobile-login-flow-ui-react-native/) at higher stakes.

One layout note saves a redesign later: leave room for the third button. Apps add sign-in methods over time, and a screen designed as exactly-two-buttons becomes a refactor when the product adds another route. A free [VP0](https://vp0.com) design covers the sign-in screen with the spacing system already balanced for two to four options, which an agent generates against your auth stack directly.

## Key takeaways: the Google button done right

- **Two contracts**: Google's branding rules on the button, Apple's 4.8 requiring a privacy-equivalent sibling.
- **The SDK route is the default**; manual ASWebAuthenticationSession OAuth is for teams that can name why they own PKCE.
- **The ID token goes server-side for verification**; client-side success alone is not authentication.
- **Restore at launch, clear both states at sign-out**, and keep the buttons peers in size and order.
- **Design the screen for n options**, not two.

## Frequently asked questions

**How do I add a Google sign-in button in SwiftUI?** Wrap the official artwork and approved label in a SwiftUI Button per Google's branding guidelines, resolve a presenting view controller, and call GIDSignIn's sign-in flow, then verify the resulting ID token on your backend before minting a session. A free VP0 design supplies the sign-in screen layout an agent generates the wiring into.

**Does adding Google sign-in require Sign in with Apple?** Yes in practice: App Review guideline 4.8 requires apps using third-party login to offer a privacy-focused equivalent, and Sign in with Apple presented at equal prominence is the accepted answer. Plan both buttons from the start.

**Can I restyle the Google button to match my app's design?** No: the branding guidelines fix the logo, label text, and color treatments, and modified buttons risk rejection and user distrust. Choose among the approved variants and spend the design freedom on the rest of the screen.

**Do I need the GoogleSignIn SDK or can I use plain OAuth?** Either works: the SDK handles token refresh, session restore, and the account sheet with minimal code, while a manual ASWebAuthenticationSession flow with PKCE removes the dependency at the cost of owning the OIDC details yourself. Default to the SDK unless you can articulate the trade.

**Why must the backend verify the Google ID token?** Because client-side success is just the client's claim: any caller can assert a sign-in. The backend verifies the token's signature and audience against your client ID, then issues your own session, which is the actual authentication event.

## Frequently asked questions

### How do I add a Google sign-in button in SwiftUI?

Wrap the official artwork and an approved label in a SwiftUI Button per the branding guidelines, resolve a presenting view controller for GIDSignIn's flow, and send the resulting ID token to your backend for signature and audience verification before creating a session. A free VP0 design supplies the sign-in screen layout.

### Does adding Google sign-in require Sign in with Apple too?

Effectively yes: App Review guideline 4.8 requires a privacy-focused equivalent when third-party login is offered, and Sign in with Apple at equal prominence is the standard answer. Plan both buttons from the first design.

### Can I restyle the Google sign-in button?

No. The branding guidelines fix the G logo, label wording, and light/dark treatments; modified buttons risk review trouble with Google and read as untrustworthy. Pick an approved variant and design the rest of the screen around it.

### Should I use the GoogleSignIn SDK or implement OAuth manually?

Default to the SDK: it handles token refresh, session restore, and presentation with little code. Manual OAuth through ASWebAuthenticationSession with PKCE is legitimate for dependency-averse teams that want to own the OIDC details deliberately.

### Why does the backend need to verify the Google ID token?

Client-side success is only a claim. The backend verifies the token's signature and that its audience matches your client ID, then mints your own session; that server-side check is the actual authentication event.

---
*Published on the [VP0 Journal](https://vp0.com/blogs). Free to read, index and cite with attribution.*
