Подключитесь к провайдеру OAuth2 с уже вошедшим пользователем в Spring Security 5 - PullRequest
0 голосов
/ 09 апреля 2019

Я хочу подключиться к STRAVA через OAuth2 для сбора и анализа учебных мероприятий.

Я уже использую токены JWT для аутентификации по имени пользователя / паролю на своей странице - это аутентификация без сохранения состояния.Токен должен быть отправлен с каждым запросом в заголовке аутентификации.

Проблема в том, что процесс OAuth перенаправляет в STRAVA, а затем обратно на мой сайт.Токен JWT уже вошедшего в систему пользователя не сохраняется во время этого процесса, и у меня нет шансов сопоставить вошедшего в систему пользователя, который предпринял попытку подключения, и полученный OAuth-токен из процесса STAVA OAuth.

Мне нужно как-то сопоставить вновь созданное соединение STRAVA с пользователем, который запустил соединение , используя поток Spring Security OAuth2.

Приветствия,

Philipp

Моя конфигурация безопасности Spring выглядит следующим образом:

http
                .csrf().disable()
                // make sure we use stateless session; session won't be used to store user's state.
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                // handle an authorized attempts
                .exceptionHandling().authenticationEntryPoint((req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
                .and()
                // Add a filter to validate user credentials and add token in the response header

                // What's the authenticationManager()?
                // An object provided by WebSecurityConfigurerAdapter, used to authenticate the user passing user's credentials
                // The filter needs this auth manager to authenticate the user.
                .addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfigurationProperties))
                .addFilterAfter(new JwtTokenAuthenticationFilter(jwtConfigurationProperties), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(new SocialBaseURLFilter(oAuth2ConfigurationProperties.getBaseURL()), OAuth2LoginAuthenticationFilter.class)
                .authorizeRequests()
                // allow all POST requests
                .antMatchers(HttpMethod.POST, jwtConfigurationProperties.getUri()).permitAll()
                .antMatchers("/register").permitAll()
                .antMatchers("/forgot-password").permitAll()
                .antMatchers("/confirm-user").permitAll()
                .antMatchers("/reset-password").permitAll()
                // any other requests must be authenticated
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .disable()
                .oauth2Login()
                .authorizationEndpoint()
                .and()
                .redirectionEndpoint()
                .baseUri("/login/oauth2/code/*")
                .and()
                .userInfoEndpoint()
                .userService(customOAuth2UserService)
                .and()
                .successHandler(oAuth2AuthenticationSuccessHandler)
                .failureHandler(oAuth2AuthenticationFailureHandler);

Моя конфигурация безопасности oauth выглядит так:

spring.security:
    oauth2:
      client:
        registration:
          google:
            clientId: [CLIENT-ID]
            clientSecret: [CLIENT-SECRET]
            scope:
              - email
              - profile
          strava:
            clientId: [CLIENT-ID]
            clientSecret: [CLIENT-SECRET]
            authorizationGrantType: authorization_code
            redirectUriTemplate: '{baseUrl}/login/oauth2/code/{registrationId}'
            clientAuthenticationMethod: post
            clientName: Strava
            clientAlias: Strava
            scope:
              - read_all,activity:read
        provider:
          strava:
            authorizationUri: https://www.strava.com/oauth/authorize
            tokenUri: https://www.strava.com/oauth/token
            userInfoUri: https://www.strava.com/api/v3/athlete
            userNameAttribute: firstname

Это моя служба пользователя Oauth:

@Service
public class CustomOAuth2UserService extends DefaultOAuth2UserService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private AuthUserDAO userRepository;

    @Autowired
    private AuthProcessor authProcessor;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException {

        OAuth2User oAuth2User = super.loadUser(oAuth2UserRequest);

        try {
            return processOAuth2User(oAuth2UserRequest, oAuth2User);
        } catch (AuthenticationException ex) {
            throw ex;
        } catch (Exception ex) {
            // Throwing an instance of AuthenticationException will trigger the OAuth2AuthenticationFailureHandler
            throw new InternalAuthenticationServiceException(ex.getMessage(), ex.getCause());
        }
    }

    private OAuth2User processOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2User oAuth2User) {
        OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(oAuth2UserRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes());
        if (StringUtils.isBlank(oAuth2UserInfo.getEmail())) {
            throw new OAuth2AuthenticationProcessingException("Email not found from OAuth2 provider");
        }

        Optional<AuthUser> userOptional = Optional.ofNullable(userRepository.findByEmail(oAuth2UserInfo.getEmail()));
        AuthUser authUser;
        if (userOptional.isPresent()) {
            authUser = userOptional.get();
            authUser = updateExistingUser(oAuth2UserRequest, authUser, oAuth2UserInfo);
        } else {
            authUser = registerNewUser(oAuth2UserRequest, oAuth2UserInfo);
        }

        return OAuthUserPrincipal.create(authUser, oAuth2User.getAttributes());
    }

    private AuthUser registerNewUser(OAuth2UserRequest oAuth2UserRequest, OAuth2UserInfo oAuth2UserInfo) {
        AuthUser authUser = new AuthUser();

        Set<Roles> roles = new HashSet<>();
        roles.add(Roles.REGISTERED);

        authUser.setEmail(oAuth2UserInfo.getEmail());
        authUser.setRoles(roles);
        authUser.setEnabled(true);
        authUser.setRegisterAt(new Date());

        Map<AuthProvider, String> providers = new HashMap<>();
        providers.put(AuthProvider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId()), oAuth2UserInfo.getId());
        authUser.setProviders(providers);
        AuthUser dbUser = userRepository.save(authUser);

        NameDTO name = new NameDTO();
        name.setForename(oAuth2UserInfo.getName());  

        return dbUser;
    }

    private AuthUser updateExistingUser(OAuth2UserRequest oAuth2UserRequest, AuthUser existingAuthUser, OAuth2UserInfo oAuth2UserInfo) {
        Map<AuthProvider, String> providers = existingAuthUser.getProviders();
        providers.put(AuthProvider.valueOf(oAuth2UserRequest.getClientRegistration().getRegistrationId()), oAuth2UserInfo.getId());
        existingAuthUser.setProviders(providers);

        return userRepository.save(existingAuthUser);
    }

}
...