调用休息时,keycloak 注销不会使令牌无效 api

keycloak logout doesn't invalidate token when call a rest api

我有一个使用 Keycloak 作为身份验证服务的 React 应用程序。此外,我还有一个 Nodejs rest api,其端点由 keycloak 保护,因此 React 应用程序在需要调用 api 时发送 JWT。在 Keycloak 管理控制台中,我创建了 1 个 public 具有用户和角色的客户端。

一切正常,但唯一的问题是当我通过管理控制台注销时,或者 在到期时间之前从我的 React 应用程序,我仍然可以使用这些令牌调用我的应用程序。

为什么我的后端应用程序不使用服务器验证令牌?

我的节点应用程序使用 keycloak-node-connect 适配器,我的 keycloak.json 是:

{
    "client-id": "my-public-client",
    "bearer-only": true,
    "auth-server-url": "http://localhost:8180/auth",
    "realm": "my-realm"    
}

已解决

我可以按照

中的建议解决我的问题

keycloak.config.js

var session = require('express-session');
var Keycloak = require('keycloak-connect');
var request = require('request');
const createError = require('http-errors');

let _keycloak;

var memoryStore = new session.MemoryStore();

function initKeycloak() {
    if (_keycloak) {
        console.log("Trying to init Keycloak again!");
        return _keycloak;
    }
    else {
        console.log("Initializing Keycloak...");
        _keycloak = new Keycloak({ store: memoryStore });
        return _keycloak;
    }
}

function getKeycloak() {
    if (!_keycloak) {
        console.error('Keycloak has not been initialized. Please called init first.');
    }
    return _keycloak;
}

async function validateTokenKeycloak(req, res, next) {
    if (req.kauth && req.kauth.grant) {        
        console.log('--- Verify token ---');
        try {
            var result = await _keycloak.grantManager.userInfo(req.kauth.grant.access_token);
            //var result = await _keycloak.grantManager.validateAccessToken(req.kauth.grant.access_token);
            if(!result) {
                console.log(`result:`,  result); 
                throw Error('Invalid Token');
            }                        
        } catch (error) {
            console.log(`Error: ${error.message}`);
            return next(createError.Unauthorized());
        }
    }
    next();  
}

module.exports = {
    memoryStore,
    initKeycloak,
    getKeycloak,
    validateTokenKeycloak
};

app.js

const express = require('express');
const createError = require('http-errors');
const dotenv = require('dotenv').config();
const session = require('express-session');
const keycloakConfig = require('./config/keycloak.config');

const app = express();

// Keycloak
app.use(session({
    secret: 'secret',
    resave: false,
    saveUninitialized: true,
    store: keycloakConfig.memoryStore
}));
  
const keycloak = keycloakConfig.initKeycloak();
  
app.use(keycloak.middleware());

app.use(keycloakConfig.validateTokenKeycloak);

app.use("/health", require('./routes/health.route'));

// 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) => {  
    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}`);
});