diff --git a/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/config/security/SecurityConfiguration.kt b/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/config/security/SecurityConfiguration.kt index b4b38fb..07adeb3 100644 --- a/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/config/security/SecurityConfiguration.kt +++ b/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/config/security/SecurityConfiguration.kt @@ -1,5 +1,6 @@ package com.banjjoknim.playground.config.security +import com.banjjoknim.playground.domain.auth.OAuth2Type import com.banjjoknim.playground.domain.user.User import com.banjjoknim.playground.domain.user.UserRepository import org.springframework.context.annotation.Bean @@ -238,12 +239,15 @@ class PrincipalOAuth2UserService( println("${userRequest.additionalParameters}") // 5.1 버전 이후일 경우. // 강제로 회원가입 진행 + val oAuth2Type = OAuth2Type.findByProvider(userRequest.clientRegistration.registrationId) val oAuth2User = super.loadUser(userRequest) - val provider = userRequest.clientRegistration.clientId // google - val providerId = oAuth2User.attributes["sub"] // googleId(PK) + val oAuth2UserInfo = oAuth2Type.createOAuth2UserInfo(oAuth2User.attributes) + + val provider = oAuth2UserInfo.getProvider() // 값의 유무로 일반 로그인, OAuth2 로그인을 구분한다. + val providerId = oAuth2UserInfo.getProviderId() val username = "${provider}_${providerId}" // OAuth2 로 로그인시, 필요 없지만 그냥 만들어준다. val password = passwordEncoder.encode("비밀번호") // OAuth2 로 로그인시, 필요 없지만 그냥 만들어준다. - val email = oAuth2User.attributes["email"] + val email = oAuth2UserInfo.getEmail() val role = "ROLE_USER" // 회원가입 여부 확인 및 저장 @@ -252,10 +256,10 @@ class PrincipalOAuth2UserService( user = User( username = username, password = password, - email = email as String, + email = email, role = role, provider = provider, - providerId = providerId as String + providerId = providerId ) userRepository.save(user) // 회원정보 저장 diff --git a/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/domain/auth/OAuth2Type.kt b/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/domain/auth/OAuth2Type.kt new file mode 100644 index 0000000..c19f85c --- /dev/null +++ b/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/domain/auth/OAuth2Type.kt @@ -0,0 +1,22 @@ +package com.banjjoknim.playground.domain.auth + +enum class OAuth2Type( + private val provider: String, + private val createUserInfo: (attributes: Map) -> OAuth2UserInfo +) { + GOOGLE("google", { attributes -> GoogleUserInfo(attributes) }), + FACEBOOK("facebook", { attributes -> FacebookUserInfo(attributes) }); + + fun createOAuth2UserInfo(attributes: Map): OAuth2UserInfo { + return createUserInfo(attributes) + } + + companion object { + fun findByProvider(provider: String): OAuth2Type { + return values() + .find { oAuth2Type -> oAuth2Type.provider == provider } + ?: throw IllegalArgumentException("존재하지 않는 OAuth2 인증 타입입니다.") + } + } +} + diff --git a/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/domain/auth/OAuth2UserInfo.kt b/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/domain/auth/OAuth2UserInfo.kt new file mode 100644 index 0000000..777cb2b --- /dev/null +++ b/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/domain/auth/OAuth2UserInfo.kt @@ -0,0 +1,12 @@ +package com.banjjoknim.playground.domain.auth + +interface OAuth2UserInfo { + + fun getProviderId(): String + + fun getProvider(): String + + fun getEmail(): String + + fun getName(): String +} diff --git a/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/domain/auth/OAuth2UserInfos.kt b/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/domain/auth/OAuth2UserInfos.kt new file mode 100644 index 0000000..c145b7f --- /dev/null +++ b/놀이터(예제 코드 작성)/spring-security/src/main/kotlin/com/banjjoknim/playground/domain/auth/OAuth2UserInfos.kt @@ -0,0 +1,57 @@ +package com.banjjoknim.playground.domain.auth + +class GoogleUserInfo( + /** + * DefaultOAuth2Service#loadUser(OAuth2UserRequest) + * ```kotlin + * val oAuth2User = super.loadUser(userRequest) + * val attributes = oAuth2User.attributes + * ``` + */ + private val attributes: Map +) : OAuth2UserInfo { + + override fun getProviderId(): String { + return attributes["sub"] as String + } + + override fun getProvider(): String { + return "google" + } + + override fun getEmail(): String { + return attributes["email"] as String + } + + override fun getName(): String { + return attributes["name"] as String + } +} + +class FacebookUserInfo( + /** + * DefaultOAuth2Service#loadUser(OAuth2UserRequest) + * ```kotlin + * val oAuth2User = super.loadUser(userRequest) + * val attributes = oAuth2User.attributes + * ``` + */ + private val attributes: Map +) : OAuth2UserInfo { + override fun getProviderId(): String { + return attributes["id"] as String + } + + override fun getProvider(): String { + return "facebook" + } + + override fun getEmail(): String { + return attributes["email"] as String + } + + override fun getName(): String { + return attributes["name"] as String + } + +} diff --git a/놀이터(예제 코드 작성)/spring-security/src/main/resources/application.yml b/놀이터(예제 코드 작성)/spring-security/src/main/resources/application.yml index bd94e2c..d6de8fb 100644 --- a/놀이터(예제 코드 작성)/spring-security/src/main/resources/application.yml +++ b/놀이터(예제 코드 작성)/spring-security/src/main/resources/application.yml @@ -6,9 +6,17 @@ spring: google: client-id: my-google-client-id client-secret: my-google-client-secret + scope: + - email + - profile + facebook: client-id: my-facebook-client-id client-secret: my-facebook-client-secret + scope: + - email + - public_profile + naver: client-id: my-naver-client-id client-secret: my-naver-client-secret @@ -25,4 +33,3 @@ spring: token-uri: https://nid.naver.com/oauth2.0/token user-info-uri: https://openapi.naver.com/v1/nid/me user-name-attribute: response # 회원정보를 json으로 받는데 response라는 키값으로 네이버가 리턴해준다. -