UNPKG

@poppinss/oauth-client

Version:

A framework agnostic package to implement "Login with" flow using OAuth compliant authorization servers.

166 lines (165 loc) 4.67 kB
import { random } from "../../../chunk-KDYPQVIV.js"; import { E_OAUTH_MISSING_TOKEN, E_OAUTH_STATE_MISMATCH, HttpClient, UrlBuilder, debug_default } from "../../../chunk-2CCQZGHU.js"; // src/clients/oauth2/main.ts import { parse } from "node:querystring"; import { RuntimeException } from "@poppinss/exception"; var Oauth2Client = class { constructor(options) { this.options = options; } /** * Define the authorize url. Can be overridden by config */ authorizeUrl = ""; /** * Define the access token url. Can be overridden by config */ accessTokenUrl = ""; /** * Processing the API client response. The child class can overwrite it * for more control */ processClientResponse(client, response) { if (client.getResponseType() === "json") { return response; } return parse(response); } /** * Configure the redirect request. Invoked before * the user callback. * * The client defaults can be removed using the `clearParam` method */ configureRedirectRequest(_) { } /** * Configure the access token request. Invoked before * the user callback. * * The client defaults can be removed using the `clearParam` or * `clearOauth1Param` methods */ configureAccessTokenRequest(_) { } /** * Returns the instance of the HTTP client for internal use */ httpClient(url) { return new HttpClient(url); } /** * Returns the instance of the URL builder */ urlBuilder(url) { return new UrlBuilder(url); } /** * Returns the redirect url for redirecting the user. Pre-defines * the following params * * - redirect_uri * - client_id */ getRedirectUrl(callback) { const authorizeUrl = this.options.authorizeUrl || this.authorizeUrl; if (!authorizeUrl) { throw new RuntimeException( 'Missing "config.authorizeUrl". The property is required to make redirect url' ); } const urlBuilder = this.urlBuilder(authorizeUrl); urlBuilder.param("redirect_uri", this.options.callbackUrl); urlBuilder.param("client_id", this.options.clientId); this.configureRedirectRequest(urlBuilder); if (typeof callback === "function") { callback(urlBuilder); } const url = urlBuilder.makeUrl(); debug_default('oauth2 redirect url: "%s"', url); return url; } /** * Generates a random token to be stored as a state and to be sent along * for later verification */ getState() { return random(32); } /** * Verifies the redirect input with the state input */ verifyState(state, inputValue) { if (!state || state !== inputValue) { throw new E_OAUTH_STATE_MISMATCH(); } } /** * Get the access token from the authorization code. One must define * the authorization code using the callback input. * * ```ts * client.getAccessToken((request) => { * request.field('code', authorizationCode) * }) * ``` * * Pre-defines the following form fields * * - grant_type = 'authorization_code' * - redirect_uri * - client_id * - client_secret */ async getAccessToken(callback) { const accessTokenUrl = this.options.accessTokenUrl || this.accessTokenUrl; if (!accessTokenUrl) { throw new RuntimeException( 'Missing "config.accessTokenUrl". The property is required to get access token' ); } const httpClient = this.httpClient(accessTokenUrl); httpClient.field("grant_type", "authorization_code"); httpClient.field("redirect_uri", this.options.callbackUrl); httpClient.field("client_id", this.options.clientId); httpClient.field("client_secret", this.options.clientSecret); httpClient.parseAs("json"); this.configureAccessTokenRequest(httpClient); if (typeof callback === "function") { callback(httpClient); } const response = await httpClient.post(); const accessTokenResponse = this.processClientResponse(httpClient, response); debug_default("oauth2 access token response %O", accessTokenResponse); const { access_token: accessToken, token_type: tokenType, expires_in: expiresIn, refresh_token: refreshToken, ...parsed } = accessTokenResponse; if (!accessToken) { throw new E_OAUTH_MISSING_TOKEN(E_OAUTH_MISSING_TOKEN.oauth2Message, { cause: parsed }); } return { token: accessToken, type: tokenType, expiresIn, ...expiresIn ? { expiresAt: new Date((/* @__PURE__ */ new Date()).getTime() + 1e3 * expiresIn) } : {}, refreshToken, ...parsed }; } }; export { Oauth2Client }; //# sourceMappingURL=main.js.map