feat: add Google login support

This commit is contained in:
Tim
2025-07-05 14:36:52 +08:00
parent 11611dbeb5
commit 20337e0501
5 changed files with 96 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ import com.openisle.service.EmailSender;
import com.openisle.service.JwtService;
import com.openisle.service.UserService;
import com.openisle.service.CaptchaService;
import com.openisle.service.GoogleAuthService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
@@ -21,6 +22,7 @@ public class AuthController {
private final JwtService jwtService;
private final EmailSender emailService;
private final CaptchaService captchaService;
private final GoogleAuthService googleAuthService;
@Value("${app.captcha.enabled:false}")
private boolean captchaEnabled;
@@ -63,6 +65,15 @@ public class AuthController {
}
}
@PostMapping("/google")
public ResponseEntity<?> loginWithGoogle(@RequestBody GoogleLoginRequest req) {
Optional<User> user = googleAuthService.authenticate(req.getIdToken());
if (user.isPresent()) {
return ResponseEntity.ok(Map.of("token", jwtService.generateToken(user.get().getUsername())));
}
return ResponseEntity.badRequest().body(Map.of("error", "Invalid google token"));
}
@GetMapping("/check")
public ResponseEntity<?> checkToken() {
return ResponseEntity.ok(Map.of("valid", true));
@@ -83,6 +94,11 @@ public class AuthController {
private String captcha;
}
@Data
private static class GoogleLoginRequest {
private String idToken;
}
@Data
private static class VerifyRequest {
private String username;

View File

@@ -0,0 +1,69 @@
package com.openisle.service;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.openisle.model.Role;
import com.openisle.model.User;
import com.openisle.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.Optional;
@Service
@RequiredArgsConstructor
public class GoogleAuthService {
private final UserRepository userRepository;
@Value("${google.client-id:}")
private String clientId;
public Optional<User> authenticate(String idTokenString) {
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), new JacksonFactory())
.setAudience(Collections.singletonList(clientId))
.build();
try {
GoogleIdToken idToken = verifier.verify(idTokenString);
if (idToken == null) {
return Optional.empty();
}
GoogleIdToken.Payload payload = idToken.getPayload();
String email = payload.getEmail();
String name = (String) payload.get("name");
return Optional.of(processUser(email, name));
} catch (Exception e) {
return Optional.empty();
}
}
private User processUser(String email, String name) {
Optional<User> existing = userRepository.findByEmail(email);
if (existing.isPresent()) {
User user = existing.get();
if (!user.isVerified()) {
user.setVerified(true);
user.setVerificationCode(null);
userRepository.save(user);
}
return user;
}
User user = new User();
String baseUsername = email.split("@")[0];
String username = baseUsername;
int suffix = 1;
while (userRepository.findByUsername(username).isPresent()) {
username = baseUsername + suffix++;
}
user.setUsername(username);
user.setEmail(email);
user.setPassword("");
user.setRole(Role.USER);
user.setVerified(true);
return userRepository.save(user);
}
}