Keycloak angular No 'Access-Control-Allow-Origin' header is present

时间:2017-07-12 08:07:19

标签: angularjs keycloak

I Have integrated keycloak with an angular app. Basically, both frontend and backend are on different server.Backend app is running on apache tomcat 8. Frontend app is running on JBoss welcome content folder.

Angular config

angular.element(document).ready(function ($http) {
    var keycloakAuth = new Keycloak('keycloak.json');
    auth.loggedIn = false;
    keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
        keycloakAuth.loadUserInfo().success(function (userInfo) {
            console.log(userInfo);  
        });
        auth.loggedIn = true;
        auth.authz = keycloakAuth;
        auth.logoutUrl = keycloakAuth.authServerUrl + "/realms/app1/protocol/openid-connect/logout?redirect_uri=http://35.154.214.8/hrms-keycloak/index.html";
        module.factory('Auth', function() {
            return auth;
        });
        angular.bootstrap(document, ["themesApp"]);
    }).error(function () {
            window.location.reload();
        });

});
module.factory('authInterceptor', function($q, Auth) {
    return {
        request: function (config) {
            var deferred = $q.defer();
            if (Auth.authz.token) {
                Auth.authz.updateToken(5).success(function() {
                    config.headers = config.headers || {};
                    config.headers.Authorization = 'Bearer ' + Auth.authz.token;
                    deferred.resolve(config);
                }).error(function() {
                        deferred.reject('Failed to refresh token');
                    });
            }
            return deferred.promise;
        }
    };
});
module.config(["$httpProvider", function ($httpProvider)  {
    $httpProvider.interceptors.push('authInterceptor');
}]);

Request Header

Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:authorization
Access-Control-Request-Method:GET
Connection:keep-alive
Host:35.154.214.8:8080
Origin:http://35.154.214.8
Referer:http://35.154.214.8/accounts-keycloak/
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36

Error on web console.

XMLHttpRequest cannot load http://35.154.214.8:8080/company/loadCurrencyList. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://35.154.214.8' is therefore not allowed access.

Cors filter on backend

@Component
public class CORSFilter implements Filter {
    static Logger logger = LoggerFactory.getLogger(CORSFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "*");
        chain.doFilter(request, response);
    }

    public void destroy() {
    }
}

11 个答案:

答案 0 :(得分:10)

我与KeyCloak和CORS以及所有这些争夺了大约两周,这是我的解决方案(针对keycloak 3.2.1):

关于配置KeyCloak服务器。 似乎是,你的王国的WebOrigin必须是

*
只有一个来源" *"。

这就是我所需要的一切。

如果您将服务器作为WebOrigin输入,则问题就出现了。 当您在JavaScript中调用keycloak.init时,keycloak不会生成CORS头,因此您必须手动配置它们,并且一旦这样做,并在成功初始化后调用keycloak.getUserInfo - 您将获得双CORS头,这不是允许的。

在keycloak邮件列表的深处,你需要在keycloak.json中设置enable-cors = true,但在keycloak.gitbooks.io上没有任何相关内容。所以似乎不是真的。

在描述JavaScript和Node.Js适配器时,他们也没有提到CORS,我也不知道为什么,似乎根本不重要。

似乎也是,您不应该触摸WildFly配置来提供CORS标头。

此外,OIDC中的CORS是一个特殊的KeyCloak功能(而不是错误)。

希望这个答案对你有用。

答案 1 :(得分:9)

请注意,将您的网络来源设置为" *"打开了一个巨大的安全漏洞。它允许来自任何域的任何脚本代表用户在该用户的浏览器中发出请求。

每当您发现自己以这种方式禁用安全功能时,您需要考虑安全功能存在的原因。

请参阅8.1.1 of the Keycloak docs

部分

答案 2 :(得分:5)

我遇到了同样的问题,并且(至少)对于Keycloak Server版本8.0.1,您可以在“ Web Origins”字段中添加一个“ +”作为输入,这似乎是最佳选择。

“ +”效果应与添加“ http://localhost:4200”作为“ Web Origins”条目相同(请参见下面的屏幕截图)。

这是“ Web Origins”字段的提示:

“允许CORS来源。要允许“有效重定向URI”的所有来源,请添加“ +”。要允许所有来源,请添加“ *”。” (请参见下面的屏幕截图)

Keycloak Client Web Origin Settings

答案 3 :(得分:3)

