@adonisjs/ally
Version:
Social authentication provider for AdonisJS
170 lines (168 loc) • 4.81 kB
JavaScript
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
};