Skip to content

fix(connect): complete Standalone Connect logins - #111

Open
gjtorikian wants to merge 1 commit into
mainfrom
workgraph/emulate-74c-d7895e59
Open

fix(connect): complete Standalone Connect logins#111
gjtorikian wants to merge 1 commit into
mainfrom
workgraph/emulate-74c-d7895e59

Conversation

@gjtorikian

Copy link
Copy Markdown
Collaborator

Summary

  • Implement API-key-protected POST /authkit/oauth2/complete, upserting users by external ID and emitting user lifecycle events so Standalone Connect clients can finish login.
  • Add the minimal browser authorize/completion redirects and authorization-code token exchange, using a seedable connectApplications[].login_url to exercise the whole flow locally.
  • Distinguish completed sessions from unknown/expired sessions; enforce single-use redirects/codes, client-secret and callback binding, and rejection of Connect codes by AuthKit's separate authentication endpoint.
  • Add regression coverage and document setup and deliberate divergences; regenerate SUPPORTED.md (Applications write coverage: 5/8).

Validation

  • bun test: 1,206 passing tests, zero failures.
  • bun run typecheck, bun run lint, bun run fmt:check, and bun run build: passed.
  • bun run gen:events, bun run gen:shapes, and bun run gen:supported: generated catalogs and support matrix are current.
  • Node library/package smoke checks passed; live HTTP curl verified the complete authorize-to-token flow, completion replay, redirect replay, and unknown/expired IDs.

Limitations

No PKCE, refresh/ID tokens, consent UI, or email_change_not_allowed policy. user_consent_options and authorize-time scopes are not modeled. Provisioned emails are marked verified, following the emulator's SSO precedent. Follow the returned completion URL rather than assuming the production URL shape.

An independent review passed with one non-blocking advisory: malformed YAML login_url values are not checked by the seed config validator (API creation does validate the field's type).

Fixes #109

Standalone login clients could not finish authentication because the
completion endpoint was missing, making unsupported routes look like
expired sessions. Provide the minimal authorize-to-token loop so tests
can exercise successful logins and distinguish expiry from completion
replay, while keeping Connect codes out of AuthKit's separate exchange.

Fixes #109
@greptile-apps

greptile-apps Bot commented Sep 11, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

The PR appears safe to merge, with a non-blocking configuration-validation gap for seeded login URLs.

Findings

  1. P2 Seeded login URLs go unchecked
Fix with agent prompt
### Issue 1
src/workos/index.ts:755
The new seeded `login_url` is stored without validation, so malformed values are accepted during startup and fail only when `/oauth2/authorize` returns `400 invalid_redirect_uri`. Validating this field with the other `connectApplications` settings would report configuration errors when the seed is loaded.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

  • Adds external authentication session storage and lifecycle handling.
  • Upserts users from completed external identities and emits existing user lifecycle events.
  • Binds authorization codes to the OAuth client, secret, callback, expiry, and originating flow.
  • Adds comprehensive end-to-end and replay/error-path tests.
  • Seeded login_url values still need startup-time validation.

Diagram

sequenceDiagram
    participant Browser
    participant Emulator
    participant LoginApp
    participant Backend
    Browser->>Emulator: GET /oauth2/authorize
    Emulator->>Emulator: Create external-auth session
    Emulator-->>Browser: "302 login_url?external_auth_id=..."
    Browser->>LoginApp: Authenticate user
    LoginApp->>Backend: Authenticated identity
    Backend->>Emulator: POST /authkit/oauth2/complete
    Emulator->>Emulator: Upsert user and complete session
    Emulator-->>Backend: Completion redirect_uri
    Browser->>Emulator: GET /oauth2/authorize/complete
    Emulator->>Emulator: Redeem session and create code
    Emulator-->>Browser: "302 callback?code=...&state=..."
    Backend->>Emulator: POST /oauth2/token
    Emulator->>Emulator: Validate and consume code
    Emulator-->>Backend: Access token
Loading

Reviews (1) · Last reviewed commit: "fix(connect): complete Standalone Connec..."

Comment thread src/workos/index.ts
scopes: appConfig.scopes ?? [],
audience: appConfig.audience ?? null,
redirect_uris: appConfig.redirect_uris ?? [],
login_url: appConfig.login_url ?? null,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Seeded login URLs go unchecked

The new seeded login_url is stored without validation, so malformed values are accepted during startup and fail only when /oauth2/authorize returns 400 invalid_redirect_uri. Validating this field with the other connectApplications settings would report configuration errors when the seed is loaded.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/workos/index.ts
Line: 755

Comment:
**Seeded login URLs go unchecked**

The new seeded `login_url` is stored without validation, so malformed values are accepted during startup and fail only when `/oauth2/authorize` returns `400 invalid_redirect_uri`. Validating this field with the other `connectApplications` settings would report configuration errors when the seed is loaded.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Standalone Connect cannot finish because POST /authkit/oauth2/complete is missing

1 participant