I am using keycloak21.0.2 in a docker container. When I try to make a get request from frontend react app.
Example:
const fetchProducts = async () => {
try {
if (keycloak.authenticated) {
const token = keycloak.token;
const res = await axios.get('/products', {
headers: {
'Authorization': `Bearer ${token}`,
},
});
setProducts(res.data);
}
} catch (err) {
console.error(err);
}
};
The error I get is
Access to XMLHttpRequest at 'http://localhost:8080/realms/project-realm/protocol/openid-connect/auth?client_id=project-api&state=294ff742-1f88-404b-8207-1ce4301fb9d2&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Fproducts%3Fauth_callback%3D1&scope=openid&response_type=code' (redirected from 'http://localhost:5000/products') from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
My react app client in keycloak is public type and is properly working on the frontend after logging in. Bearer token is properly passed to the API but it cors blocks it. I even have origin set to origin: '*', even though It is a bad practice it still does not make it work.
For backend I have client authentication and authorization turned on. Config for frontend is very similiar as in the picture above it's just localhost:3000 instead of localhost:5000.
My api connected to mongodb database looks like that
const bodyParser = require('body-parser');
const express = require('express');
const {NodeAdapter} = require('ef-keycloak-connect');
const mongoose = require('mongoose');
const cors=require("cors");
const session = require('express-session');
const memoryStore = new session.MemoryStore();
const app = express();
const config = {
"realm": "project-realm",
"auth-server-url": "http://localhost:8080/",
"ssl-required": "external",
"resource": "project-api",
"verify-token-audience": true,
"credentials": {
"secret": "secret"
},
"confidential-port": 0,
"policy-enforcer": {}
}
const keycloak = new NodeAdapter(config);
app.use(cors({
origin: '*'
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: true,
store: memoryStore
}));
app.use(keycloak.middleware());
const productsRouter = require('./routes/products');
app.use('/products', keycloak.protect(), productsRouter);
and an example route
router.get('/', async (req, res) => {
try {
const roles = req.kauth.grant?.access_token.content.realm_access.roles;
const isAdmin = roles?.some(role => role === 'admin');
let products;
if (isAdmin) {
products = await Product.find({});
} else {
products = await Product.find({ isPublic: true });
}
res.json(products);
} catch (err) {
res.status(500).json({ message: err.message });
}
});
I tried changing webOrigins to * on both clients and adding cors with origin * to the api. I also tried adding different headers in the frontend. Nothing really helped and I suspect it's an issue with keycloak config or logic of my app. I doubt it's just a normal cors error.