Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[🚌 Issue] dev api 로그인 요청 위치에 따라 redirect url 변환 #245

Merged
merged 25 commits into from
Mar 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b99367c
delete: 유저 정보를 활용한 타임라인 조회 API 삭제
egg528 Mar 24, 2024
4249f81
refactor: PaginationResult.transform() 사용 방식 lamda 형태로 통일
egg528 Mar 24, 2024
854f4a2
refactor: 메서드 로직에 따라 get, find 명칭 구분
egg528 Mar 24, 2024
23aa5f9
refactor: lamda body 내 생략 가능한 parameter 생략
egg528 Mar 24, 2024
1c7d46f
refactor: 메서드명 내 부정확한 단어 제거(findGoalTimelineCountMap -> findGoalCount…
egg528 Mar 24, 2024
74b372b
refactor: associateWith 메서드 활용
egg528 Mar 24, 2024
54c8b81
refactor: PaginationResult total값 Long으로 다시 변경
egg528 Mar 24, 2024
ef9f69d
Merge branch 'develop' of github.com:depromeet/amazing3-be into featu…
egg528 Mar 26, 2024
30b557b
fix: 목표 피드 조회 API deadline 역순으로 정렬 조회
egg528 Mar 26, 2024
89264c7
Merge branch 'develop' of github.com:depromeet/amazing3-be into featu…
egg528 Mar 26, 2024
5425558
chore: apply lint
egg528 Mar 26, 2024
48e2709
fix: goals 테이블의 index 수정
egg528 Mar 26, 2024
a9135a1
refactor: pagination cusorId type Any -> Generic으로 변경
egg528 Mar 26, 2024
63bb7e9
Merge branch 'develop' of github.com:depromeet/amazing3-be into featu…
egg528 Mar 27, 2024
4c110bc
fix: 타임 라인 목표 조회 API paging 처리 방식 offset으로 변경
egg528 Mar 27, 2024
bb151c4
refactor: cursor 기반 pagination 공통 모듈 cursor type long으로 통일
egg528 Mar 27, 2024
0a00a11
refactor: pagination 공통 모듈 cursor와 offset 구분
egg528 Mar 27, 2024
c94c5b5
feat(#244): dev api 로그인 요청 위치에 따라 redirect url 변환
egg528 Mar 27, 2024
e97bc4e
chore: apply lint
egg528 Mar 27, 2024
583201f
fix: @Value(spring.profiles.active) default값 추가
egg528 Mar 27, 2024
e307c2d
refactor: 코드 리뷰 반영(#245)
egg528 Mar 28, 2024
1073e18
chore: encrypt하던 데이터 삭제
egg528 Mar 28, 2024
39ce4cc
chore: resolve conflict
egg528 Mar 28, 2024
128357d
chore: encrypted test properties 삭제
egg528 Mar 28, 2024
e27bb5b
chore: referer 저장/조회 logging 추가
egg528 Mar 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.raemian.api.support.limiter
package io.raemian.api.cheer.service

import com.github.benmanes.caffeine.cache.Caffeine
import org.springframework.stereotype.Component
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import io.raemian.api.cheer.model.CheeringCountResult
import io.raemian.api.event.model.CheeredEvent
import io.raemian.api.support.exception.CoreApiException
import io.raemian.api.support.exception.ErrorInfo
import io.raemian.api.support.limiter.CheeringLimiter
import io.raemian.api.support.response.CursorPaginationResult
import io.raemian.storage.db.core.cheer.CheerJdbcQueryRepository
import io.raemian.storage.db.core.cheer.Cheerer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import io.raemian.api.auth.converter.TokenRequestEntityConverter
import io.raemian.api.auth.model.CurrentUser
import io.raemian.api.auth.service.OAuth2UserService
import io.raemian.api.support.constant.WebSecurityConstant
import io.raemian.api.support.security.LoginRedirector
import io.raemian.api.support.security.StateOAuth2AuthorizationRequestRepository
import io.raemian.api.support.security.TokenProvider
import jakarta.servlet.http.HttpServletResponse
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType
import org.springframework.security.config.annotation.SecurityConfigurerAdapter
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
Expand All @@ -25,16 +24,14 @@ import org.springframework.security.web.DefaultSecurityFilterChain
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
import org.springframework.web.filter.CorsFilter
import java.nio.charset.StandardCharsets

@Configuration
@EnableWebSecurity
class WebSecurityConfig(
private val corsFilter: CorsFilter,
private val tokenProvider: TokenProvider,
private val oAuth2UserService: OAuth2UserService,
@Value("\${spring.profiles.active:local}")
private val profile: String,
private val loginRedirector: LoginRedirector,
private val tokenRequestEntityConverter: TokenRequestEntityConverter,
private val httpCookieOAuth2AuthorizationRequestRepository: StateOAuth2AuthorizationRequestRepository,
) : SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>() {
Expand Down Expand Up @@ -66,23 +63,9 @@ class WebSecurityConfig(
it.authorizationEndpoint { it.authorizationRequestRepository(httpCookieOAuth2AuthorizationRequestRepository) }
it.successHandler { request, response, authentication ->
val user = authentication.principal as CurrentUser
response.contentType = MediaType.APPLICATION_JSON_VALUE
response.characterEncoding = StandardCharsets.UTF_8.name()

val tokenDTO = tokenProvider.generateTokenDto(user)
response.setHeader("x-token", tokenDTO.accessToken)
log.info("x-token access ${tokenDTO.accessToken}")

// TODO edit redirect url
val referer = request.getHeader("referer")
val redirectUrl =
if (profile == "live") {
"https://bandiboodi.com/oauth2/token"
} else {
"http://localhost:3000/oauth2/token"
}

response.sendRedirect("$redirectUrl?token=${tokenDTO.accessToken}&refresh=${tokenDTO.refreshToken}")
val token = tokenProvider.generateTokenDto(user)
val redirectUrl = loginRedirector.getUrl(request.getParameter("state"), token)
response.sendRedirect(redirectUrl)
}
it.failureHandler { request, response, exception ->
log.error("x-token error ${exception.message}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.raemian.api.support.security

import io.raemian.api.auth.model.Token
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component

@Component
class LoginRedirector(
val profilePlaceHolder: ProfileHolder,
val redirectUrlHolder: RedirectUrlHolder,
val loginRequestRefererStorage: LoginRequestRefererStorage,
) {
private val log = LoggerFactory.getLogger(javaClass)

fun getUrl(state: String, token: Token): String {
if (profilePlaceHolder.isLive()) {
return "${redirectUrlHolder.live}?token=${token.accessToken}&refresh=${token.refreshToken}"
}

val referer = loginRequestRefererStorage.get(state)
log.info("get referer: {}", referer)

if (profilePlaceHolder.isDev() && referer.contains("dev-bandiboodi")) {
return "${redirectUrlHolder.dev}?token=${token.accessToken}&refresh=${token.refreshToken}"
}

return "${redirectUrlHolder.local}?token=${token.accessToken}&refresh=${token.refreshToken}"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.raemian.api.support.security

import com.github.benmanes.caffeine.cache.Caffeine
import org.springframework.stereotype.Component
import java.util.concurrent.TimeUnit

@Component
class LoginRequestRefererStorage {
private val timedStorage = Caffeine.newBuilder()
.expireAfterWrite(60L, TimeUnit.SECONDS)
.build<String, String>()

fun put(state: String, referer: String?) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[[ 100% 취향 제안 ]]
저도 자바에 익숙해서 우석님이랑 항상 같은 방식으로 코드를 작성했는데요?
요즘 코틀린 코드들 다른데서 보면서 아래와 같은 코드도 조금 이뻐 보이이기 시작했는데 어떠신가요..

put() = if (referer.isNullOrBlank()) return
else timedStorage.put(state, referer)

혹은.. 확장함수 활용해서 isNotNullOrBlank() 구현한 다음..

fun put() {
  if (referer.isNotNullOrBlank()) 
    timedStorage.put(state, referer)
}

완전 취향이고 지금 얼리 리턴 방식도 너무 좋아요 저도 보통 그렇게 작성해왔던 것 같아요.
어떤지 한번 얘기해보고 싶어서 올려봐요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 얼리 리턴을 위한 조건문은 명시적으로 작성하는 편이 잘 읽힌다고 생각하는 편이였는데요.
진호님이 제시해주신 첫번째 코드 (if문 Expression으로 사용)를 보니 한번 사용해보고 싶다는 생각이 들었습니다 ㅎㅎ
첫번째 방식으로 수정 한번 해보겠습니다!
제안 감사합니다 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@binary-ho
제안 감사합니다 👍

추가 제안 ㅆㄱㄴ

if (referer.isNullOrBlank()) {
return
} else {
timedStorage.put(state, referer)
}
}

fun get(state: String): String {
return timedStorage.getIfPresent(state) ?: ""
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.raemian.api.support.security

import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component

@Component
class ProfileHolder(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@binary-ho
제안 감사합니다 👍

추가 제안 ㅆㄱㄴ

@Value("\${spring.profiles.active:local}")
private val profile: String,
) {
fun isLive(): Boolean {
return ProfileType.fromString(profile) == ProfileType.LIVE
}

fun isDev(): Boolean {
return ProfileType.fromString(profile) == ProfileType.DEV
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.raemian.api.support.security

enum class ProfileType(
Copy link
Member Author

@egg528 egg528 Mar 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ManHyuk
제안 감사합니다 👍

추가 제안 ㅆㄱㄴ

value: String,
) {
LIVE("live"),
DEV("dev"),
LOCAL("local"), ;
companion object {
fun fromString(value: String): ProfileType =
when (value) {
"live" -> LIVE
"dev" -> DEV
else -> LOCAL
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.raemian.api.support.security

import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties(prefix = "redirect-url")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@binary-ho
2개의 제안을 합쳐서 RedirectUrlHolder에 ConfigurationProperties를 적용해봤습니다!
제안 감사합니다 👍

추가 제안 ㅆㄱㄴ

data class RedirectUrlHolder(
val live: String,
val dev: String,
val local: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@ import com.github.benmanes.caffeine.cache.Cache
import com.github.benmanes.caffeine.cache.Caffeine
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.slf4j.LoggerFactory
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest
import org.springframework.stereotype.Component
import java.util.concurrent.TimeUnit

@Component
class StateOAuth2AuthorizationRequestRepository() : AuthorizationRequestRepository<OAuth2AuthorizationRequest> {
class StateOAuth2AuthorizationRequestRepository(
val profilePlaceHolder: ProfileHolder,
val loginRequestRefererStorage: LoginRequestRefererStorage,
) : AuthorizationRequestRepository<OAuth2AuthorizationRequest> {
private val log = LoggerFactory.getLogger(javaClass)

private val oauthRequestStorage: Cache<String, OAuth2AuthorizationRequest> = Caffeine.newBuilder()
.expireAfterWrite(60L, TimeUnit.SECONDS)
.build()
Expand All @@ -25,6 +31,12 @@ class StateOAuth2AuthorizationRequestRepository() : AuthorizationRequestReposito
response: HttpServletResponse,
) {
if (authorizationRequest != null) {
/*** for frontend dev test ***/
if (profilePlaceHolder.isDev()) {
log.info("save referer: {}", request.getParameter("referer"))
loginRequestRefererStorage.put(authorizationRequest.state, request.getParameter("referer"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

프로필래핑 객체가 있다면 여기서도 활용이 가능하다는 장점 ㅎㅎ (어필)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제안 감사합니다 👍

추가 제안 ㅆㄱㄴ

}

oauthRequestStorage.put(authorizationRequest.state, authorizationRequest)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ apple-login:
team-id: ENC(jzk4UvjfcLerYSo05oJ8vNGGxgt4SLuS)
key-id: ENC(T/yX80PVdBkgQcFkOs/H2dFgAuBKDeNR)

redirect-url:
live: ENC(n7sXFCoABK2wVGKkMdhVLJEtvfHXtds+NwvpxWntSnYArf3DGN2cFbKlCR9hIACj)
dev: ENC(ZOWsz9hwBfF4yJrxHevHshhkGZqYuS9XyoFFLQQea473KOSJoKg2zMgHOGXkoGGz8jZ3Zc4rnQE=)
local: ENC(LxpM8W1yvAXRpin++amkeEhqGXro90Y2E3tQgD4EzOJnOZfBVKST3TF/0T3CqvZZ)


spring:
security:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ apple-login:
team-id: ENC(jzk4UvjfcLerYSo05oJ8vNGGxgt4SLuS)
key-id: ENC(T/yX80PVdBkgQcFkOs/H2dFgAuBKDeNR)

redirect-url:
live: ENC(n7sXFCoABK2wVGKkMdhVLJEtvfHXtds+NwvpxWntSnYArf3DGN2cFbKlCR9hIACj)
dev: ENC(ZOWsz9hwBfF4yJrxHevHshhkGZqYuS9XyoFFLQQea473KOSJoKg2zMgHOGXkoGGz8jZ3Zc4rnQE=)
local: ENC(LxpM8W1yvAXRpin++amkeEhqGXro90Y2E3tQgD4EzOJnOZfBVKST3TF/0T3CqvZZ)

spring:
security:
oauth2:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ apple-login:
team-id: ENC(jzk4UvjfcLerYSo05oJ8vNGGxgt4SLuS)
key-id: ENC(T/yX80PVdBkgQcFkOs/H2dFgAuBKDeNR)

redirect-url:
live: ENC(n7sXFCoABK2wVGKkMdhVLJEtvfHXtds+NwvpxWntSnYArf3DGN2cFbKlCR9hIACj)
dev: ENC(ZOWsz9hwBfF4yJrxHevHshhkGZqYuS9XyoFFLQQea473KOSJoKg2zMgHOGXkoGGz8jZ3Zc4rnQE=)
local: ENC(LxpM8W1yvAXRpin++amkeEhqGXro90Y2E3tQgD4EzOJnOZfBVKST3TF/0T3CqvZZ)


spring:
security:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ apple-login:
team-id: EMPTY-VALUE
key-id: EMPTY-VALUE

redirect-url:
live: EMPTY-VALUE
dev: EMPTY-VALUE
local: EMPTY-VALUE

spring:
security:
oauth2:
Expand Down Expand Up @@ -62,7 +67,7 @@ spring:
redirect-uri: EMPTY-VALUE
authorizationGrantType: authorization_code
clientAuthenticationMethod: POST
clientName: pple
clientName: apple
scope:
- email
- name
Loading