Merge pull request #348 from automatisch/refactor/use-http-client-for-twitter-oauth
refactor: Adjust twitter authentication to use http client
This commit is contained in:
@@ -52,6 +52,7 @@
|
||||
"luxon": "2.3.1",
|
||||
"morgan": "^1.10.0",
|
||||
"nodemailer": "6.7.0",
|
||||
"oauth-1.0a": "^2.2.6",
|
||||
"objection": "^3.0.0",
|
||||
"octokit": "^1.7.1",
|
||||
"pg": "^8.7.1",
|
||||
|
@@ -4,25 +4,37 @@ import type {
|
||||
IField,
|
||||
IJSONObject,
|
||||
} from '@automatisch/types';
|
||||
import TwitterApi, { TwitterApiTokens } from 'twitter-api-v2';
|
||||
import HttpClient from '../../helpers/http-client';
|
||||
import OAuth from 'oauth-1.0a';
|
||||
import crypto from 'crypto';
|
||||
import { URLSearchParams } from 'url';
|
||||
|
||||
export default class Authentication implements IAuthentication {
|
||||
appData: IApp;
|
||||
connectionData: IJSONObject;
|
||||
client: TwitterApi;
|
||||
|
||||
client: HttpClient;
|
||||
oauthClient: OAuth;
|
||||
|
||||
static baseUrl = 'https://api.twitter.com';
|
||||
|
||||
constructor(appData: IApp, connectionData: IJSONObject) {
|
||||
this.appData = appData;
|
||||
this.connectionData = connectionData;
|
||||
|
||||
const clientParams = {
|
||||
appKey: connectionData.consumerKey,
|
||||
appSecret: connectionData.consumerSecret,
|
||||
accessToken: connectionData.accessToken,
|
||||
accessSecret: connectionData.accessSecret,
|
||||
} as TwitterApiTokens;
|
||||
|
||||
this.client = new TwitterApi(clientParams);
|
||||
this.client = new HttpClient({ baseURL: Authentication.baseUrl });
|
||||
this.oauthClient = new OAuth({
|
||||
consumer: {
|
||||
key: this.connectionData.consumerKey as string,
|
||||
secret: this.connectionData.consumerSecret as string,
|
||||
},
|
||||
signature_method: 'HMAC-SHA1',
|
||||
hash_function(base_string, key) {
|
||||
return crypto
|
||||
.createHmac('sha1', key)
|
||||
.update(base_string)
|
||||
.digest('base64');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async createAuthData() {
|
||||
@@ -31,35 +43,83 @@ export default class Authentication implements IAuthentication {
|
||||
);
|
||||
const callbackUrl = appFields.value;
|
||||
|
||||
const authLink = await this.client.generateAuthLink(callbackUrl);
|
||||
const requestData = {
|
||||
url: `${Authentication.baseUrl}/oauth/request_token`,
|
||||
method: 'POST',
|
||||
data: { oauth_callback: callbackUrl },
|
||||
};
|
||||
|
||||
const authHeader = this.oauthClient.toHeader(
|
||||
this.oauthClient.authorize(requestData)
|
||||
);
|
||||
|
||||
try {
|
||||
const response = await this.client.post(`/oauth/request_token`, null, {
|
||||
headers: { ...authHeader },
|
||||
});
|
||||
|
||||
const responseData = Object.fromEntries(
|
||||
new URLSearchParams(response.data)
|
||||
);
|
||||
|
||||
return {
|
||||
url: authLink.url,
|
||||
accessToken: authLink.oauth_token,
|
||||
accessSecret: authLink.oauth_token_secret,
|
||||
url: `${Authentication.baseUrl}/oauth/authorize?oauth_token=${responseData.oauth_token}`,
|
||||
accessToken: responseData.oauth_token,
|
||||
accessSecret: responseData.oauth_token_secret,
|
||||
};
|
||||
} catch (error) {
|
||||
const errorMessages = error.response.data.errors
|
||||
.map((error: IJSONObject) => error.message)
|
||||
.join(' ');
|
||||
|
||||
throw new Error(
|
||||
`Error occured while verifying credentials: ${errorMessages}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async verifyCredentials() {
|
||||
const verifiedCredentials = await this.client.login(
|
||||
this.connectionData.oauthVerifier as string
|
||||
const verifiedCredentials = await this.client.post(
|
||||
`/oauth/access_token?oauth_verifier=${this.connectionData.oauthVerifier}&oauth_token=${this.connectionData.accessToken}`,
|
||||
null
|
||||
);
|
||||
|
||||
const responseData = Object.fromEntries(
|
||||
new URLSearchParams(verifiedCredentials.data)
|
||||
);
|
||||
|
||||
return {
|
||||
consumerKey: this.connectionData.consumerKey,
|
||||
consumerSecret: this.connectionData.consumerSecret,
|
||||
accessToken: verifiedCredentials.accessToken,
|
||||
accessSecret: verifiedCredentials.accessSecret,
|
||||
userId: verifiedCredentials.userId,
|
||||
screenName: verifiedCredentials.screenName,
|
||||
accessToken: responseData.oauth_token,
|
||||
accessSecret: responseData.oauth_token_secret,
|
||||
userId: responseData.user_id,
|
||||
screenName: responseData.screen_name,
|
||||
};
|
||||
}
|
||||
|
||||
async isStillVerified() {
|
||||
try {
|
||||
await this.client.currentUser();
|
||||
const token = {
|
||||
key: this.connectionData.accessToken as string,
|
||||
secret: this.connectionData.accessSecret as string,
|
||||
};
|
||||
|
||||
const requestData = {
|
||||
url: `${Authentication.baseUrl}/1.1/account/verify_credentials.json`,
|
||||
method: 'GET',
|
||||
};
|
||||
|
||||
const authHeader = this.oauthClient.toHeader(
|
||||
this.oauthClient.authorize(requestData, token)
|
||||
);
|
||||
|
||||
await this.client.get(`/1.1/account/verify_credentials.json`, {
|
||||
headers: { ...authHeader },
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch {
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -14012,6 +14012,11 @@ nwsapi@^2.2.0:
|
||||
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
|
||||
integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
|
||||
|
||||
oauth-1.0a@^2.2.6:
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/oauth-1.0a/-/oauth-1.0a-2.2.6.tgz#eadbccdb3bceea412d24586e6f39b2b412f0e491"
|
||||
integrity sha512-6bkxv3N4Gu5lty4viIcIAnq5GbxECviMBeKR3WX/q87SPQ8E8aursPZUtsXDnxCs787af09WPRBLqYrf/lwoYQ==
|
||||
|
||||
oauth-sign@~0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
|
Reference in New Issue
Block a user