oauth2orize
oauth2orize copied to clipboard
Authorization Code redirect call in case of error
Is there a mechanism to send to the redirect_uri some custom query parameters in case of error? (I'm talking about https://localhost:8080/oauth2/authorize/decision endpoint)
Expected behavior
In case there is an error on
server.grant(oauth2orize.grant.code((client, redirectUri, user, ares, done) => {...});
it should call the redirect_uri with an error description as a query parameter.
Actual behavior
Instead, a json response containing the error description is returned.
{"error":"server_error","error_description":"The database service encountered an unexpected error."}
What error handling middleware is being used on that endpoint?
Thank you for responding.
The code I use is this. However, the error handler I wrote at the end is not called in case of error. I think the error handling is done internally, or I did not specify one? Can you help me with a solution to this?
//////////////////////////////oauth2.js/////////////////////////
server.exchange(oauth2orize.exchange.code((client, code, redirectUri, done) => {
// This code can either be for service/credential authorization. It should be found by value
Code.findOne({ value: code, client_id: client._id }, function (err, authCode) {
if (err) { return done(err); }
if (authCode === undefined || authCode === null) { return done(errors.internalServerError); }
if (client._id.toString() !== authCode.client_id) { return done(errors.invalidClientId); }
if (redirectUri !== authCode.redirect_uri) { return done(errors.notMatchRedirectUri); }
// check token availability
if (authCode.creation_date.getTime() + 1000 * config.settings.code_expiring_time < Date.now()) { return done(errors.invalidCode, false); }
switch (authCode.scope) {
case 'service':
crypto.randomBytes(256, function (err, buffer) {
if (err) return done(errors.internalServerError);
const tokenValue = buffer.toString('hex');
Token.updateOne({ client_id: authCode.client_id, type: 'access_token' }, {
value: tokenValue,
type: 'access_token',
user_id: authCode.user_id,
client_id: authCode.client_id
}, { upsert: true }, (err) => {
if (err) return done(errors.databaseError);
done(null, tokenValue, { token_type: "Bearer", expiresIn: config.settings.csc.access_token_expiring_time });
});
});
break;
case 'credential':
//generate SAD. It gets deleted when the signature is done
crypto.randomBytes(128, function (err, buffer) {
if (err) return done(errors.internalServerError);
const sadValue = buffer.toString('hex');
const sad = new Sad({
value: sadValue,
hashes: authCode.hashes,
credential_id: authCode.credential_id
});
sad.save((err) => {
if (err) return done(errors.databaseError);
// send response
done(null, sadValue, { token_type: "SAD", expiresIn: config.settings.csc.sad_expiring_time });
});
});
break;
default:
done(errors.internalServerError);
}
});
}));
module.exports.decision = [
login.ensureLoggedIn(),
server.decision(function (req, done) {
return done(null, {
scope: req.oauth2.req.scope,
credentialID: req.body.credentialID,
hash: req.body.hash,
numSignatures: +req.body.num_signatures
}) // this is ares
}) // invokes server.grant()
];
//////////////////app.js////////////////////
app.post(`/oauth2/authorize/decision`, require('./routes/oauth2').decision);
// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
req.app.get('env') === 'development' ? logger.info(err) : {};
// render the error page
if (err.status !== undefined) {
res.status(err.status);
return res.json({
error: err.message,
error_description: err.description
});
}
// fallback for unknown application errors
res.status(errors.internalServerError.status);
res.json({
error: errors.internalServerError.message,
error_description: errors.internalServerError.description
});
});