Skip to content

Commit

Permalink
@uppy/companion: catch "invalid initialization vector" instead of cra…
Browse files Browse the repository at this point in the history
…shing (#4661)

prevent crashing companion

when async function rejects promise unhandled
  • Loading branch information
mifi authored Sep 6, 2023
1 parent 57336a1 commit a4b8683
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 31 deletions.
1 change: 1 addition & 0 deletions packages/@uppy/companion/src/server/helpers/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ module.exports.decrypt = (encrypted, secret) => {
throw new Error('Invalid encrypted value. Maybe it was generated with an old Companion version?')
}

// NOTE: The first 32 characters are the iv, in hex format. The rest is the encrypted string, in base64 format.
const iv = Buffer.from(encrypted.slice(0, 32), 'hex')
const encryptionWithoutIv = encrypted.slice(32)

Expand Down
64 changes: 33 additions & 31 deletions packages/@uppy/companion/src/server/provider/credentials.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,42 +70,44 @@ async function fetchProviderKeys (providerName, companionOptions, credentialRequ
*/
exports.getCredentialsOverrideMiddleware = (providers, companionOptions) => {
return async (req, res, next) => {
const { authProvider, override } = req.params
const [providerName] = Object.keys(providers).filter((name) => providers[name].authProvider === authProvider)
if (!providerName) {
next()
return
}
try {
const { authProvider, override } = req.params
const [providerName] = Object.keys(providers).filter((name) => providers[name].authProvider === authProvider)
if (!providerName) {
next()
return
}

if (!companionOptions.providerOptions[providerName]?.credentialsURL) {
next()
return
}
if (!companionOptions.providerOptions[providerName]?.credentialsURL) {
next()
return
}

const dynamic = oAuthState.getDynamicStateFromRequest(req)
// only use state via session object if user isn't making intial "connect" request.
// override param indicates subsequent requests from the oauth flow
const state = override ? dynamic : req.query.state
if (!state) {
next()
return
}
const dynamicState = oAuthState.getDynamicStateFromRequest(req)
// only use state via session object if user isn't making intial "connect" request.
// override param indicates subsequent requests from the oauth flow
const state = override ? dynamicState : req.query.state
if (!state) {
next()
return
}

const preAuthToken = oAuthState.getFromState(state, 'preAuthToken', companionOptions.secret)
if (!preAuthToken) {
next()
return
}
// pre auth token is companionKeysParams encoded and encrypted by companion before the oauth flow,
// I believe this has been done so that it cannot be modified by the client later.
const preAuthToken = oAuthState.getFromState(state, 'preAuthToken', companionOptions.secret)
if (!preAuthToken) {
next()
return
}

let payload
try {
payload = tokenService.verifyEncryptedToken(preAuthToken, companionOptions.preAuthSecret)
} catch (err) {
next()
return
}
let payload
try {
payload = tokenService.verifyEncryptedToken(preAuthToken, companionOptions.preAuthSecret)
} catch (err) {
next()
return
}

try {
const credentials = await fetchProviderKeys(providerName, companionOptions, payload)

res.locals.grant = {
Expand Down

0 comments on commit a4b8683

Please sign in to comment.