对我有用的解决方案是将Web Origins URL(不是我的客户,而是域)设置为例如http://localhost:3000/http://localhost:3000(请注意,缺少/结束)。这样,您不会通过使用*将其打开到所有URL。

答案 4 :(得分:2)

你给出了你自己的问题的答案,将WebOrigin添加为*在客户端级别(不是在Realm级别!),这对你有用,但在我自己的情况下它并没有。实际上,删除*对我来说是个窍门,因为KC两次发送CORS标题 - 删除它,将其剥离一次......

感谢您的回答,我很幸运地找到了解决问题的答案......

我们都同意的是KC文件至少非常差。

这是为假人写的,但是......我们不是傻瓜,也不是主题......

它没有解释技术细节。例如,端点的响应是什么。搜索网络(两周)确实给了一点 - 但为什么它没有在文档中列出?

一个例子。但我有几个......

我们可以帮助提供文档吗?

答案 5 :(得分:2)

我有同样的CORS错误。 KeyCloak的新功能。尝试将网页来源设置为“ *”,“ +”和特定的网址。没事。直到我将客户端设置上的“访问类型”更改为公共。然后,将网络来源设置为特定网址和+的两个选项均起作用。由于将其设置为*并不安全,因此请不要尝试。

当访问类型设置为机密时,它再次开始出现CORS错误。我正在尝试使用PKCE(代码流)进行授权流。

使用10.0.2版。

有效设置的屏幕截图:

enter image description here

答案 6 :(得分:1)

我遇到了同样的问题,在我的情况下,这是由于在keycloak js适配器创建中使用选项对象引起的,其中,身份验证服务器的URL错误地设置为http而不是https:

const keycloak = Keycloak({
    url: 'http://my-keycloak-auth-server/auth',
    realm: 'myRealm',
    clientId: 'myClient'
});

但正确的是

const keycloak = Keycloak({
    url: 'https://my-keycloak-auth-server/auth',
    realm: 'myRealm',
    clientId: 'myClient'
});

答案 7 :(得分:0)

在使用Angular 6,REST Web Services的Spring Boot和Keycloak时也遇到了同样的问题。

密钥斗篷地址:KEYCLOAK
Angular 6应用程序地址:ANGULAR_APP
通过Keycloak和Spring自动配置保护的两个REST WS:AA,BB

流程为:Angular应用请求(GET)AA,AA请求(GET)BB

使用XMLHttpRequest错误类似于: 无法加载AA。对预检请求的响应未通过访问控制检查:请求的资源上不存在“ Access-Control-Allow-Origin”标头。因此,不允许访问来源“ ANGULAR_APP”。

使用来自Angular的Observable,它是: 无法加载AA:CORS策略已阻止从“ BB”重定向到“ KEYCLOAK”:所请求的资源上不存在“ Access-Control-Allow-Origin”标头。因此,不允许访问来源“ ANGULAR”。

尝试使用网络起源:*至无解决方案

从不知道为什么Keycloak会进行重定向,从而导致问题

当我根据https://developers.redhat.com/blog/2017/05/25/easily-secure-your-spring-boot-applications-with-keycloak/

将服务AA中的安全性从Keycloak +自动配置切换为Keycloak + Spring Security时,问题就消失了

正因为如此,所以很多天都无法入睡。万一有人面对类似的情况,就离开吧。

答案 8 :(得分:0)

我在init上添加此行...

this.keycloakAuth.init({ onLoad:“需要登录”, 流程:“隐式” })

答案 9 :(得分:0)

这是一个相当老的问题,但我还是要回答。它可能会帮助别人。在keycloak管理页面中,转到clients->your client。在那里,您可以在下面看到一个名为web origins的字段。在此输入您的网址,您的问题将得到解决。

enter image description here

答案 10 :(得分:0)

keycloak-js 中遇到了类似的错误,虽然不在 Angular 中:我可以使用文档中的代码成功登录:

keycloak.init({
  onLoad: 'login-required',
}).then(function(authenticated) {
  alert(authenticated ? 'authenticated' : 'not authenticated');
}).catch(function() {
  alert('failed to initialize');
});

但是连续调用(在我的例子中为 keycloak.loadUserProfile(),调用 account 端点)最终会导致 CORS 错误。

后来我发现我以一种糟糕的方式操纵了我的代码,以至于连续调用与 init!事后看来很明显但是..

TLDR;如果您在 init 调用完成之前调用 keycloak 端点,响应将缺少 CORS 标头,并且您将收到 CORS 错误!这只是意味着您没有通过身份验证。