Skip to content

feat(auth): Google SSO via OIDC PKCE#10

Open
psdjungpulzze wants to merge 7 commits into
mainfrom
feat/google-sso
Open

feat(auth): Google SSO via OIDC PKCE#10
psdjungpulzze wants to merge 7 commits into
mainfrom
feat/google-sso

Conversation

@psdjungpulzze

Copy link
Copy Markdown
Contributor

Summary

  • Adds a Continue with Google button to the login screen using OIDC PKCE against https://auth.interactor.com
  • New src/lib/oidc.ts: useOidcRequest hook + exchangeCodeForToken via expo-auth-session (PKCE S256)
  • New signInWithJwt() in auth store; signIn() (password flow) now delegates to it — both paths end with the same pm_mobile_* session exchange

How it works

  1. User taps "Continue with Google" → promptAsync() opens in-app browser to https://auth.interactor.com/oauth/authorize
  2. Account-server handles the Google IdP flow and returns an auth code
  3. App exchanges code + PKCE verifier for an id_token via expo-auth-session
  4. id_token is exchanged for a long-lived pm_mobile_* token via POST /api/v1/me/mobile-sessions

Required action before testing

Register these redirect URIs with account-server's OAuth client (EXPO_PUBLIC_INTERACTOR_CLIENT_ID):

  • buildapp://auth/callback — standalone app
  • exp://*/--/auth/callback — Expo Go / simulator (wildcard for LAN IPs)

Test plan

  • "Continue with Google" button visible on login screen
  • Tapping it opens account-server OAuth in browser
  • Completing Google auth redirects back and signs in (Me tab shows email)
  • Password login still works unchanged
  • npm run typecheck passes (no TS errors)

- Add src/lib/oidc.ts: useOidcRequest hook + exchangeCodeForToken using
  expo-auth-session with PKCE (S256) against https://auth.interactor.com
- Add signInWithJwt() to auth store; refactor signIn() to reuse it so
  both password and OIDC paths share the same pm_mobile_* exchange logic
- Update login screen with "Continue with Google" button above email/password
- Fix pre-existing TypeScript error in _layout.tsx (router.replace type)
- Install expo-auth-session, expo-crypto, expo-web-browser; add EXPO_PUBLIC_INTERACTOR_CLIENT_ID to config

Redirect URIs to register with account-server:
  buildapp://auth/callback          (standalone app)
  exp://*/--/auth/callback          (Expo Go / simulator)
- Fix env var names (EXPO_PUBLIC_INTERACTOR_CLIENT_ID/SECRET) to match config.ts
- Disable PKCE (account-server does not support code_challenge)
- Pass request.redirectUri to token exchange to guarantee URI consistency
- Bypass mobile-session exchange with user JWT directly (TODO: restore once
  POST /api/v1/me/mobile-sessions is deployed on build.interactor.com)
- Add babel.config.js with babel-preset-expo + reanimated plugin
- Add react-native-worklets peer dep for reanimated 4.x
- Update npm start to --dev-client for native build compatibility
- Add Ionicons to tab bar (home/checkbox/thumbs-up/notifications/person)
- Fix SafeAreaView import on home screen (react-native-safe-area-context)
- Remove Tasks and Inbox tabs; add Goal and Feedback tabs
- Overview: stats grid (todos, approvals, tasks, unread) + recent todo list with pull-to-refresh
- Goal: filter pills (All/Open/In Progress/Accepted) with GoalCard showing type badge, display number, status, priority dot, progress bar
- Approvals: approve/reject actions with reject comment modal (bottom sheet)
- Feedback: project picker scroll pills → feedback list with source, votes, status, rating
- Me: fix SafeAreaView import (react-native → react-native-safe-area-context), add settings section rows
- queries.ts: add EngineGoal, FeedbackEntry types; useGoals, useFeedback hooks; fix TodoProject typing
…+ cookie session

The mobile app is the frontend for the product-manager backend which uses
NextAuth cookie-based auth. iOS's NSURLSession cookie jar automatically stores
and sends the authjs.session-token cookie, so no manual token forwarding needed.

- Login: GET /api/auth/csrf → POST /api/auth/callback/credentials → cookie jar
  stores the session token → GET /api/auth/session confirms the session
- API client: remove Authorization Bearer header (cookie jar handles auth)
- SSE: remove Bearer header (cookie jar handles auth)
- Remove: expo-auth-session, expo-crypto, expo-web-browser, src/lib/oidc.ts
- Remove: pm_mobile_* token storage, signInWithJwt, ACCOUNT_SERVER_URL config
- Login screen: clean email/password form, no OIDC button
…e_* Bearer auth

All sign-in methods (email/password and Interactor SSO) now end with a
long-lived pm_mobile_* Bearer token stored in SecureStore. Every API call
and SSE connection uses Authorization: Bearer pm_mobile_<token>.

Email/password flow: credentials POST → session cookie → exchange via
POST /api/v1/me/mobile-sessions → store pm_mobile_*.

Interactor SSO flow: openAuthSessionAsync opens the product-manager OIDC
sign-in page → backend mobile-callback route mints pm_mobile_* and redirects
to buildapp://auth/callback?token=...&email=...&userId=... → app captures it.

The backend GET /api/auth/mobile-callback route is tracked in T#105 and
requires a separate PR before the SSO button is fully functional.
Full notification inbox with All/Unread filter pills, per-notification
mark-as-read, mark-all-as-read, type-based icons, and page navigation.
Replaces the Feedback tab with Inbox (more action-critical on mobile).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant