Securityv0.1.5
@tekir/social
OAuth social authentication with Google, GitHub, Apple, Discord, Facebook.
Installation
$
bun add @tekir/socialFeatures
- 5 built-in providers: Google, GitHub, Apple, Discord, Facebook
- HMAC-signed state tokens for CSRF protection
- Redirect URL validation (whitelist + wildcard subdomains)
- Custom provider support via register()
- Stateless mode for mobile/SPA apps
Quick Example
TypeScript
import { Social } from '@tekir/social'
const social = new Social({
providers: {
google: {
clientId: env.GOOGLE_CLIENT_ID,
clientSecret: env.GOOGLE_CLIENT_SECRET,
redirectUri: '/auth/google/callback',
},
},
})
const { url, state } = await social.redirect('google')
ctx.session.put('oauth_state', state)
return response.redirect(url)Changelog
v0.1.5LatestSeptember 16, 2026
- Published output now uses the shared Node-targeted ESM bundle pipeline with external dependencies and generated TypeScript declarations, while Bun consumers keep the native source export.
v0.1.4July 23, 2026
- Package metadata now follows the shared compatible
0.1.xdependency range used by this coordinated Tekir release.
v0.1.3July 16, 2026
- OAuth state validation rejects future and malformed timestamps, production requires a signing key, and provider token/user parsing is stricter and safer.
v0.1.2June 13, 2026
- Apple
id_tokenis now cryptographically verified. The token's RS256 signature is checked against Apple's JWKS (with thekid, cached for an hour) andiss/aud/exp(plus optionalnonce) are validated, so a forged or decode-only token is rejected and only a verifiedemail_verifiedaddress is accepted. - OAuth flows now use PKCE (S256) end to end. Every
redirect()generates a verifier/challenge, the authorization URL carriescode_challenge, andexchangeCodesends thecode_verifier. - OAuth state is now bound to the user's session.
handleCallbackrequires the stored state in both signed and plain modes (fail-closed) and compares the state's bound nonce in constant time, closing login-CSRF and replay. - Redirect validation now allows only
http(s)(rejectingjavascript:/data:/file:), enforces real label boundaries for wildcard matches, and requires HTTPS. The GitHub email fallback accepts only a primary verified address. Access and refresh tokens are made non-enumerable so they do not leak throughJSON.stringify, spread, or most logging. - Found and fixed with Fable.
v0.1.1May 17, 2026
Socialnow refuses to construct underNODE_ENV=productionwhenAPP_KEYis missing, instead of warning and falling back to unsigned state tokens. Dev and test environments still see the warning and the unsigned fallback so quick spike work keeps moving.- Absolute redirect URLs now require
allowedRedirectsin the config. The previous behaviour treated an empty list as no restriction at all, so a freshly configured app could accept?redirect=https://evil.com/pathend to end. Protocol-relative URLs like//evil.com/pathare now resolved againsthttps:and run through the same allowlist instead of slipping past astartsWith('/')shortcut. - OAuth state HMAC comparison now runs in constant time. The library already signed the state token; this closes the timing-side-channel ambient to any HMAC verification.
v0.1.0April 1, 2026
- Initial release