Fix auth verify access and token fallback
All checks were successful
build-and-deploy / build-deploy (push) Successful in 27s
All checks were successful
build-and-deploy / build-deploy (push) Successful in 27s
This commit is contained in:
@@ -5,6 +5,8 @@ import com.android.trisolarisserver.controller.dto.UserResponse
|
|||||||
import com.android.trisolarisserver.repo.AppUserRepo
|
import com.android.trisolarisserver.repo.AppUserRepo
|
||||||
import com.android.trisolarisserver.repo.PropertyUserRepo
|
import com.android.trisolarisserver.repo.PropertyUserRepo
|
||||||
import com.android.trisolarisserver.security.MyPrincipal
|
import com.android.trisolarisserver.security.MyPrincipal
|
||||||
|
import com.google.firebase.auth.FirebaseAuth
|
||||||
|
import jakarta.servlet.http.HttpServletRequest
|
||||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
import org.springframework.web.bind.annotation.PostMapping
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
@@ -21,13 +23,19 @@ class Auth(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
@PostMapping("/verify")
|
@PostMapping("/verify")
|
||||||
fun verify(@AuthenticationPrincipal principal: MyPrincipal?): AuthResponse {
|
fun verify(
|
||||||
return buildAuthResponse(principal)
|
@AuthenticationPrincipal principal: MyPrincipal?,
|
||||||
|
request: HttpServletRequest
|
||||||
|
): AuthResponse {
|
||||||
|
return buildAuthResponse(principal ?: resolvePrincipalFromHeader(request))
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/me")
|
@GetMapping("/me")
|
||||||
fun me(@AuthenticationPrincipal principal: MyPrincipal?): AuthResponse {
|
fun me(
|
||||||
return buildAuthResponse(principal)
|
@AuthenticationPrincipal principal: MyPrincipal?,
|
||||||
|
request: HttpServletRequest
|
||||||
|
): AuthResponse {
|
||||||
|
return buildAuthResponse(principal ?: resolvePrincipalFromHeader(request))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildAuthResponse(principal: MyPrincipal?): AuthResponse {
|
private fun buildAuthResponse(principal: MyPrincipal?): AuthResponse {
|
||||||
@@ -56,6 +64,28 @@ class Auth(
|
|||||||
properties = memberships
|
properties = memberships
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun resolvePrincipalFromHeader(request: HttpServletRequest): MyPrincipal {
|
||||||
|
val header = request.getHeader("Authorization") ?: throw ResponseStatusException(
|
||||||
|
HttpStatus.UNAUTHORIZED,
|
||||||
|
"Missing Authorization token"
|
||||||
|
)
|
||||||
|
if (!header.startsWith("Bearer ")) {
|
||||||
|
throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid Authorization header")
|
||||||
|
}
|
||||||
|
val token = header.removePrefix("Bearer ").trim()
|
||||||
|
val decoded = try {
|
||||||
|
FirebaseAuth.getInstance().verifyIdToken(token)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid token")
|
||||||
|
}
|
||||||
|
val user = appUserRepo.findByFirebaseUid(decoded.uid)
|
||||||
|
?: throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "User not found")
|
||||||
|
return MyPrincipal(
|
||||||
|
userId = user.id ?: throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "User id missing"),
|
||||||
|
firebaseUid = decoded.uid
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AuthResponse(
|
data class AuthResponse(
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class FirebaseAuthFilter(
|
|||||||
|
|
||||||
override fun shouldNotFilter(request: HttpServletRequest): Boolean {
|
override fun shouldNotFilter(request: HttpServletRequest): Boolean {
|
||||||
val path = request.requestURI
|
val path = request.requestURI
|
||||||
return path == "/" || path == "/health"
|
return path == "/" || path == "/health" || path.startsWith("/auth/")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doFilterInternal(
|
override fun doFilterInternal(
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.springframework.core.annotation.Order
|
|||||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity
|
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy
|
import org.springframework.security.config.http.SessionCreationPolicy
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer
|
||||||
import org.springframework.security.web.SecurityFilterChain
|
import org.springframework.security.web.SecurityFilterChain
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
|
||||||
|
|
||||||
@@ -14,6 +15,13 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
|
|||||||
class SecurityConfig(
|
class SecurityConfig(
|
||||||
private val firebaseAuthFilter: FirebaseAuthFilter
|
private val firebaseAuthFilter: FirebaseAuthFilter
|
||||||
) {
|
) {
|
||||||
|
@Bean
|
||||||
|
fun webSecurityCustomizer(): WebSecurityCustomizer {
|
||||||
|
return WebSecurityCustomizer {
|
||||||
|
it.ignoring().requestMatchers("/", "/health", "/auth/**")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Order(1)
|
@Order(1)
|
||||||
fun publicChain(http: HttpSecurity): SecurityFilterChain {
|
fun publicChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
|
|||||||
Reference in New Issue
Block a user