UNPKG

@adonisjs/ally

Version:

Social authentication provider for AdonisJS

170 lines (168 loc) 4.81 kB
import { Oauth2Driver } from "../../chunk-EXGR73T6.js"; import "../../chunk-NK6X76EQ.js"; import "../../chunk-TSIMPJ6I.js"; // src/drivers/twitter_x.ts var TwitterXDriver = class extends Oauth2Driver { /** * Create a new X driver instance. * * @param ctx - The current HTTP context. * @param config - X driver configuration. */ constructor(ctx, config) { super(ctx, config); this.config = config; this.loadState(); } config; /** * X token endpoint URL. */ accessTokenUrl = "https://api.x.com/2/oauth2/token"; /** * X authorization endpoint URL. */ authorizeUrl = "https://x.com/i/oauth2/authorize"; /** * X user profile endpoint URL. */ userInfoUrl = "https://api.x.com/2/users/me"; /** * The param name for the authorization code */ codeParamName = "code"; /** * The param name for the error */ errorParamName = "error"; /** * Cookie name for storing the "twitter_x_oauth_state" */ stateCookieName = "twitter_x_oauth_state"; /** * Cookie name for storing the PKCE code verifier */ codeVerifierCookieName = "twitter_x_oauth_code_verifier"; /** * Parameter name to be used for sending and receiving the state from X */ stateParamName = "state"; /** * Parameter name for defining the scopes */ scopeParamName = "scope"; /** * Scopes separator */ scopesSeparator = " "; /** * Configures the redirect request with X-specific requirements. * * @param request - The redirect request to configure. */ configureRedirectRequest(request) { request.scopes(this.config.scopes || ["tweet.read", "users.read", "users.email"]); request.param("response_type", "code"); } /** * Configures the token request with the PKCE verifier and the Basic auth * header required for confidential X clients. * * @param request - The token request to configure. */ configureAccessTokenRequest(request) { const credentials = Buffer.from(`${this.config.clientId}:${this.config.clientSecret}`).toString( "base64" ); request.header("Authorization", `Basic ${credentials}`); request.clearField("client_id"); request.clearField("client_secret"); } /** * Creates an authenticated request for X API calls. * * @param url - The API endpoint URL. * @param token - The access token to send. * @returns A configured HTTP client instance. */ getAuthenticatedRequest(url, token) { const request = this.httpClient(url); request.header("Authorization", `Bearer ${token}`); request.header("Accept", "application/json"); request.parseAs("json"); return request; } /** * Fetches the authenticated user's profile from /2/users/me. * * @param token - The access token to use. * @param includeConfirmedEmail - Whether to request the confirmed email field. * @param callback - Optional callback to customize the API request. */ async getUserInfo(token, includeConfirmedEmail, callback) { const request = this.getAuthenticatedRequest(this.config.userInfoUrl || this.userInfoUrl, token); request.param( "user.fields", includeConfirmedEmail ? "profile_image_url,confirmed_email" : "profile_image_url" ); if (typeof callback === "function") { callback(request); } const body = await request.get(); const user = body.data; return { id: user.id, nickName: user.username, name: user.name ?? user.username, email: user.confirmed_email ?? null, emailVerificationState: "unsupported", avatarUrl: user.profile_image_url ?? null, original: body }; } /** * Check if the error from the callback indicates that the user denied * authorization. * * @returns `true` when the provider reported an access-denied error. */ accessDenied() { const error = this.getError(); if (!error) { return false; } return error === "access_denied"; } /** * Fetches the authenticated user using the authorization code from the * callback request. * * @param callback - Optional callback to customize the API request. */ async user(callback) { const token = await this.accessToken(callback); const user = await this.getUserInfo(token.token, token.scope.includes("users.email"), callback); return { ...user, token }; } /** * Fetches the user profile using an existing access token. * * @param token - The access token to use. * @param callback - Optional callback to customize the API request. */ async userFromToken(token, callback) { const user = await this.getUserInfo(token, false, callback); return { ...user, token: { token, type: "bearer" } }; } }; export { TwitterXDriver };