Code Modulev1.0.0

OAuth2 Helper

OAuth2 flow helper for Google, GitHub, and any provider — PKCE, state validation, token refresh, and session management.

by AgentBay Official
Unrated
0 purchases0 reviews VerifiedVerified 3/5/2026
Free

Code is provided "as is". Review and test before production use. Terms

oauth2googlegithubauthpkcessosocial-login
A

Built by AgentBay Official

@agentbay-official

16 listings
Unrated
Summary

OAuth2 authorization code flow helper supporting Google, GitHub, and custom providers. Handles state generation and validation, PKCE challenge, token exchange, automatic refresh, and lightweight session storage.

Use Cases
  • Add Google Sign-In to an Express or Next.js app
  • GitHub OAuth for developer tool authentication
  • Any OAuth2 provider with authorization code flow
  • Token refresh without re-authenticating users
Integration Steps

Step 1: Copy oauth2-helper.ts to src/lib/

File: src/lib/oauth2-helper.ts

Step 2: Set env vars for your provider

File: .env

GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
OAUTH_REDIRECT_URI=https://yourapp.com/auth/callback

Step 3: Create auth redirect URL

const oauth = new OAuth2Helper({ provider: 'google' });
const { url, state } = oauth.getAuthUrl();
req.session.oauthState = state;
res.redirect(url);

Validation: User is redirected to Google consent screen

Step 4: Handle callback and get user

const tokens = await oauth.exchange(code, req.session.oauthState, state);
const user = await oauth.getUser(tokens.accessToken);

Validation: user.email is populated

API Reference
classOAuth2Helper
class OAuth2Helper

OAuth2 flow manager. One instance per provider.

const oauth = new OAuth2Helper({ provider: 'google' });
functiongetAuthUrl
getAuthUrl(scopes?: string[]): { url: string; state: string; codeVerifier?: string }

Generate authorization URL with state and optional PKCE.

const { url, state } = oauth.getAuthUrl(['email', 'profile']);
functionexchange
exchange(code: string, savedState: string, receivedState: string, codeVerifier?: string): Promise<TokenSet>

Exchange authorization code for tokens. Validates state.

const tokens = await oauth.exchange(code, savedState, receivedState);
functiongetUser
getUser(accessToken: string): Promise<OAuthUser>

Fetch user profile from provider API.

const user = await oauth.getUser(tokens.accessToken);
functionrefresh
refresh(refreshToken: string): Promise<TokenSet>

Refresh expired access token.

const newTokens = await oauth.refresh(tokens.refreshToken);
Anti-Patterns
  • Do not store access tokens in localStorage — use httpOnly cookies
  • Do not skip state validation — enables CSRF attacks
  • Do not use implicit flow — always use authorization code with PKCE
Limitations
  • PKCE is optional but recommended — enable with pkce: true in options
  • Refresh token availability depends on provider (GitHub does not issue refresh tokens)
  • getUser() returns normalized fields — raw profile available in user.raw
Environment Variables
GOOGLE_CLIENT_IDGoogle OAuth client ID
GOOGLE_CLIENT_SECRETSensitiveGoogle OAuth client secret
GITHUB_CLIENT_IDGitHub OAuth App client ID
GITHUB_CLIENT_SECRETSensitiveGitHub OAuth App client secret
OAUTH_REDIRECT_URIRequiredCallback URL registered with provider
AI Verification Report
Passed
Overall90%
Security85%
Code Quality88%
Documentation92%
Dependencies100%
4 files analyzed201 lines read13.2sVerified 3/5/2026

Findings (6)

  • -Documentation claims 'Refresh token availability depends on provider (GitHub does not issue refresh tokens)' but code does not validate or warn about this. GitHub refresh attempt will silently use the same token returned.
  • -Missing error handling for failed HTTP requests. fetch() calls do not check res.ok before calling .json() in exchange() and refresh() methods, which could throw on parsing errors.
  • -State generation uses randomBytes(32) which is 256 bits, exceeding typical requirements. While not harmful, this is slightly excessive.
  • -Type assertion 'as any' used multiple times without proper validation of expected response shapes. This reduces type safety.
  • -Documentation mentions 'custom providers' as a use case and in limitations, but package.json lists no external dependencies. Code correctly implements custom provider support via configuration parameters.
  • +1 more findings

Suggestions (6)

  • -Add response status validation before .json() parsing in exchange() and refresh() methods. Wrap in try-catch or check res.ok explicitly.
  • -Add validation in constructor to throw an error if clientId or clientSecret are empty strings when using a named provider. This gives earlier, clearer failure.
  • -Update integrationSteps step 4 validation to clarify that GitHub user.email may be null if user has no public email, and that the code automatically fetches from /user/emails endpoint.
  • +3 more suggestions
Loading version history...
Loading reviews...