Skip to content

Commit

Permalink
test
Browse files Browse the repository at this point in the history
  • Loading branch information
egg528 committed Feb 29, 2024
1 parent cb7c465 commit efc2423
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 3 deletions.
1 change: 1 addition & 0 deletions backend/application/api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies {

/* security */
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.bouncycastle:bcpkix-jdk18on:1.72")

/* oauth-client */
implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package io.raemian.api.auth.converter

import com.nimbusds.jose.util.IOUtils
import com.nimbusds.jose.util.StandardCharset
import io.jsonwebtoken.Jwts
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo
import org.bouncycastle.openssl.PEMParser
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter
import org.springframework.core.convert.converter.Converter
import org.springframework.core.io.ClassPathResource
import org.springframework.http.RequestEntity
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequestEntityConverter
import org.springframework.util.LinkedMultiValueMap
import java.io.StringReader
import java.security.PrivateKey
import java.time.LocalDateTime
import java.time.ZoneId
import java.util.Date


class TokenRequestEntityConverter: Converter<OAuth2AuthorizationCodeGrantRequest, RequestEntity<*>> {

private val defaultConverter = OAuth2AuthorizationCodeGrantRequestEntityConverter()
private val APPLE_URL = "https://appleid.apple.com"
private val APPLE_KEY_PATH = "static/AuthKey_L6LHNB5853.p8"
private val APPLE_CLIENT_ID = "com.app.bandiboodi"
private val APPLE_TEAM_ID = "R39H272X9N"
private val APPLE_KEY_ID = "L6LHNB5853"

override fun convert(req: OAuth2AuthorizationCodeGrantRequest): RequestEntity<*> {
val entity = defaultConverter.convert(req)!!
val registrationId = req.clientRegistration.registrationId
val params = entity.body as LinkedMultiValueMap<String, String>

if(registrationId.contains("apple")) {
params.set("client_secret", createClientSecret())
}

return RequestEntity<Any>(params, entity.headers, entity.method, entity.url)
}

fun getPrivateKey(): PrivateKey {
val resource = ClassPathResource(APPLE_KEY_PATH)
val converter = JcaPEMKeyConverter()

val input = resource.inputStream
val pemParser = PEMParser(StringReader(IOUtils.readInputStreamToString(input, StandardCharset.UTF_8)))
val key = pemParser.readObject() as PrivateKeyInfo

return converter.getPrivateKey(key)
}

fun createClientSecret(): String {
val expirationDate: Date =
Date.from(LocalDateTime.now().plusDays(30).atZone(ZoneId.systemDefault()).toInstant())
val jwtHeader = mapOf("kid" to APPLE_KEY_ID, "alg" to "ES256")

return Jwts.builder()
.setHeaderParams(jwtHeader)
.setIssuer(APPLE_TEAM_ID)
.setIssuedAt(Date(System.currentTimeMillis())) // 발행 시간 - UNIX 시간
.setExpiration(expirationDate) // 만료 시간
.setAudience(APPLE_URL)
.setSubject(APPLE_CLIENT_ID)
.signWith(getPrivateKey())
.compact();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,23 @@ class OAuth2UserService(
val provider =
OAuthProvider.valueOf(userRequest.clientRegistration.registrationId.uppercase())
) {
OAuthProvider.APPLE -> {
val email =
oAuth2User.attributes["email"]?.toString() ?: throw RuntimeException("구글 이메일이없음")

val name = oAuth2User.attributes["name"]?.toString()
val image = oAuth2User.attributes["picture"]?.toString() ?: ""
val user = upsert(
email = email,
image = image,
oAuthProvider = provider,
)
CurrentUser(
id = user.id!!,
email = email,
authorities = listOf(),
)
}
OAuthProvider.GOOGLE -> {
val email =
oAuth2User.attributes["email"]?.toString() ?: throw RuntimeException("구글 이메일이없음")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.raemian.api.config

import io.raemian.api.auth.converter.TokenRequestEntityConverter
import io.raemian.api.auth.domain.CurrentUser
import io.raemian.api.auth.service.OAuth2UserService
import io.raemian.api.support.TokenProvider
Expand All @@ -18,13 +19,17 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest
import org.springframework.security.web.DefaultSecurityFilterChain
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
import org.springframework.web.filter.CorsFilter
import java.nio.charset.StandardCharsets


@Configuration
@EnableWebSecurity
class WebSecurityConfig(
Expand Down Expand Up @@ -75,7 +80,8 @@ class WebSecurityConfig(
.anyRequest().authenticated()
}
.oauth2Login {
it.userInfoEndpoint { endpoint -> endpoint.userService(oAuth2UserService) }
it.tokenEndpoint { it.accessTokenResponseClient(accessTokenResponseClient()) }
.userInfoEndpoint { endpoint -> endpoint.userService(oAuth2UserService) }
it.successHandler { request, response, authentication ->
val user = authentication.principal as CurrentUser
response.contentType = MediaType.APPLICATION_JSON_VALUE
Expand Down Expand Up @@ -115,4 +121,12 @@ class WebSecurityConfig(
fun getPasswordEncoder(): PasswordEncoder {
return BCryptPasswordEncoder()
}

@Bean
fun accessTokenResponseClient(): OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> {
val accessTokenResponseClient = DefaultAuthorizationCodeTokenResponseClient()
accessTokenResponseClient.setRequestEntityConverter(TokenRequestEntityConverter())

return accessTokenResponseClient
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ spring:
token_uri: https://kauth.kakao.com/oauth/token
user-info-uri: https://kapi.kakao.com/v2/user/me
user_name_attribute: id
apple:
authorizationUri: https://appleid.apple.com/auth/authorize?scope=name%20email&response_mode=form_post
tokenUri: https://appleid.apple.com/auth/token
registration:
naver:
redirect-uri: ENC(4+bYmAkIEVrVaxN+PJN45Yw4OX+7ic6kI++xBfdUrAQue4vWC1apiXgr+jIHrd1/IIFxyyNHSzDYjxMT89gBjaIGUPuhX3lZ)
Expand All @@ -45,4 +48,14 @@ spring:
client-secret: ENC(Sv6L3GpxMxJA7s93BGorm6DclzLwJYSg8rezWXhkAi0PY85zzA/d7ulKspstKMY/)
scope:
- email
- profile
- profile
apple:
client-id: L6LHNB5853
client-secret: static/AuthKey_L6LHNB5853.p8
redirect-uri: https://www.one-bailey.o-r.kr/dev/api/login/oauth2/code/apple
authorizationGrantType: authorization_code
clientAuthenticationMethod: POST
clientName: Apple
scope:
- email
- name
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQga4FUpdhLY3Pb8feb
MYS+VanfU+FTjUgGY2Xx2cLR7+KgCgYIKoZIzj0DAQehRANCAAR5iFOVk0PP/LN+
8rlgxXKwviytJ95imMkvJr/CSNZ1W5VkkICjoyG/PV9tcY0XvlyAd6Z7scJ62Cyb
Dq6Ghiu+
-----END PRIVATE KEY-----
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package io.raemian.storage.db.core.user.enums

enum class OAuthProvider {
GOOGLE, NAVER, KAKAO
GOOGLE, NAVER, KAKAO, APPLE
}

0 comments on commit efc2423

Please sign in to comment.