Я хочу подключиться к 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);
}
}