Я реализовал SuccessHandler для автоматического сохранения учетных данных для использования API Календаря Google, различающихся по электронной почте, каждый раз, когда пользователь входит в систему через Google OAuth2. .
Проблема в том, что когда я вызываю API для получения событий календаря, даже если в параметре запроса существуют учетные данные для электронной почты, окно выбора учетной записи продолжает появляться. После выбора учетной записи аутентификация OAuth завершается успешно, но вместо выполнения логики для получения событий календаря обработчик перехватывает запрос и обрабатывает его.
Вот мои требования:
Когда пользователь входит в систему через Google OAuth2:
Проверьте, существуют ли в файловой системе учетные данные, соответствующие адресу электронной почты пользователя.
Если учетные данные существует, верните токен JWT для конкретного проекта.
Если учетные данные не существуют, создайте и сохраните новые учетные данные.
При вызове API для получения событий календаря через API Календаря Google:< /p>
Проверьте, существуют ли в файловой системе учетные данные, соответствующие адресу электронной почты, указанному в параметре запроса.
Если учетные данные существуют, немедленно получите события календаря без дополнительных шагов аутентификации.
/>Если учетные данные не существует, предложите пользователю войти в систему через OAuth2, чтобы сгенерировать и сохранить новые учетные данные.
Я прикрепил соответствующий код ниже для справки.
Спасибо за помощь.
Код: Выделить всё
@RequiredArgsConstructor
@Component
@Slf4j
public class OAuth2AuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private final JwtTokenProvider jwtTokenProvider;
private final GoogleAuthorizationService authorizationService;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException {
OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal();
String email = oAuth2User.getAttribute("email");
if (email == null) {
log.error("OAuth2 provider did not return email");
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Email not provided by OAuth2 provider");
return;
}
try {
authorizationService.getCredentials(email);
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
JwtToken jwtToken = jwtTokenProvider.generateToken(authentication);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
ObjectMapper objectMapper = new ObjectMapper();
response.getWriter().write(objectMapper.writeValueAsString(jwtToken));
}
}
Код: Выделить всё
@Service
public class GoogleAuthorizationService {
private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
private static final String TOKENS_DIRECTORY_PATH = "tokens";
@Value("${google.credentials.file-path}")
private String credentialsFilePath;
@Value("#{'${google.scopes}'.split(',')}")
private List scopes;
@Value("${spring.security.oauth2.client.registration.google.client-id}")
private String clientId;
@Value("${spring.security.oauth2.client.registration.google.client-secret}")
private String clientSecret;
public Credential getCredentials(String email) throws IOException, GeneralSecurityException {
InputStream in = new FileInputStream(credentialsFilePath);
if (in == null) {
throw new FileNotFoundException("Resource not found: " + credentialsFilePath);
}
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
FileDataStoreFactory dataStoreFactory = new FileDataStoreFactory(
new java.io.File(TOKENS_DIRECTORY_PATH + "/" + sanitizeEmail(email))
);
Credential credential = getStoredCredential(dataStoreFactory, email);
if (credential != null) {
return credential;
}
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, JSON_FACTORY, clientSecrets, scopes)
.setDataStoreFactory(dataStoreFactory)
.setAccessType("offline")
.build();
LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
return new AuthorizationCodeInstalledApp(flow, receiver).authorize(email);
}
private String sanitizeEmail(String email) {
return email.replaceAll("@", "_at_").replaceAll("\\.", "_dot_");
}
private Credential getStoredCredential(DataStoreFactory dataStoreFactory, String email) throws IOException, GeneralSecurityException {
DataStore dataStore = StoredCredential.getDefaultDataStore(dataStoreFactory);
StoredCredential storedCredential = dataStore.get(email);
if (storedCredential != null) {
Credential credential = new Credential.Builder(BearerToken.authorizationHeaderAccessMethod())
.setTransport(GoogleNetHttpTransport.newTrustedTransport())
.setJsonFactory(JSON_FACTORY)
.setClientAuthentication(new ClientParametersAuthentication(clientId, clientSecret))
.setTokenServerUrl(new GenericUrl("https://oauth2.googleapis.com/token"))
.build()
.setAccessToken(storedCredential.getAccessToken())
.setRefreshToken(storedCredential.getRefreshToken());
if (credential.getAccessToken() == null || credential.getExpiresInSeconds() != null && credential.getExpiresInSeconds()
Подробнее здесь: [url]https://stackoverflow.com/questions/79214671/google-calendar-api-duplicated-authorization[/url]