@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
JavaScript
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