diff --git a/src/main/java/com/safetypin/authentication/service/GoogleAuthService.java b/src/main/java/com/safetypin/authentication/service/GoogleAuthService.java
index d41f56a15d89a5b1385e87595135cdfaaa4053b4..b06c09f77c73e6e8d98070f750f07796e8ccbc5a 100644
--- a/src/main/java/com/safetypin/authentication/service/GoogleAuthService.java
+++ b/src/main/java/com/safetypin/authentication/service/GoogleAuthService.java
@@ -48,43 +48,151 @@ public class GoogleAuthService extends AuthenticationService {
     }
 
     protected GoogleIdTokenVerifier createIdTokenVerifier() {
-        return null;
+        return new GoogleIdTokenVerifier.Builder(
+                new NetHttpTransport(), new GsonFactory())
+                .setAudience(Collections.singletonList(googleClientId))
+                .build();
     }
 
     public GoogleIdToken.Payload verifyIdToken(String idTokenString) throws Exception {
-        return null;
+        if (idTokenString == null) {
+            throw new IllegalArgumentException("ID Token cannot be null");
+        }
+
+        GoogleIdTokenVerifier verifier = createIdTokenVerifier();
+        GoogleIdToken idToken = verifier.verify(idTokenString);
+
+        if (idToken == null) {
+            throw new Exception("Invalid ID Token");
+        }
+        return idToken.getPayload();
     }
 
     protected GoogleAuthorizationCodeTokenRequest createTokenRequest(
             String tokenUrl, String clientId, String clientSecret) {
-        return null;
+        return new GoogleAuthorizationCodeTokenRequest(
+                new NetHttpTransport(),
+                GsonFactory.getDefaultInstance(),
+                tokenUrl,
+                clientId,
+                clientSecret,
+                "",
+                "");
     }
 
     public String getAccessToken(String serverAuthCode) throws IOException {
-        return null;
+        TokenResponse tokenResponse = createTokenRequest(
+                "https://oauth2.googleapis.com/token",
+                googleClientId,
+                googleClientSecret)
+                .setCode(serverAuthCode)
+                .execute();
+
+        return tokenResponse.getAccessToken();
     }
 
     protected URL createURL(String urlString) throws IOException {
-        return null;
+        return new URL(urlString);
     }
 
     public String fetchUserData(String accessToken, String personFields) throws IOException {
-        return null;
+        String apiUrl = PEOPLE_API_BASE_URL + "?personFields=" + personFields;
+
+        URL url = createURL(apiUrl);
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+        try {
+            conn.setRequestMethod("GET");
+            conn.setRequestProperty("Authorization", "Bearer " + accessToken);
+            conn.setRequestProperty("Accept", "application/json");
+
+            int responseCode = conn.getResponseCode();
+            if (responseCode == HttpURLConnection.HTTP_OK) {
+                return readResponse(conn.getInputStream());
+            } else {
+                throw new ApiException("Error fetching data from Google API", responseCode);
+            }
+        } finally {
+            conn.disconnect();
+        }
     }
 
     private String readResponse(InputStream inputStream) throws IOException {
-        return null;
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
+            StringBuilder response = new StringBuilder();
+            String line;
+            while ((line = reader.readLine()) != null) {
+                response.append(line);
+            }
+            return response.toString();
+        }
     }
 
     public LocalDate getUserBirthdate(String accessToken) throws IOException {
-        return null;
+        String response = fetchUserData(accessToken, "birthdays");
+        return extractBirthday(response);
     }
 
     public String authenticate(GoogleAuthDTO googleAuthDTO) throws Exception {
-        return null;
+        GoogleIdToken.Payload payload = verifyIdToken(googleAuthDTO.getIdToken());
+
+        String email = payload.getEmail();
+        String name = (String) payload.get("name");
+
+        Optional<User> existingUser = Optional.ofNullable(super.getUserRepository().findByEmail(email));
+        if (existingUser.isPresent()) {
+            User user = existingUser.get();
+            String userProvider = user.getProvider();
+            if (!EMAIL_PROVIDER.equals(userProvider)) {
+                throw new UserAlreadyExistsException("An account with this email exists. Please sign in using " + userProvider);
+            }
+            return super.generateJwtToken(user.getId());
+        }
+
+        String accessToken = getAccessToken(googleAuthDTO.getServerAuthCode());
+        LocalDate userBirthdate = getUserBirthdate(accessToken);
+
+        User newUser = new User();
+        newUser.setEmail(email);
+        newUser.setName(name);
+        newUser.setPassword(null);
+        newUser.setProvider("GOOGLE");
+        newUser.setVerified(true);
+        newUser.setRole("USER");
+        newUser.setBirthdate(userBirthdate);
+
+        User user = super.getUserRepository().save(newUser);
+
+        return super.generateJwtToken(user.getId());
     }
 
     LocalDate extractBirthday(String jsonResponse) {
-        return null;
+        JsonElement rootElement = JsonParser.parseString(jsonResponse);
+        JsonObject rootObj = rootElement.getAsJsonObject();
+
+        if (!rootObj.has("birthdays")) {
+            return null;
+        }
+
+        JsonArray birthdaysArray = rootObj.getAsJsonArray("birthdays");
+        if (birthdaysArray.isEmpty()) {
+            return null;
+        }
+
+        JsonObject birthdayObj = birthdaysArray.get(0).getAsJsonObject();
+        if (!birthdayObj.has("date")) {
+            return null;
+        }
+
+        JsonObject dateObj = birthdayObj.getAsJsonObject("date");
+
+        int year = dateObj.has("year") ? dateObj.get("year").getAsInt() : 0;
+        int month = dateObj.get("month").getAsInt();
+        int day = dateObj.get("day").getAsInt();
+
+        if (year > 0) {
+            return LocalDate.of(year, month, day);
+        } else {
+            return LocalDate.of(Year.now().getValue(), month, day);
+        }
     }
-}
+}
\ No newline at end of file