Search code examples
corskeycloakkeycloak-services

CORS issue with Keycloak OIDC token endpoint


I'm encountering a CORS (Cross-Origin Resource Sharing) issue when trying to obtain an access token from the Keycloak OIDC token endpoint. I'm running my web application on http://localhost:8000, and Keycloak is running on http://localhost:8080.

When my application makes a request to http://localhost:8080/realms/myrealm/protocol/openid-connect/token, I get the following CORS error:

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.

I have configured the following settings in my client's settings on the Keycloak Administration Console:

Valid Redirect URIs: http://localhost:8000/ Valid Post Logout Redirect URIs: http://localhost:8000/ Web Origins: http://localhost:8000 Despite these configurations, the CORS issue persists when my application tries to obtain an access token from the Keycloak OIDC token endpoint.

Keycloak

Can someone please help me resolve this CORS issue and allow my application to successfully obtain an access token from the Keycloak OIDC token endpoint?

My Keycloak version is 22.0

Here is my 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>

I am running keycloak using 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

Solution

  • My "Allow CORS: Access-Control-Allow-Origin" extension was on. Turning it off solved the problem

    Allow CORS: Access-Control-Allow-Origin