优化twitter oauth流程

This commit is contained in:
CounterFire2023 2023-06-21 11:27:15 +08:00
parent f039e796e5
commit 7fd65ba0bb
4 changed files with 78 additions and 51 deletions

View File

@ -4,6 +4,7 @@ import { role, router } from 'decorators/router'
import logger from 'logger/logger' import logger from 'logger/logger'
import { AuthRecord } from 'modules/AuthRecord' import { AuthRecord } from 'modules/AuthRecord'
import { DiscordSvr, exchangeDiscrodCodeForToken, userInfo } from 'services/discord.svr' import { DiscordSvr, exchangeDiscrodCodeForToken, userInfo } from 'services/discord.svr'
import { parseOauthState } from 'utils/net.util'
class DiscordController extends BaseController { class DiscordController extends BaseController {
@role(ROLE_ANON) @role(ROLE_ANON)
@ -11,7 +12,7 @@ class DiscordController extends BaseController {
async discordCallback(req, res) { async discordCallback(req, res) {
let { code, state } = req.params let { code, state } = req.params
if (code && state) { if (code && state) {
const stateArr = state.split('|') const stateArr = parseOauthState(state)
const address = stateArr[0].toLowerCase() const address = stateArr[0].toLowerCase()
const record = await AuthRecord.insertOrUpdate( const record = await AuthRecord.insertOrUpdate(
{ address, platform: 7 }, { address, platform: 7 },
@ -22,17 +23,26 @@ class DiscordController extends BaseController {
record.refreshToken = tokenResponse.refresh_token record.refreshToken = tokenResponse.refresh_token
record.scope = tokenResponse.scope record.scope = tokenResponse.scope
record.tokenType = tokenResponse.token_type record.tokenType = tokenResponse.token_type
record.expiresIn = tokenResponse.expires_in + Date.now() record.expiresIn = tokenResponse.expires_in || 0 + Date.now()
await record.save() await record.save()
let uinfo = await userInfo(tokenResponse.access_token) if (tokenResponse && tokenResponse.access_token) {
record.nickname = uinfo.username let uinfo = await userInfo(tokenResponse.access_token)
record.username = uinfo.username record.nickname = uinfo.username
record.discriminator = uinfo.discriminator record.username = uinfo.username
record.openId = uinfo.id record.discriminator = uinfo.discriminator
await record.save() record.openId = uinfo.id
return res.view('/templates/discord_redirect.ejs') await record.save()
} else { }
return res.view('/templates/discord_redirect.ejs') if (stateArr.length > 2) {
return res.redirect(stateArr[2])
}
} }
if (state) {
const stateArr = parseOauthState(state)
if (stateArr.length > 2) {
return res.redirect(stateArr[2])
}
}
return res.view('/templates/discord_redirect.ejs')
} }
} }

View File

@ -1,9 +1,9 @@
import BaseController, { ROLE_ANON } from 'common/base.controller' import BaseController, { ROLE_ANON } from 'common/base.controller'
import { ZError } from 'common/ZError'
import { role, router } from 'decorators/router' import { role, router } from 'decorators/router'
import logger from 'logger/logger' import logger from 'logger/logger'
import { AuthRecord } from 'modules/AuthRecord' import { AuthRecord } from 'modules/AuthRecord'
import { exchangeTwitterCodeForToken, getTwitterUserInfo } from 'services/twitter.svr' import { exchangeTwitterCodeForToken, getTwitterUserInfo } from 'services/twitter.svr'
import { parseOauthState } from 'utils/net.util'
class TwitterController extends BaseController { class TwitterController extends BaseController {
@role(ROLE_ANON) @role(ROLE_ANON)
@ -12,7 +12,7 @@ class TwitterController extends BaseController {
logger.info('twitter redirect: ', req.params) logger.info('twitter redirect: ', req.params)
const { code, state } = req.params const { code, state } = req.params
if (code && state) { if (code && state) {
const stateArr = state.split('|') const stateArr = parseOauthState(state)
const address = stateArr[0].toLowerCase() const address = stateArr[0].toLowerCase()
const record = await AuthRecord.insertOrUpdate( const record = await AuthRecord.insertOrUpdate(
{ address, platform: 4 }, { address, platform: 4 },
@ -24,13 +24,24 @@ class TwitterController extends BaseController {
record.refreshToken = tokenResponse.refresh_token record.refreshToken = tokenResponse.refresh_token
record.scope = tokenResponse.scope record.scope = tokenResponse.scope
record.tokenType = tokenResponse.token_type record.tokenType = tokenResponse.token_type
record.expiresIn = tokenResponse.expires_in + Date.now() record.expiresIn = tokenResponse.expires_in || 0 + Date.now()
await record.save()
const uinfo = await getTwitterUserInfo(tokenResponse.access_token)
record.nickname = uinfo.data.name
record.username = uinfo.data.username
record.openId = uinfo.data.id
await record.save() await record.save()
if (tokenResponse && tokenResponse.access_token) {
const uinfo = await getTwitterUserInfo(tokenResponse.access_token)
record.nickname = uinfo.data.name
record.username = uinfo.data.username
record.openId = uinfo.data.id
await record.save()
}
if (stateArr.length > 2) {
return res.redirect(stateArr[2])
}
}
if (state) {
const stateArr = parseOauthState(state)
if (stateArr.length > 2) {
return res.redirect(stateArr[2])
}
} }
return res.view('/templates/twitter_redirect.ejs') return res.view('/templates/twitter_redirect.ejs')
} }

View File

@ -128,38 +128,38 @@ export function generateKVStr({
sort = false, sort = false,
encode = false, encode = false,
ignoreNull = true, ignoreNull = true,
splitChar = "&", splitChar = '&',
equalChar = "=", equalChar = '=',
uri = "", uri = '',
}: { }: {
data?: any; data?: any
sort?: boolean; sort?: boolean
encode?: boolean; encode?: boolean
ignoreNull?: boolean; ignoreNull?: boolean
splitChar?: string; splitChar?: string
equalChar?: string; equalChar?: string
uri?: string; uri?: string
}) { }) {
const keys = Object.keys(data); const keys = Object.keys(data)
sort && keys.sort(); sort && keys.sort()
let result = ""; let result = ''
let i = 0; let i = 0
for (let key of keys) { for (let key of keys) {
if (ignoreNull && !data[key]) { if (ignoreNull && !data[key]) {
continue; continue
} }
if (i++ > 0) result += splitChar; if (i++ > 0) result += splitChar
if (encode) { if (encode) {
result += `${key}${equalChar}${encodeURIComponent(data[key])}`; result += `${key}${equalChar}${encodeURIComponent(data[key])}`
} else { } else {
result += `${key}${equalChar}${data[key]}`; result += `${key}${equalChar}${data[key]}`
} }
} }
if (uri) { if (uri) {
const joinChar = uri.search(/\?/) === -1 ? "?" : "&"; const joinChar = uri.search(/\?/) === -1 ? '?' : '&'
result = uri + joinChar + result; result = uri + joinChar + result
} }
return result; return result
} }
/** /**
@ -168,19 +168,23 @@ export function generateKVStr({
* @param splitChar , & * @param splitChar , &
* @param equalChar = * @param equalChar =
*/ */
export function keyValToObject( export function keyValToObject(str: string, splitChar: string = '&', equalChar = '='): {} {
str: string, let result: any = {}
splitChar: string = "&",
equalChar = "="
): {} {
let result: any = {};
if (!str) { if (!str) {
return result; return result
} }
let arrs = str.split(splitChar); let arrs = str.split(splitChar)
for (let sub of arrs) { for (let sub of arrs) {
let subArr = sub.split(equalChar); let subArr = sub.split(equalChar)
result[subArr[0]] = subArr[1]; result[subArr[0]] = subArr[1]
}
return result
}
export function parseOauthState(state: string) {
if (state.startsWith('0x')) {
return state.split('|')
} else {
return atob(state).split('|')
} }
return result;
} }

View File

@ -15,6 +15,8 @@
<body> <body>
<script> <script>
(function() { (function() {
// const bc = new BroadcastChannel("cebg")
// bc.postMessage("twitter login finished")
window.close(); window.close();
})(); })();
</script> </script>