passport-apple

Passport.js OAuth2 strategy for Sign in with Apple, handling Apple's JWT client-secret generation and POST-based callback flow.

SDK
npm
v2.0.2
146 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
38 /100 Needs Attention
Development Activity 0
Maintenance 20
Community 52
Maturity 60
Momentum 20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
45 /100 Fair
Architecture 60
Code Quality 25
Innovation 40
Learning Curve 55

passport-apple is a Passport.js strategy that implements Sign in with Apple, Apple’s OAuth2/OpenID Connect identity provider used for “Sign in with Apple” buttons in web and mobile apps. Rather than reimplementing passport-oauth2 from scratch, it extends OAuth2Strategy and patches in the two behaviors Apple’s implementation requires that most OAuth2 providers don’t: signing a short-lived ES256 JWT as the client_secret on every token exchange, and normalizing Apple’s POST-based callback (delivered via form_post) into the query-parameter shape Passport expects.

The library also captures the one-time name/email payload Apple sends only on a user’s very first authorization, exposing it as req.appleProfile so the consuming app can persist it before Apple stops sending it on subsequent logins.

What You Get

  • A drop-in Passport.js Strategy class (passport-apple) that plugs into any existing passport.use(...) setup alongside other OAuth strategies
  • Automatic generation of Apple’s required ES256-signed JWT client_secret on every token exchange, using either a private key file path or an in-memory key string
  • Built-in handling of Apple’s POST-based form_post callback, remapping req.body into req.query so Passport’s OAuth2Strategy machinery works unmodified
  • Capture of the one-time user payload (first name/last name) Apple sends only on a user’s first authorization, exposed as req.appleProfile
  • Configurable passReqToCallback, custom authorizationURL/tokenURL overrides, and access to the decoded idToken claims (sub, email, email_verified) in the verify callback

Common Use Cases

  • Adding “Sign in with Apple” as a login option alongside Google/Facebook/GitHub OAuth in an Express app that already uses Passport.js
  • Satisfying Apple App Store Guideline 4.8, which requires apps offering third-party login to also offer Sign in with Apple
  • Implementing account creation flows that must capture a user’s name on first Apple sign-in before Apple stops including it in later logins
  • Building a unified SSO/auth server that normalizes Apple’s non-standard OAuth callback behavior alongside standard OAuth2 providers

Under The Hood

Architecture The package is a thin two-file module: src/strategy.js defines a Strategy constructor that extends passport-oauth2’s OAuth2Strategy via util.inherits, overriding three methods — it monkey-patches this._oauth2.getOAuthAccessToken to inject a freshly generated JWT client secret into the token-exchange POST, overrides authenticate() to merge req.body into req.query so Apple’s form_post callback works with Passport’s query-based flow, and overrides authorizationParams() to set Apple’s required response_type, scope, and response_mode. Cryptographic concerns are delegated entirely to src/token.js’s AppleClientSecret class, which reads a private key (from a file path or string) and signs a short-lived ES256 JWT per request. The design is tightly coupled to passport-oauth2’s internal call shape — reassigning this._oauth2.getOAuthAccessToken directly rather than using a documented extension point — so an upstream signature change in passport-oauth2 would break the override silently.

Tech Stack A plain CommonJS Node.js module with no build step or bundler — package.json’s main points straight at src/strategy.js, consumed via require() in Express/Passport apps. Its only two runtime dependencies are jsonwebtoken (^9.0.0), used for ES256-signing the Apple client secret, and passport-oauth2 (^1.6.1), the base strategy class it extends using pre-ES6 util.inherits-style prototypal inheritance rather than JavaScript classes. There is no database layer, no CLI, and no bundler config; the module is distributed purely as an npm package consumed at the source level.

Code Quality No test files or test framework exist in the repository — package.json’s test script is a stub that echoes an error and exits 1 — and no CI configuration (.github/workflows or similar) is present. Error handling is inconsistent: token.js rejects promises with plain strings ("AppleAuth Error – ...") rather than Error objects, while strategy.js relies on node-style callback error-first conventions. There is no TypeScript, no visible linter/formatter config, and no static type checking, though JSDoc-style comments document the public constructor options reasonably well.

API Design The module’s public surface is minimal and idiomatic for Passport: a single Strategy class registered via passport.use(new AppleStrategy({...}, verifyCallback)), matching the shape developers already know from other OAuth strategies, so switching providers requires no route-level rewrites. Getting started demands assembling Apple-specific configuration (team ID, key ID, PEM private key) that has nothing to do with the library itself, and the README documents this setup path together with the req.appleProfile one-time-name quirk and the POST-to-GET redirect workaround needed to preserve session cookies across Apple’s cross-site callback.

Used by 5 apps in this directory

TypeScript
92%
GPL 3.0

Blinko

Knowledge Management · Note Taking

11,049

A self-hosted, AI-powered card note-taking tool that lets you capture fleeting thoughts instantly and retrieve them with natural language search.

View details
75
Repo Health
69
Technical
63
Dependency
Built with
TypeScript 92%
Updated 1 months ago
TypeScript
82%
MIT

LibreChat

AI Assistants · Developer Tools

45,009

Unite every major AI model in one self-hosted chat platform with agents, code execution, MCP tools, and enterprise authentication.

View details
93
Repo Health
81
Technical
65
Dependency
Built with
TypeScript 82%
JavaScript 17%
Updated 1 weeks ago
TypeScript
97%
Other

Rocket.Chat

Team Chat

46,180

The secure, self-hosted team communications platform for organizations that cannot compromise on data sovereignty.

View details
96
Repo Health
79
Technical
66
Dependency
Built with
TypeScript 97%
Updated 1 weeks ago
TypeScript
68%
Other

TaskView

Productivity · Project Management

1,081

Self-hosted project and task management platform for software teams, with Kanban boards, sprints, time tracking, GitHub/GitLab integrations, and an MCP server for AI assistants.

View details
78
Repo Health
77
Technical
71
Dependency
Built with
TypeScript 68%
Vue 21%
Updated 1 weeks ago
TypeScript
65%
AGPL 3.0

Worklenz

Collaboration · Product Management · Project Management

3,191

All-in-one open source project management for teams who want full control — plan projects, track tasks, manage resources, and monitor finances without the SaaS lock-in.

View details
86
Repo Health
7
Technical
64
Dependency
Built with
TypeScript 65%
JavaScript 23%
Updated 1 weeks ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers