Как пользовательское сообщение об ошибке скрытия ключей в NodeJS

#node.js #keycloak #keycloak-rest-api

#node.js #keycloak #keycloak-rest-api

Вопрос:

Я новичок в node, у меня есть rest api с express, а некоторые конечные точки имеют защиту от скрытого доступа с использованием keycloak-connect. Мне нужен пользовательский ответ при обнаружении ошибки 403, то есть пользовательское сообщение в формате json. Я использую обработчик для управления каким-либо другим статусом, например, 200, 201, 204, 404, 500, но я не смог выполнить работы, когда keycloak выдает 403.

 var memoryStore = new session.MemoryStore();

app.use(session({
  secret: 'my-secret',
  resave: false,
  saveUninitialized: true,
  store: memoryStore
}));

var keycloak = new Keycloak({
  store: memoryStore
});

app.use(keycloak.middleware());

// keycloak security
app.get('/service/secured', keycloak.protect('realm:user'), function (req, res) {
  res.json({message: 'secured'});
});

app.get('/service/admin', keycloak.protect('realm:admin'), function (req, res) {
  res.json({message: 'admin'});
});

// 404 handler and pass to error handler
app.use((req, res, next) => {    
    next(createError(404, 'Not found'));
});

// Error Handler
app.use((err, req, res, next) => { 
    // This log never is printed when 403 ocurrs
    console.log('Error: ', err); 
    res.status(err.status || 500);
    res.send({
        error : {
            status : err.status || 500,
            message : err.message
        }
    });
});

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
    console.log(`Server starter on port ${PORT}`);
});
  

Ответ №1:

Проблема в том, что keycloak-connect неправильно использует промежуточное программное обеспечение express. Оно использует res.end() вместо next() , поэтому вы ничего не можете сделать после этого. Вы можете попробовать переписать эту логику, добавив новое промежуточное программное обеспечение.

 ...

app.use(function(req, res, next) {
  res.end = function(body) {
    if (res.statusCode === 403 amp;amp; body === 'Access denied') {
      next(body);
    } else {
      res.send(body);
    }
  }
});

app.use(keycloak.middleware());

...

// handle error how you want
  

Комментарии:

1. Запрос просто истекает. Как мне вернуть пользовательский объект ответа вместо Access denied текста по умолчанию

2. @odane-brissett У вас есть обработчик ошибок маршрутизатора? expressjs.com/en/guide/error-handling.html Вот так: app.use(function (err, req, res, next) { console.error(err.stack); res.status(500).send('Something broke!'); });

Ответ №2:

Вы можете переопределить Keycloak.prototype.accessDenied перед инициализацией и выдать новую ошибку, чтобы ваш дескриптор мог ее обработать.

 var memoryStore = new session.MemoryStore();

app.use(session({
  secret: 'my-secret',
  resave: false,
  saveUninitialized: true,
  store: memoryStore
}));

// Overriding keycloak access denied to return 401 status code and custom message.
Keycloak.prototype.accessDenied = () => {
  // Considering createError will throw new Error.
  createError(401, 'Access Denied');
};

var keycloak = new Keycloak({
  store: memoryStore
});

app.use(keycloak.middleware());

// keycloak security
app.get('/service/secured', keycloak.protect('realm:user'), function (req, res) {
  res.json({message: 'secured'});
});

app.get('/service/admin', keycloak.protect('realm:admin'), function (req, res) {
  res.json({message: 'admin'});
});

// 404 handler and pass to error handler
app.use((req, res, next) => {    
    next(createError(404, 'Not found'));
});

// Error Handler
app.use((err, req, res, next) => { 
    // Now this print with error 401 and message Access Denied
    console.log('Error: ', err); 
    res.status(err.status || 500);
    res.send({
        error : {
            status : err.status || 500,
            message : err.message
        }
    });
});

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
    console.log(`Server starter on port ${PORT}`);
});