12.4 Building OAuth2 + JWT Integrated Login (Google, Kakao)
In modern web/app services, Social Logins like "Log in with Google" or "Log in with Kakao" are indispensable features alongside organic proprietary user registrations. Leveraging Spring Security's OAuth2 Client perfectly encapsulates this chaotic multi-step verification procedure seamlessly into a fluid pipeline.
1. OAuth2 Request Flow (Authorization Code Grant)
- The Client (Browser) aggressively redirects the user targeting the Kakao Auth Server upon clicking the "Kakao Login" button.
- The user types their Kakao credentials, implicitly granting permission consents. Kakao reciprocates securely by mailing an Authorization Code back directly to your Backend server.
- Spring Security's internal
OAuth2LoginAuthenticationFilterintercepts this code natively, initiating backend Server-to-Server REST communication heavily securing a definitive Access Token from Kakao. - Capitalizing on this acquired Access Token, the system subsequently fetches User Profile Data (Email, Name, Avatar) exclusively from Kakao resources (
DefaultOAuth2UserServicebehaves here). - Upon successful profile retrieval, the
OAuth2AuthenticationSuccessHandlertriggers aggressively. Inside this handler, you strategically register (Save) the user entity natively into your internal DB architecture, deliberately weaving your proprietary internal JWT Access Token then explicitly replying back to the Browser frontend securely.
2. Dependencies and application.yml Settings
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
spring:
security:
oauth2:
client:
registration:
google:
client-id: "ID_PROVISIONED_FROM_GOOGLE_CONSOLE"
client-secret: "SECRET"
scope: profile, email
kakao:
client-id: "KAKAO_REST_API_KEY"
client-secret: "SECRET"
client-authentication-method: POST
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/{action}/oauth2/code/{registrationId}"
client-name: Kakao
provider:
kakao:
authorization-uri: https://kauth.kakao.com/oauth/authorize
token-uri: https://kauth.kakao.com/oauth/token
user-info-uri: https://kapi.kakao.com/v2/user/me
user-name-attribute: id
3. Customizing the CustomOAuth2UserService
This component houses the core bridging translation logic transforming the raw foreign User Info natively into mapping correctly against your custom Entity schema.
@Service
@RequiredArgsConstructor
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
private final UserRepository userRepository;
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
// Init superclass behaviors inherently extracting unified Profile Information from Kakao/Google
OAuth2User oAuth2User = super.loadUser(userRequest);
// Identify originating Platform provider (google, kakao etc.)
String registrationId = userRequest.getClientRegistration().getRegistrationId();
// Parse User Data (Highly recommend establishing a Factory Pattern since differing platforms wield bizarrely structured JSONs)
OAuth2UserInfo userInfo = OAuth2UserInfoFactory.getOAuth2UserInfo(registrationId, oAuth2User.getAttributes());
// Query if Platform ID independently exists in our DB, if null gracefully Upsert(Save) an entirely new member identity
User user = userRepository.findByEmail(userInfo.getEmail())
.orElseGet(() -> userRepository.save(User.createSocialUser(userInfo)));
// Returns Authentication Object payload injected rigidly into the Security Sesssion (PrincipalDetails interface)
return new PrincipalDetails(user, oAuth2User.getAttributes());
}
}
Conclusively, engineering a robust SuccessHandler overriding that aggressively redirects the Browser (response.sendRedirect(...)) implicitly injecting your custom generated JWT heavily masked inside Header segments or URL query parameters transferring directly towards the Frontend territory culminates as the true bedrock of mastering Integrated OAuth2 Architectures.