Почему при использовании аутентификации sso с использованием клиента пользователь не остается в системе на сервере (весенняя загрузка oauth2)?

Я создал серверное приложение и клиент, используя предоставление кода авторизации с помощью весенней загрузки. Я заметил, что когда я захожу через Facebook и открываю новую вкладку, а затем захожу на сайт Facebook, я уже вошел в систему (потому что я вошел в систему с помощью клиента, использующего их механизм аутентификации.

Я не могу добиться этого с моей конфигурацией клиент / сервер. Если я вхожу в систему, используя мой клиент (я перенаправлен на страницу входа на сервер, а затем перенаправлен обратно - вход в систему работает на клиенте), то при попытке открыть приложение сервера (на котором также есть некоторые страницы, доступные после аутентификации), я снова вижу страница авторизации. Я хотел бы иметь тот же поток, что и Facebook, чтобы быть уже аутентифицированным на серверном приложении.

Если я вхожу непосредственно в серверное приложение, то открываю другую вкладку с клиентом в chrome и пытаюсь выполнить некоторые действия над клиентским приложением. Я там больше не захожу.

Как я могу оставаться аутентифицированным в приложении сервера после аутентификации клиента?

Конфигурация сервера:

@Configuration
@RestController
@EnableOAuth2Client
@EnableAuthorizationServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityOauth2Configuration extends WebSecurityConfigurerAdapter {

@Autowired
OAuth2ClientContext oauth2ClientContext;
@Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;


@Autowired
UserDetailsService userDetailsService;
@Autowired
UserService userService;

@RequestMapping({"/user", "/me"})
public Map<String, Object> user(Principal principal, OAuth2Authentication oAuth2Authentication) {
    Map<String, Object> map = new LinkedHashMap<>();
    map.put("name", principal.getName());

    try {
        UserDTO userDTO = userService.findUserByEmail(principal.getName());

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT, "@type");
        String value = objectMapper.writeValueAsString(userDTO);
        map.put("userDTO", value);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (UserNotFoundException e) {

    }
    return map;
}


@Override
@Autowired 
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}

@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
    return new BCryptPasswordEncoder();
}

@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    AuthenticationManager manager = super.authenticationManagerBean();
    return manager;
}



@Override
protected void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http.antMatcher("/**").authorizeRequests().antMatchers("/", "/oauth/**", "/custom-logout","/logout", "/login**", "/webjars/**", "/rest/**")
            .permitAll().anyRequest().authenticated().antMatchers("/revoke/**", "/resources/**","/static/**", "/admin/**", "/public/**", "/logout2").permitAll()

            .and().logout().clearAuthentication(true).invalidateHttpSession(true).logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login").permitAll().and().exceptionHandling()
            .accessDeniedHandler(customAccessDeniedHandler())
            .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")).and().formLogin()
//                .loginProcessingUrl("/login")
            .defaultSuccessUrl("/loggedin")

//                .successHandler(customSocialAuthenticationSuccessHandler())//.permitAll()
            .failureHandler(customAuthFailureHandler())

//                .and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
             .and().csrf().disable()
            .rememberMe().tokenRepository(persistentTokenRepository()).tokenValiditySeconds(1209600).and()
            .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
    // @formatter:on
}

@Autowired
DataSource dataSource;
@Bean
public PersistentTokenRepository persistentTokenRepository() {
    JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
    db.setDataSource(dataSource);
    return db;
}


@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http.requestMatchers().antMatchers("/registration", "/abc", "/me", "/resources/**", "/static/**", "/revoke/**", "/rest/**", "/logout2",
                "/public/**"  //public information pages
        )
                .and().authorizeRequests().antMatchers("/me").access("#oauth2.hasScope('read')")
                .antMatchers("/rest/**", "/admin/**").fullyAuthenticated()
        ;

        // @formatter:on
    }
}

@Bean
public CustomAuthFailureHandler customAuthFailureHandler() {
    return new CustomAuthFailureHandler();
}

@Bean
public AccessDeniedHandler customAccessDeniedHandler() {
    return new CustomAccessDeniedHandler();
}


@Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(filter);
    registration.setOrder(-100);
    return registration;
}

@Bean
@ConfigurationProperties("github")
public ClientResources github() {
    return new ClientResources();
}

@Bean
@ConfigurationProperties("facebook")
public ClientResources facebook() {
    return new ClientResources();
}

private Filter ssoFilter() {
    CompositeFilter filter = new CompositeFilter();
    List<Filter> filters = new ArrayList<>();
    filters.add(ssoFilter(facebook(), "/login/facebook"));
    filters.add(ssoFilter(github(), "/login/github"));
    filter.setFilters(filters);
    return filter;
}

@Bean
public CustomAuthenticationSuccessHandler customSocialAuthenticationSuccessHandler(){
    return new CustomAuthenticationSuccessHandler();
}



