esiil
Version:
Minimalist library for EVE Online's ESI
88 lines (81 loc) • 2.86 kB
text/typescript
import {_tokenExchange, _tokenRefresh} from './helpers/Token'
import {importJWK, jwtVerify, JWK, JWTPayload} from 'jose'
import ICcpJwt from "./interfaces/CcpJwt";
import ITokenResponseBody from "./interfaces/responses/TokenResponseBody";
import Defaults from './defaults'
import ITokenServiceResponse from "./interfaces/responses/TokenServiceResponse";
import ITokenPlus from "./interfaces/responses/TokenPlus";
async function _processAuthToken(authToken: string, ccpToken: ICcpJwt) {
const payload = `grant_type=authorization_code&code=${authToken}`
return _handleTokens(await _tokenExchange(payload), ccpToken)
}
async function _refreshTheToken(refreshToken: string, ccpToken: ICcpJwt) {
const payload = [
`grant_type=refresh_token`,
`refresh_token=${refreshToken}`,
`client_id=${Defaults.clientID}`
].join('&')
return _handleTokens(await _tokenRefresh(payload), ccpToken)
}
async function _reduceScope(refreshToken: string, ccpToken: ICcpJwt, updatedScopes: string[]) {
const payload = [
`grant_type=refresh_token`,
`refresh_token=${refreshToken}`,
`client_id=${Defaults.clientID}`,
`scope=${encodeURIComponent(updatedScopes.join(' '))}`
].join('&')
return _handleTokens(await _tokenRefresh(payload), ccpToken)
}
async function _handleTokens(rawSessionToken: ITokenServiceResponse, ccpToken: ICcpJwt): Promise<ITokenPlus> {
try {
if (typeof rawSessionToken.body === 'string') {
throw new Error(`Not a valid object: ${rawSessionToken.body}`)
}
if ("access_token" in rawSessionToken.body) {
const verification: JWTPayload = await _doVerify(ccpToken, rawSessionToken.body.access_token)
if (verification.iss == 'login.eveonline.com') {
const safeCharId = Number(verification.sub?.split(':')[2])
if (safeCharId && typeof verification.owner === 'string') {
const completeTokenData: ITokenPlus = {
character: safeCharId,
owner: verification.owner,
...rawSessionToken.body
}
return completeTokenData
} else {
throw new Error("JWTPayload verification.sub.split(':')[2] not a valid number")
}
} else {
throw new Error(`Could not verify JWT`)
}
}
} catch (err) {
console.log('err')
console.log(err)
}
return {
access_token: '',
expires_in: 0,
token_type: '',
refresh_token: '',
character: 0,
owner: ''
}
}
async function _doVerify(ccpToken: ICcpJwt, accessToken: string) {
const ccpJwk = await importJWK(_ccpToJwk(ccpToken), 'RS256')
const { payload, protectedHeader } = await jwtVerify(accessToken, ccpJwk, {})
return payload
}
function _ccpToJwk(token: ICcpJwt): JWK {
return {
kty: token.kty,
e: token.e,
n:token.n
}
}
export {
_processAuthToken,
_refreshTheToken,
_reduceScope
}