feat: [LC-1663] Streamline Auto-verify email #1122
Conversation
β¦ation Add provider-agnostic OIDC JWT verification to the createProfile route so email ContactMethod is verified during onboarding instead of requiring a 3-hop VP-JWT chain. Pending inbox credentials are also finalized inline (fire-and-forget) for faster embed SDK claim resolution. - Add `jose` for OIDC discovery-based JWT verification - New `oidc-jwt.helpers.ts`: verifyAuthToken using JWKS + issuer matching - New `finalize-inbox.helpers.ts`: extracted from inbox.ts finalize route - Extend createProfile input with optional `authToken` field - Client passes Firebase ID token during onboarding - Env vars: OIDC_TRUSTED_ISSUERS, OIDC_EXPECTED_AUDIENCE Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
π¦ Changeset detectedLatest commit: 3a12ae1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 18 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
β Deploy Preview for app-store-1-basic-launchpad-app canceled.
|
β Deploy Preview for learncarddocs canceled.
|
β Deploy Preview for staging-learncardapp ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
π Hey there! It looks like you modified code, but didn't update the documentation in If this PR introduces new features, changes APIs, or modifies behavior that users or developers need to know about, please consider updating the docs. π Windsurf TipYou can ask Windsurf to help:
Windsurf will review your changes and suggest appropriate documentation updates based on what was modified. π Documentation Guide
This is an automated reminder. If no docs are needed, feel free to ignore this message. |
β¦ofile authToken - 11 unit tests for verifyAuthToken: valid JWT, unknown issuer, malformed/expired/wrong-key tokens, wrong audience, multiple issuers, missing claims - 6 integration tests for createProfile + authToken: auto-verify email, backwards compat, non-fatal failures, emailVerified=false handling - Add oidc-jwt.spec.ts to vitest.unit.config.ts (no Neo4j dependency) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add changeset for email auto-verification feature.
|
@claude please review |
|
Claude finished @goblincore's task ββ View job PR Review CompleteI've conducted a comprehensive review of PR #1122: feat: LC-1663 Streamline Auto-verify email π Review SummaryThis PR implements provider-agnostic OIDC JWT verification for automatic email verification during profile creation. The implementation is well-designed, secure, and follows best practices. β Recommendation: Cannot Auto-Approve - Manual Review RequiredReason: This PR touches high-risk areas ( π Detailed AnalysisSecurity Assessmentβ Strong Security Implementation
Code Quality Assessmentβ Excellent Implementation Quality OIDC JWT Helper (
Profiles Route Enhancement (
Client Integration (
Architecture Assessmentβ Well-Architected Solution Refactoring Excellence:
Provider Agnostic Design:
Testing Assessmentβ Comprehensive Test Coverage Unit Tests (
Integration Tests (
π Specific Code ObservationsPositive Highlights:
Minor Suggestions (non-blocking):
ποΈ Change Impact Assessment
π Auto-Approval AnalysisCannot auto-approve due to:
This is not a reflection of code quality - the implementation is excellent and secure. π― Final Verdictβ APPROVE - This is a well-implemented, secure, and valuable feature that streamlines user onboarding while maintaining strong security practices. The code quality is high, test coverage is comprehensive, and the architecture is sound. The feature eliminates the email verification round-trip during signup, significantly improving UX while using industry-standard OIDC verification methods. |
There was a problem hiding this comment.
β¨ PR Review
LGTM
Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
π‘ Tip: You can customize your AI Review using Guidelines Learn how
Overview
π Relevant Jira Issues
LC-1663
π What is the context and goal of this PR?
Implement provider-agnostic OIDC JWT verification so that email ContactMethods can be auto-verified at profile creation time, eliminating the separate email verification round-trip and enabling immediate finalization of inbox credentials (e.g. from embed SDK claims) when users sign up.
Previously, email verification required the
useAutoVerifyContactMethodWithProofOfLoginclient hook to fire after login, followed byuseFinalizeInboxCredentialsto sign and store pending credentials. This multi-step async chain was fragile and slow - users who received credentials before signing up had to wait for two separate hook cycles before the credential appeared in their wallet.Now the brain-service verifies the auth provider's JWT inline during
createProfile, verifies the email ContactMethod immediately (so that eliminates that round trip via useAutoVerifyContactMethodWithProofOfLogin), and the existing client finalization hook picks up pending credentials on first login(this part is same as before).π₯΄ TL; RL:
jose-based verification using standard OIDC discovery (/.well-known/openid-configuration). Supports Firebase, Keycloak, Okta, Auth0 - adding a provider is a config change, not a code changecreateProfileroute enhancement - accepts optionalauthToken, verifies JWT, creates/links/verifies ContactMethod in the same requestinbox.tsinto reusablefinalizeInboxCredentialsForProfilehelperOnboardingNetworkFormretrieves Firebase ID token and passes it during signupπ‘ Feature Breakdown (screenshots & videos encouraged!)
This pretty much exactly follows the spec outlined in the JIRA:
https://www.loom.com/share/0767c3df46524477a9f4c411169058e4
(In the video I forgot to mention the added env variables you need though if you read the testing instructions in the QA instructions further down you will see it, but just to make sure - you also need to set the brain service ENV variables:
)
1. OIDC JWT Verification (
oidc-jwt.helpers.ts)(SEE JIRA for a more detailed explanation of what OIDC is): "Every major provider (Firebase, Keycloak, Okta, Auth0, etc.) supports OpenID Connect Discovery. They all publish a /.well-known/openid-configuration document that contains a jwks_uri pointing to their public keys."
joselibrary (~45KB, zero deps) for JWT verification via OIDC discoveryOIDC_TRUSTED_ISSUERS(comma-separated issuer URLs) andOIDC_EXPECTED_AUDIENCECache-Controlheaders)emailClaim,emailVerifiedClaim) per providernullon any failure - never throws2.
createProfileroute (profiles.ts)authTokenfield on input (backwards compatible)HAS_CONTACT_METHODdeleteAllProfileContactMethodRelationshipsExceptForProfileId)finalizeInboxCredentialsForProfilefor now and uses existing hook (was causing race condition)3. Finalization helper extraction (
finalize-inbox.helpers.ts)inbox.tsroute into standalone helperISSUED/CLAIMEDstatus updates, webhook dispatch, activity logging (both success and failure paths)/inbox/finalizeroute (existing)4. Client-side token forwarding (
OnboardingNetworkForm.tsx)FirebaseAuthentication.getIdToken()(Capacitor native) orauth().currentUser.getIdToken()(web)authTokenincreateProfilecall5. Plugin type update (
learn-card-network/src/types.ts)createProfilemethod signature updated with optionalauthToken?: stringπ Important tradeoffs made:
joseover Firebase Admin SDK - Provider-agnostic OIDC verification means no vendor SDK dependency. Adding Keycloak/Okta/Auth0 is a config entry, not a dependency.OIDC_TRUSTED_ISSUERSandOIDC_EXPECTED_AUDIENCEare env vars rather than stored in Neo4j. Simpler to manage per-environment and doesn't require a migration.π Types of Changes
π³ Does This Create Any New Technical Debt? ( If yes, please describe and add JIRA TODOs )
Testing
π¬ How Can Someone QA This?
Prerequisites: Set env vars on brain-service:
Happy path - new signup with auto-verified email:
Embed claim β signup β credential appears:
π± π₯ Which devices would you like help testing on?
Chromium / Safari (desktop web), iOS (Capacitor native)
π§ͺ Code Coverage
OIDC JWT Unit Tests (
test/oidc-jwt.spec.ts) β 11 tests, run vianpx vitest run --config vitest.unit.config.ts test/oidc-jwt.spec.ts:OIDC_TRUSTED_ISSUERSβ returns null (no-op)emailVerified: falseβ returned as-is (not suppressed){ email: '', emailVerified: false }createProfile + authToken Integration Tests (
test/profiles.spec.ts) β 6 tests added (require Neo4j via testcontainers):verifyAuthTokennever calledemailVerified: falseβ no ContactMethod createdThe
finalizeInboxCredentialsForProfilehelper is covered by the existingfinalizeroute tests (refactor only, no logic change).Documentation
π Documentation Checklist
User-Facing Docs (
docs/β docs.learncard.com)docs/tutorials/)docs/how-to-guides/)docs/sdks/)docs/core-concepts/)docs/apps/)Internal/AI Docs
Visual Documentation
π Documentation Notes
Internal infrastructure change, no user-facing doc changes needed. The
OIDC_TRUSTED_ISSUERS/OIDC_EXPECTED_AUDIENCEenv vars need to be documented in deployment runbooks for staging/production.β PR Checklist
@analyticsin learn-card-app)π Ready to squash-and-merge?:
β¨ PR Description
Purpose: Add OpenID Connect (OIDC) JWT-based email auto-verification during profile creation to streamline user onboarding by eliminating manual verification steps.
Main changes:
Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
π‘ Tip: You can customize your AI Description using Guidelines Learn how