enhancement: add validation for custom U&P OAuth callbacks

This commit is contained in:
Convly 2024-04-05 09:12:04 +02:00
parent 2fe3160287
commit e762295cbe
2 changed files with 35 additions and 4 deletions

View File

@ -18,6 +18,19 @@ module.exports = {
},
},
},
callback: {
validate(url, provider) {
const uCallback = new URL(url);
const uRedirect = new URL(provider.redirectUri);
// The default validation checks that the provided callback's origin matches the provider redirectUri origin
if (uCallback.origin !== uRedirect.origin) {
throw new Error(
`Forbidden callback provided: origins don't match (${uCallback.origin} !== ${uRedirect.origin})`
);
}
},
},
}),
validator() {},
};

View File

@ -201,10 +201,28 @@ module.exports = {
}
// Ability to pass OAuth callback dynamically
grantConfig[provider].callback =
_.get(ctx, 'query.callback') ||
_.get(ctx, 'session.grant.dynamic.callback') ||
grantConfig[provider].callback;
const queryCustomCallback = _.get(ctx, 'query.callback');
const dynamicSessionCallback = _.get(ctx, 'session.grant.dynamic.callback');
const customCallback = queryCustomCallback ?? dynamicSessionCallback;
// The custom callback is validated to make sure it's not redirecting to an unwanted actor.
if (customCallback !== undefined) {
try {
// We're extracting the callback validator from the plugin config since it can be user-customized
const { validate: validateCallback } = strapi
.plugin('users-permissions')
.config('callback');
await validateCallback(customCallback, grantConfig[provider]);
grantConfig[provider].callback = customCallback;
} catch (e) {
strapi.log.warn(e.message);
}
}
// Build a valid redirect URI for the current provider
grantConfig[provider].redirect_uri = getService('providers').buildRedirectUri(provider);
return grant(grantConfig)(ctx, next);