增加twitter auth v1

This commit is contained in:
CounterFire2023 2024-04-22 22:05:37 +08:00
parent 1ea077ca93
commit 3691d000da
5 changed files with 141 additions and 1 deletions

View File

@ -16,10 +16,12 @@
"author": "zhl",
"license": "ISC",
"dependencies": {
"@fastify/cookie": "^9.3.1",
"@fastify/cors": "^8.1.0",
"@fastify/formbody": "^7.3.0",
"@fastify/helmet": "^10.0.1",
"@fastify/jwt": "^6.3.2",
"@fastify/session": "^10.7.2",
"@fastify/view": "^7.4.1",
"@typegoose/typegoose": "9.12.1",
"axios": "^1.1.3",
@ -34,6 +36,7 @@
"mongoose-findorcreate": "^3.0.0",
"nanoid": "^3.1.23",
"node-schedule": "^2.1.1",
"oauth": "^0.10.0",
"tracer": "^1.1.6"
},
"devDependencies": {

View File

@ -29,6 +29,16 @@ export class ApiServer {
console.log('version::' + process.version)
}
private registerPlugins() {
this.server.register(require('@fastify/cookie'))
this.server.register(require('@fastify/session'), {
cookieName: 'sessionId',
secret: process.env.COOKIE_SECRET,
cookie: { secure: false },
expires: 900000,
})
this.server.addHook('preHandler', (request, reply, next) => {
next()
})
this.server.register(require('@fastify/formbody'))
this.server.register(zReqParserPlugin)
this.server.register(helmet, {

View File

@ -1,8 +1,14 @@
import { ZError } from 'common/ZError'
import BaseController, { ROLE_ANON } from 'common/base.controller'
import { role, router } from 'decorators/router'
import logger from 'logger/logger'
import { AuthRecord } from 'modules/AuthRecord'
import { exchangeTwitterCodeForToken, getTwitterUserInfo } from 'services/twitter.svr'
import {
exchangeTwitterCodeForToken,
getOAuthAccessTokenWith,
getOAuthRequestToken,
getTwitterUserInfo,
} from 'services/twitter.svr'
import { parseOauthState } from 'utils/net.util'
class TwitterController extends BaseController {
@ -51,4 +57,51 @@ class TwitterController extends BaseController {
}
return res.view('/templates/twitter_redirect.ejs')
}
@role(ROLE_ANON)
@router('get /twitter/oauth/:address')
async twitterOauth1(req, res) {
let method = 'authenticate'
let { address } = req.params
if (!address) {
throw new ZError(10, 'address needed')
}
address = address.toLowerCase()
// @ts-ignore
const { oauthRequestToken, oauthRequestTokenSecret } = await getOAuthRequestToken()
console.log(`/oauth/twitter} ->`, { oauthRequestToken, oauthRequestTokenSecret })
req.session.oauthRequestToken = oauthRequestToken
req.session.oauthRequestTokenSecret = oauthRequestTokenSecret
req.session.address = address
const authorizationUrl = `https://api.twitter.com/oauth/${method}?oauth_token=${oauthRequestToken}`
console.log('redirecting user to ', authorizationUrl)
res.redirect(authorizationUrl)
}
// for twitter oauth v1.0
@role(ROLE_ANON)
@router('get /twitter/callback')
async twitterOauth1Callback(req, res) {
const { address, oauthRequestToken, oauthRequestTokenSecret } = req.session
console.log('request.query', req.query)
const { oauth_verifier: oauthVerifier } = req.query
const { oauthAccessToken, oauthAccessTokenSecret, results } = await getOAuthAccessTokenWith({
oauthRequestToken,
oauthRequestTokenSecret,
oauthVerifier,
})
const { user_id: userId /*, screen_name */ } = results
console.log('userId:', userId)
const record = await AuthRecord.insertOrUpdate(
{ address, platform: 4 },
{ address, platform: 4, $inc: { version: 1 } },
)
record.nickname = results.screen_name
record.username = results.screen_name
record.openId = results.user_id
record.accessToken = oauthAccessToken
record.refreshToken = oauthAccessTokenSecret
record.tokenType = 'oauth1'
await record.save()
return res.view('/templates/twitter_redirect.ejs')
}
}

View File

@ -1,5 +1,7 @@
const consumerKey = process.env.TWITTER_CLIENT_ID
const consumerSecret = process.env.TWITTER_CLIENT_SECRET
import { OAuth } from 'oauth'
import { promisify } from 'util'
export async function exchangeTwitterCodeForToken(code: string, vcode: string) {
const url = 'https://api.twitter.com/2/oauth2/token'
@ -63,3 +65,49 @@ export async function getTwitterUserInfo(accessToken: string) {
const data = await response.json()
return data
}
var oauthConsumer = new OAuth(
'https://api.twitter.com/oauth/request_token',
'https://api.twitter.com/oauth/access_token',
process.env.TWITTER_API_KEY,
process.env.TWITTER_API_SECRET,
'1.0A',
process.env.TWITTER_OAUTH1_CB,
'HMAC-SHA1',
)
export async function getOAuthAccessTokenWith({
oauthRequestToken,
oauthRequestTokenSecret,
oauthVerifier,
}: any = {}): Promise<any> {
return new Promise((resolve, reject) => {
oauthConsumer.getOAuthAccessToken(
oauthRequestToken,
oauthRequestTokenSecret,
oauthVerifier,
function (error, oauthAccessToken, oauthAccessTokenSecret, results) {
return error
? reject(new Error('Error getting OAuth access token'))
: resolve({ oauthAccessToken, oauthAccessTokenSecret, results })
},
)
})
}
export async function getOAuthRequestToken() {
return new Promise((resolve, reject) => {
oauthConsumer.getOAuthRequestToken(function (error, oauthRequestToken, oauthRequestTokenSecret, results) {
return error
? reject(new Error('Error getting OAuth request token'))
: resolve({ oauthRequestToken, oauthRequestTokenSecret, results })
})
})
}
export async function oauthGetUserById(userId, { oauthAccessToken, oauthAccessTokenSecret }: any = {}) {
return promisify(oauthConsumer.get.bind(oauthConsumer))(
`https://api.twitter.com/1.1/users/show.json?user_id=${userId}`,
oauthAccessToken,
oauthAccessTokenSecret,
).then(body => JSON.parse(body))
}

View File

@ -109,6 +109,14 @@
ajv-formats "^2.1.1"
fast-uri "^2.0.0"
"@fastify/cookie@^9.3.1":
version "9.3.1"
resolved "https://registry.yarnpkg.com/@fastify/cookie/-/cookie-9.3.1.tgz#48b89a356a23860c666e2fe522a084cc5c943d33"
integrity sha512-h1NAEhB266+ZbZ0e9qUE6NnNR07i7DnNXWG9VbbZ8uC6O/hxHpl+Zoe5sw1yfdZ2U6XhToUGDnzQtWJdCaPwfg==
dependencies:
cookie-signature "^1.1.0"
fastify-plugin "^4.0.0"
"@fastify/cors@^8.1.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@fastify/cors/-/cors-8.3.0.tgz#f03d745731b770793a1a15344da7220ca0d19619"
@ -161,6 +169,14 @@
fastify-plugin "^4.0.0"
steed "^1.1.3"
"@fastify/session@^10.7.2":
version "10.7.2"
resolved "https://registry.yarnpkg.com/@fastify/session/-/session-10.7.2.tgz#8c4441133257075fc7eb79ce31b9a9d594e32ea8"
integrity sha512-PezR26nY8FMmAs4cww5rpnVyRkPDv2WQcVBLEKrtLTQy8mjL+twUKv9TLo/SXZYHZOIETzmquWoLYlnY3dSb+w==
dependencies:
fastify-plugin "^4.0.0"
safe-stable-stringify "^2.3.1"
"@fastify/view@^7.4.1":
version "7.4.1"
resolved "https://registry.yarnpkg.com/@fastify/view/-/view-7.4.1.tgz#265daba48386a5d3f69dfc446af468d72e0a8757"
@ -727,6 +743,11 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
cookie-signature@^1.1.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.1.tgz#790dea2cce64638c7ae04d9fabed193bd7ccf3b4"
integrity sha512-78KWk9T26NhzXtuL26cIJ8/qNHANyJ/ZYrmEXFzUmhZdjpBv+DlWlOANRTGBt48YcyslsLrj0bMLFTmXvLRCOw==
cookie@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
@ -1763,6 +1784,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
oauth@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.10.0.tgz#3551c4c9b95c53ea437e1e21e46b649482339c58"
integrity sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==
obliterator@^2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816"