private Filter ssoFilter(ClientResources client, String path) {
    OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(path);
    OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
    filter.setRestTemplate(template);
    UserInfoTokenServices tokenServices = new UserInfoTokenServices(client.getResource().getUserInfoUri(),
            client.getClient().getClientId());
    tokenServices.setRestTemplate(template);
    filter.setTokenServices(tokenServices);

    filter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);

    return filter;
}

}

class ClientResources {

@NestedConfigurationProperty
private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();

@NestedConfigurationProperty
private ResourceServerProperties resource = new ResourceServerProperties();

public AuthorizationCodeResourceDetails getClient() {
    return client;
}

public ResourceServerProperties getResource() {
    return resource;
}
}

// public static void main(String[] args) {
// SpringApplication.run(SocialApplication.class, args);
// }



class CustomAccessDeniedHandler implements AccessDeniedHandler {

@Override
public void handle(
        HttpServletRequest request,
        HttpServletResponse response,
        AccessDeniedException exc) throws IOException, ServletException {

    Authentication auth
            = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null) {
    }

    response.sendRedirect(request.getContextPath() + "/login?error=true&bla=userdoesnothavespecificrole");
}
}


class CustomAuthFailureHandler extends SimpleUrlAuthenticationFailureHandler 
{

@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                    AuthenticationException exception) throws IOException, ServletException {
    getRedirectStrategy().sendRedirect(request, response, "/login?error=true");

}
}

Конфигурация клиента

@RestController
@Configuration
@EnableOAuth2Client
public class ClientApplication extends WebSecurityConfigurerAdapter {

@Autowired
private OAuth2ClientContext oauth2ClientContext;

@Resource
@Qualifier("accessTokenRequest")
private AccessTokenRequest accessTokenRequest;

@Autowired
private OAuth2RestTemplate restTemplate;

@Autowired
private SSOLogoutHandler mySsoLogoutHandler;

@Override
protected void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    //first line : url accessible without auth
    http.antMatcher("/**").authorizeRequests().antMatchers("/**", "/login**", "/*.bundle.js", "/*.woff**", "/*.ttf", "/resources/**", "/assets/**", "/user/**").permitAll()
            .antMatchers("/rest/**").authenticated()/* .and().exceptionHandling() */
//                .antMatchers("/api/**").authenticated()
            .and().logout().logoutSuccessUrl("/").permitAll().addLogoutHandler(mySsoLogoutHandler).and().csrf()
            .disable().addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
    // @formatter:on
}

@Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(filter);
    registration.setOrder(-100);
    return registration;
}
@Configuration
public class RestConfig {
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("DELETE");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

@Bean
@ConfigurationProperties("security.oauth2")
public ClientResources gate() {
    return new ClientResources();
}

private Filter ssoFilter() {
    CompositeFilter filter = new CompositeFilter();
    List<Filter> filters = new ArrayList<>();
    filters.add(ssoFilter(gate(), "/auth"));
    filter.setFilters(filters);
    return filter;
}

private Filter ssoFilter(ClientResources client, String path) {
    OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(path);
    OAuth2RestTemplate template = restTemplate;
    filter.setRestTemplate(template);

    UserInfoTokenServices tokenServices = new UserInfoTokenServices(client.getResource().getUserInfoUri(),
            client.getClient().getClientId());
    tokenServices.setRestTemplate(template);
    filter.setTokenServices(tokenServices);

    return filter;
}

@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public OAuth2RestTemplate oAuth2RestTemplate() {
    OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(gate().getClient(), oauth2ClientContext);


    oAuth2RestTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
    return oAuth2RestTemplate;
}

@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Qualifier(value = "publicRestAPI")
public RestTemplate publicRestTemplate() {
    return new RestTemplate();
}

class ClientResources {

    @NestedConfigurationProperty
    private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();

    @NestedConfigurationProperty
    private ResourceServerProperties resource = new ResourceServerProperties();

    public AuthorizationCodeResourceDetails getClient() {
        return client;
    }

    public ResourceServerProperties getResource() {
        return resource;
    }
}
}

конфиг клиента yml:

server:
  port: 9999
security:
  oauth2:
    client:
      client-id: app-client-id
      client-secret: app-client-secret
      access-token-uri: http://127.0.0.1:8080/oauth/token
      user-authorization-uri: http://127.0.0.1:8080/oauth/authorize
    resource:
      user-info-uri: http://127.0.0.1:8080/me
  basic:
   enabled: false

url.gate: http://127.0.0.1:8080/
url.gate.token.revoke: revoke/token

Конфигурация сервера iml:

security:
  oauth2:
    client:
      client-id: app-client-id
      client-secret: app-client-secret
      scope: read,write
      grant-type: password, authorization_code, refresh_token
      auto-approve-scopes: '.*'
      access-token-validity-seconds: 10
      refresh-token-validity-seconds: 400000

0 ответов

Другие вопросы по тегам