Я столкнулся с проблемой CORS (совместное использование ресурсов между источниками) при попытке получить токен доступа из конечной точки токена Keycloak OIDC. Я запускаю свое веб-приложение на http://localhost:8000, а Keycloak — на http://localhost:8080.
Когда мое приложение отправляет запрос на http://localhost:8080/realms/myrealm/protocol/openid-connect/token, я получаю следующую ошибку CORS:
Access to XMLHttpRequest at 'http://localhost:8080/realms/myrealm/protocol/openid-connect/token' from origin 'http://localhost:8000' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'http://localhost:8080' that is not equal to the supplied origin.
Я настроил следующие параметры в настройках моего клиента в консоли администрирования Keycloak:
Действительные URI перенаправления: http://localhost:8000/. Действительные URI перенаправления после выхода из системы: http://localhost:8000/ Веб-происхождение: http://localhost:8000. Несмотря на эти конфигурации, проблема CORS сохраняется, когда мое приложение пытается получить токен доступа от конечной точки токена Keycloak OIDC.
Может ли кто-нибудь помочь мне решить эту проблему CORS и позволить моему приложению успешно получить токен доступа из конечной точки токена Keycloak OIDC?
Моя версия Keycloak — 22.0.
Вот мой app.js
var express = require('express');
var app = express();
var stringReplace = require('string-replace-middleware');
var KC_URL = process.env.KC_URL || "http://localhost:8080";
var SERVICE_URL = process.env.SERVICE_URL || "http://localhost:3000/secured";
app.use(stringReplace({
'SERVICE_URL': SERVICE_URL,
'KC_URL': KC_URL
}));
app.use(express.static('.'))
app.get('/', function(req, res) {
res.render('index.html');
});
app.get('/client.js', function(req, res) {
res.render('client.js');
});
app.listen(8000);
<!DOCTYPE html>
<html>
<head>
<title>Keycloak Example Application</title>
<script type = "text/javascript" src = "KC_URL/js/keycloak.js"></script>
<script type = "text/javascript">
function output(content) {
if (typeof content === 'object') {
content = JSON.stringify(content, null, 2)
}
document.getElementById('output').textContent = content;
}
function profile() {
if (kc.idTokenParsed.name) {
document.getElementById('name').textContent = 'Hello ' + kc.idTokenParsed.name;
} else {
document.getElementById('name').textContent = 'Hello ' + kc.idTokenParsed.preferred_username;
}
if (kc.idTokenParsed.picture) {
document.getElementById('picture').src = kc.idTokenParsed.picture;
}
document.getElementById('user').style.display = 'block';
}
function sendRequest() {
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState === 4) {
output(req.status + '\n\n' + req.responseText);
}
}
req.open('GET', 'SERVICE_URL', true);
req.setRequestHeader('Authorization', 'Bearer ' + kc.token);
req.send();
}
var kc = new Keycloak({ realm: 'myrealm', clientId: 'myclient' });
window.onload = function() {
kc.init({'messageReceiveTimeout': 100000}).then(function() {
if (kc.authenticated) {
profile();
} else {
document.getElementById('anonymous').style.display = 'block';
}
});
}
</script>
</head>
<body>
<div id = "anonymous" style = "display: none">
<button onclick = "window.kc.login()">Login</button>
</div>
<div id = "user" style = "display: none">
<button onclick = "window.kc.logout()">Logout</button>
<button onclick = "output(kc.idTokenParsed)">Show ID Token</button>
<button onclick = "output(kc.tokenParsed)">Show Access Token</button>
<button onclick = "window.kc.updateToken(-1).then(function() { output(kc.idTokenParsed); profile() })">Refresh</button>
<button onclick = "sendRequest()">Invoke Service</button>
<hr/>
<h2 id = "name"></h2>
<img id = "picture" width = "50px" height = "50px"/>
<hr/>
<pre id = "output"></pre>
</div>
</body>
</html>
Я использую keycloak, используя Docker
docker run -p 8080:8080 \
-p 8443:8443 \
--add-host=host.docker.internal:host-gateway \
--name keycloak \
-e KEYCLOAK_USER=admin \
-e KEYCLOAK_PASSWORD=admin \
quay.io/keycloak/keycloak:22.0.0 start-dev
Мое расширение «Разрешить CORS: Access-Control-Allow-Origin» было включено. Отключение решило проблему