Skip to main content

Quik Framework :: OAuth Server

@quik/oauth-server provides OAuth server primitives for running your app as an authorization provider.

Installation

pnpm add @quik/oauth-server

What The Module Does

  • Loads OAuth server locales.
  • Registers QOAuthServerService in ServicesStore.
  • Registers API OAuth endpoints when HTTP engine is available.
  • Supports authorization code flow with PKCE verification.
  • Supports refresh token flow with optional rotation.
  • Supports client credentials flow.
  • Exposes JWKS public key metadata for token validation.
  • Exposes token introspection and revocation endpoints.
  • Provides consent store contracts for client/user scope approvals.

Configuration (oauth.server)

  • oauth.server.enabled from OAUTH_SERVER_ENABLED default false.
  • oauth.server.issuer from OAUTH_SERVER_ISSUER default http://localhost:3000.
  • oauth.server.http.authenticationPrefix from OAUTH_SERVER_HTTP_AUTHENTICATION_PREFIX default /auth.
  • oauth.server.http.managementPrefix from OAUTH_SERVER_HTTP_MANAGEMENT_PREFIX default /.
  • oauth.server.authorizationCode.timeToLiveSeconds from OAUTH_SERVER_AUTHORIZATION_CODE_TIME_TO_LIVE_SECONDS default 300.
  • oauth.server.accessToken.timeToLiveSeconds from OAUTH_SERVER_ACCESS_TOKEN_TIME_TO_LIVE_SECONDS default 3600.
  • oauth.server.refreshToken.timeToLiveSeconds from OAUTH_SERVER_REFRESH_TOKEN_TIME_TO_LIVE_SECONDS default 2592000.
  • oauth.server.pkce.requiredByDefault from OAUTH_SERVER_PKCE_REQUIRED_BY_DEFAULT default true.
  • oauth.server.refreshToken.rotateOnUse from OAUTH_SERVER_REFRESH_TOKEN_ROTATE_ON_USE default true.
  • oauth.server.jwks.keyIdentifier from OAUTH_SERVER_JWKS_KEY_IDENTIFIER default oauth-server-default.
  • oauth.server.jwks.rsaModulusLength from OAUTH_SERVER_JWKS_RSA_MODULUS_LENGTH default 2048.
  • oauth.server.jwks.signing.privateKeyPem from OAUTH_SERVER_JWKS_SIGNING_PRIVATE_KEY_PEM default empty.
  • oauth.server.jwks.signing.publicKeyPem from OAUTH_SERVER_JWKS_SIGNING_PUBLIC_KEY_PEM default empty.
  • oauth.server.jwks.signing.allowGeneratedFallback from OAUTH_SERVER_JWKS_SIGNING_ALLOW_GENERATED_FALLBACK default true only when NODE_ENV=development, otherwise false.

Built-In API Endpoints

Authentication routes are registered under:

  • http.paths.api + oauth.server.http.authenticationPrefix + /oauth.

Client management routes are registered under:

  • http.paths.api + oauth.server.http.managementPrefix + /oauth/clients.

Default paths become:

  • POST /api/auth/oauth/authorize.
  • POST /api/auth/oauth/token.
  • POST /api/auth/oauth/introspect.
  • POST /api/auth/oauth/revoke.
  • GET /api/auth/oauth/.well-known/jwks.json.
  • POST /api/oauth/clients/.
  • GET /api/oauth/clients/.
  • GET /api/oauth/clients/:clientId.
  • PATCH /api/oauth/clients/:clientId.
  • DELETE /api/oauth/clients/:clientId.

Request parameters for these endpoints are defined as typed entities in src/entities/:

Quick Usage

import { ServicesStore } from '@quik/services';
import { QOAuthServerService } from '@quik/oauth-server';

const oauth = ServicesStore.get(QOAuthServerService);
oauth.assertEnabled();

oauth.registerClient({
id: 'web-app',
type: 'public',
redirectUris: [ 'https://app.example.com/callback' ],
allowedGrantTypes: [ 'authorization_code', 'refresh_token' ]
});

const authCode = oauth.createAuthorizationCode({
clientId: 'web-app',
userId: 'user-1',
redirectUri: 'https://app.example.com/callback',
scope: [ 'profile' ],
codeChallenge: 'S256_HASH',
codeChallengeMethod: 'S256'
});

const token = await oauth.exchangeAuthorizationCode({
clientId: 'web-app',
code: authCode.code,
redirectUri: 'https://app.example.com/callback',
codeVerifier: 'verifier-value'
});

const jwks = oauth.getJWKS();

const introspection = oauth.introspectToken({
clientId: 'web-app',
token: token.accessToken
});

oauth.revokeToken({
clientId: 'web-app',
token: String(token.refreshToken),
tokenTypeHint: 'refresh_token'
});

Store Extensibility

  • Replace active stores with setOAuthClientStore, setOAuthAuthorizationCodeStore, setOAuthRefreshTokenStore, and setOAuthConsentStore.
  • Build repository-backed consent stores by extending QAbstractOAuthConsentStore.
import { QAbstractOAuthConsentStore, type QOAuthConsent } from '@quik/oauth-server';

class DBConsentStore extends QAbstractOAuthConsentStore<MyConsentRepository> {
protected persistConsent(consent: QOAuthConsent): QOAuthConsent {
return this.repository.upsert(consent);
}

protected fetchConsent(id: string): QOAuthConsent | undefined {
return this.repository.findById(id);
}

protected findConsent(clientId: string, userId: string): QOAuthConsent | undefined {
return this.repository.findByClientAndUser(clientId, userId);
}

protected removeConsent(id: string): void {
this.repository.deleteById(id);
}

protected clearConsents(): void {
this.repository.deleteAll();
}

protected removeRevoked(now: number): number {
return this.repository.deleteRevokedSince(now);
}
}

API Reference

Generated API documentation is available in the oauth-server API section.