security oauth2+oidc(openid连接)操作启动/使用多个RP返回通道注销

ubbxdtey  于 2021-07-13  发布在  Java
关注(0)|答案(2)|浏览(510)

该体系结构是一个具有多个rps的身份验证服务器(op)。请检查下面的图片。

我能够成功地用rp启动的注销注销,也就是说,如果我从任何客户端注销,客户端(rp)就会注销,op也会注销。
请查找openid提供者发现元数据;

{
    "jwks_uri":"https://<Auth Server URL>/token_keys",
    "subject_types_supported":["public"],
    "end_session_endpoint":"https://<Auth Server URL>/logout",
    "issuer":"https://<Auth Server URL>/oauth/token",
    "authorization_endpoint":"https://<Auth Server URL>/oauth/authorize",
    "token_endpoint":"https://<Auth Server URL>/oauth/token"
}

"end_session_endpoint" 在发现中,我可以在客户端使用以下代码执行rp启动的注销操作,

import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import com.nimbusds.jose.shaded.json.JSONArray;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ClientRegistrationRepository clientRegistrationRepository;

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/assets/**").antMatchers("/assets/bundles/**");
    }

     @Bean(name = "oidcUserService")
     OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
         return new CustomOidcUserService();
     }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.cors().and().headers(headers -> headers.cacheControl().and()
                .addHeaderWriter(new StaticHeadersWriter("X-UA-Compatible", "IE=edge"))
                .frameOptions(frameOptions -> frameOptions.sameOrigin()).httpStrictTransportSecurity())
        .authorizeRequests(authorize -> authorize
                .antMatchers("/error").permitAll()
                .anyRequest().authenticated())
        .oauth2Login(oauthLogin -> oauthLogin
                .userInfoEndpoint()
                .oidcUserService(this.oidcUserService()))
        .logout(logout -> logout
                .logoutSuccessHandler(oidcLogoutSuccessHandler())
                .invalidateHttpSession(true)
                .clearAuthentication(true)
                .deleteCookies("JSESSIONID","CSRF-TOKEN","XSRF-TOKEN")
                .permitAll())
         .csrf((csrf) -> csrf
                    .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()));

    }

    private OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler() {
        OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler = new OidcClientInitiatedLogoutSuccessHandler(this.clientRegistrationRepository);
        oidcLogoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}");
        return oidcLogoutSuccessHandler;
     }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

}

但是我不知道如何实现op-initiatedlogot,如果op会话过期或op注销,它将注销op下的所有客户端。有什么例子吗?我已经为此研究了几天,并发现有另一个关键叫 "check_session_iframe" 但在spring中找不到合适的文档。如果你有任何例子,请分享。谢谢您。

goucqfw6

goucqfw61#

如果op的元数据不包含
check_session_iframe frontchannel_logout_supported 或者 backchannel_logout_supported ,则它根本不支持单次注销,这将在客户端触发注销,即“op initiated logout”。

xpszyzbs

xpszyzbs2#

这个 check_session_iframe 包含由op控制的url。客户端将把这个url嵌入为iframe,也称为op iframe。opiframe可以访问openid提供者的用户代理状态(因为它是同一个域)。客户端将创建另一个iframe,rp iframe,向op iframe发送postmessage请求,以检查会话状态。op-iframe随后将向rp-iframe响应postmessage请求,并返回结果(更改、未更改或错误)。
关于会话管理规范的客户机部分,惟一需要做的就是嵌入op iframe,给它一个id,这样就可以向它发送postmessage请求,并在rp iframe中处理来自它的postmessage请求。查看规范中的伪代码:https://openid.net/specs/openid-connect-session-1_0.html#rpiframe

相关问题