OAuth Client for TypeScript: Complete Guide to Implementing Authorization
In modern web development, secure user authentication is one of the key tasks. OAuth 2.0 is an open authorization protocol that allows applications to obtain limited access to user resources without transmitting login and password. In this article, we will walk through how to create an OAuth client in TypeScript that can be used in any web application. The library is suitable for integration with Google, GitHub, Facebook, and other providers.
What is an OAuth Client in TypeScript?
An OAuth client is a set of functions and classes that implement the authorization flow (Authorization Code Flow) on the client or server side. In TypeScript, such a client provides strict typing, which reduces the number of errors and simplifies code maintenance. The main tasks of the client are:
- Generating a URL to redirect the user to the provider's page.
- Exchanging a temporary code for an access token and refresh token.
- Storing and refreshing tokens.
- Validating request parameters (state, nonce).
Library Architecture
The library consists of several modules:
OAuthClient— the main class that manages all stages.TokenStore— an interface for storing tokens (can be implemented in memory, localStorage, or a database).ProviderConfig— configuration for a specific provider (clientId, redirectUri, endpoints).AuthError— a class for handling authorization errors.
Example Implementation in TypeScript
Below is a basic example of an OAuth client for TypeScript. First, let's define the types and interfaces:
// types.tsexport interface TokenResponse { access_token: string; token_type: string; expires_in: number; refresh_token?: string; scope?: string;}
export interface ProviderConfig { authorizationEndpoint: string; tokenEndpoint: string; clientId: string; redirectUri: string; scope: string;}
export interface TokenStore { getToken(): Promise<string | null>; setToken(token: TokenResponse): Promise<void>; clearToken(): Promise<void>;}Now let's create the main OAuthClient class:
// OAuthClient.tsimport { TokenResponse, ProviderConfig, TokenStore } from './types';import { AuthError } from './AuthError';
export class OAuthClient { private config: ProviderConfig; private store: TokenStore;
constructor(config: ProviderConfig, store: TokenStore) { this.config = config; this.store = store; }
// Generate authorization URL getAuthorizationUrl(state: string): string { const params = new URLSearchParams({ client_id: this.config.clientId, redirect_uri: this.config.redirectUri, response_type: 'code', scope: this.config.scope, state: state, }); return `${this.config.authorizationEndpoint}?${params.toString()}`; }
// Exchange code for token async exchangeCodeForToken(code: string, state: string, expectedState: string): Promise<TokenResponse> { if (state !== expectedState) { throw new AuthError('State mismatch. Possible CSRF attack.'); }
const body = new URLSearchParams({ grant_type: 'authorization_code', code: code, redirect_uri: this.config.redirectUri, client_id: this.config.clientId, });
const response = await fetch(this.config.tokenEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: body, });
if (!response.ok) Also in library
Task Scheduler in C# (.NET): Quartz.NET and System.Threading.Timer
Gorilla Mux for Go: A Complete Guide with Examples
Node.js Application Configuration: Best Tools and Approaches
Caching in Java: Redis, Caffeine, Ehcache — Complete Guide