在使用Java应用程序与OAuth2和Google / Azure身份验证服务器注销的问题。

huangapple go评论88阅读模式
英文:

Problem to logout in java app with oauth2 and Google / Azure auth server

问题

我有一个问题,需要一些建议。
情况如下,我有一个非常简单的Java模块,带有Spring Security和受保护的HTML页面。这个模块的唯一功能是针对Google / Azure进行身份验证,如果凭据正确,它会带我进入HTML页面。我实施了OAuth2和Spring Security 5。身份验证没有问题,我获得了idTokens、访问令牌和刷新令牌(在Azure的情况下)。
问题出现在尝试注销时(HTML中的按钮调用“app/logogut” URL)。我看到本地安全上下文的相关部分被删除,没有cookie,浏览器存储中也没有剩余内容,但是外部服务器(Google / Azure)上的会话仍然处于活动状态,当我刷新页面时,我仍然登录。
如果我在Gmail中打开一个新选项卡,我可以直接进入而不需要重新登录,但如果我从Gmail中注销,然后刷新第一个选项卡,它会再次要求用户和密码。我的问题是,我是否遗漏了一些东西,以使Spring Security完全关闭会话?

此外,尝试对每个服务器的URL执行GET以注销,这似乎有效,但不希望采用这种方式(CORS问题)。

我的安全配置如下:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/", "/login**").permitAll()
            .anyRequest().authenticated()
            .and()
            .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/app/logout"))
            .addLogoutHandler(new HeaderWriterLogoutHandler(
                    new ClearSiteDataHeaderWriter(
                            ClearSiteDataHeaderWriter.Directive.CACHE,
                            ClearSiteDataHeaderWriter.Directive.COOKIES,
                            ClearSiteDataHeaderWriter.Directive.STORAGE)))
            .and()
            .oauth2Login()
            .and().csrf().disable();
}

我的控制器:

@Autowired
@PreAuthorize("hasRole('ROLE_USER')")
@GetMapping("/restricted")
public String restricted() throws IOException, URISyntaxException {
    URL resource = getClass().getClassLoader().getResource("static\\Protected.html");
    if (resource == null) {
        throw new IllegalArgumentException("file not found!");
    } else {
        File html = new File(resource.toURI());
        List<String> strings = Files.readLines(html, StandardCharsets.UTF_8);
        StringBuffer sb = new StringBuffer();
        for (String s : strings) {
            sb.append(s);
        }
        return sb.toString();
    }
}

HTML页面如下:

希望能提供帮助!
提前感谢。

英文:

I'm having a problem and I need some advice.
The situation is the following, I have a very simple java module with spring security and a protected HTML page. The only thing this module does is authenticate against Google / Azure and if the credentials are correct it takes me to the HTML page. Implement OAuth2 and Spring security 5. Authentication works without problems, I get the idTokens, access token, and refresh token (in the case of Azure).
The problem arises when trying to logout (button in HTML call to "app/logogut" URL). I see that what refers to the local security context is deleted, there are no cookies and there is nothing left in the browser's storage, however, the session on the external server (Google / Azure) is still active and when I refresh the page I am still logged in.
If I open a new tab with Gmail, I enter directly without logging in and if I log out from Gmail, when I refresh the first tab now, it asks for the user and pass again. My query is if I am missing something for the logout to completely close the session through Spring security?

Also, try to do a GET to the URL of each server to log out, that seems to work, but it would not be desirable to go that way -CORS Problem :(-.

My security config

在使用Java应用程序与OAuth2和Google / Azure身份验证服务器注销的问题。

In-text

 @Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers(&quot;/&quot;, &quot;/login**&quot;).permitAll()
            .anyRequest().authenticated()
            .and()
            .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher(&quot;/app/logout&quot;))
            .addLogoutHandler(new HeaderWriterLogoutHandler(
                    new ClearSiteDataHeaderWriter(
                            ClearSiteDataHeaderWriter.Directive.CACHE,
                            ClearSiteDataHeaderWriter.Directive.COOKIES,
                            ClearSiteDataHeaderWriter.Directive.STORAGE)))
            .and()
            .oauth2Login()
            .and().csrf().disable()
    ;
}

My Controller

 @Autowired
@PreAuthorize(&quot;hasRole(&#39;ROLE_USER&#39;)&quot;)
@GetMapping(&quot;/restricted&quot;)
public String restricted() throws IOException, URISyntaxException {
    URL resource = getClass().getClassLoader().getResource(&quot;static\\Protected.html&quot;);
    if (resource == null) {
        throw new IllegalArgumentException(&quot;file not found!&quot;);
    } else {

        File html = new File(resource.toURI());
        List&lt;String&gt; strings = Files.readLines(html, StandardCharsets.UTF_8);
        StringBuffer sb = new StringBuffer();
        for (String s : strings) {
            sb.append(s);
        }
        return sb.toString();


    }

}

HTML PAge

在使用Java应用程序与OAuth2和Google / Azure身份验证服务器注销的问题。

Any help would be appreciated!

Thanks in advance

答案1

得分: 1

你可能需要告诉Spring Security在注销时使http会话失效:

.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/app/logout"))
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true) 

或者,根据您如何处理授权服务器,可以重定向到一个处理注销的控制器,参见这里

通常情况下,在注销控制器中调用session.invalidate()即可结束OAuth2登录。

英文:

You might need to tell Spring Security to invalidate the http session upon logout:

.logout()
.logoutRequestMatcher(new AntPathRequestMatcher(&quot;/app/logout&quot;))
.deleteCookies(&quot;JSESSIONID&quot;)
.invalidateHttpSession(true) 

Or depending on how you're handling your authorization server, redirect to a controller that handles logout, see here

Normally you can just call session.invalidate() in a logout controller to end an oauth2 sign in.

答案2

得分: 0

终于,在经过这么长的时间后,我找到了解决我的问题的方法。
根据 Spring 文档(https://docs.spring.io/spring-security/site/docs/5.2.x/reference/html/oauth2.html#oauth2login-advanced-oidc-logout),我发现了一种被称为单点退出的方法,如果在 application.properties 中指定了 issuer-uri,就可以实现这个方法。这个 URI 返回一个 JSON,其中包含了 end_session_endpoint 的 URL,以及其他一些数据。

使用这个方法,现在你可以像这样配置 OidcClientInitiatedLogoutSuccessHandler

当从我的应用程序注销时,这允许之前的处理程序被调用,并在授权服务器中使会话失效。

非常感谢帮助。

英文:

Finally, after all this time, I found a solution to my problem.
Following Spring documentation (https://docs.spring.io/spring-security/site/docs/5.2.x/reference/html/oauth2.html#oauth2login-advanced-oidc-logout) I found what some calls Single Sign Out and can be implemented if the issuer-uri is specified in application.properties. This uri returns a json where, among other data, is the end_session_endpoint url.

在使用Java应用程序与OAuth2和Google / Azure身份验证服务器注销的问题。

With this now you can configure OidcClientInitiatedLogoutSuccessHandler like this

在使用Java应用程序与OAuth2和Google / Azure身份验证服务器注销的问题。

This allows that when logging out from my application, the previous handler is invoked and invalidates the session in the authorization server.

Thank you very much for the help

huangapple
  • 本文由 发表于 2020年9月23日 00:33:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/64014013.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定