Adds JWT secret, turns on Swagger UI, and cleans up refresh token response

This commit is contained in:
2026-05-12 00:26:35 -05:00
parent 0c01c5dbcc
commit 2e0244e1ee
7 changed files with 38 additions and 9 deletions

View File

@@ -31,7 +31,9 @@ class AuthTokenFilter(private val jwtUtils: JwtUtil, private val hunterDetailsSe
userDetails.authorities userDetails.authorities
) )
authentication.details = WebAuthenticationDetailsSource().buildDetails(request) authentication.details = WebAuthenticationDetailsSource().buildDetails(request)
SecurityContextHolder.getContext().authentication = authentication val context = SecurityContextHolder.createEmptyContext()
context.authentication = authentication
SecurityContextHolder.setContext(context)
} }
} catch (e: Exception) { } catch (e: Exception) {
println("Cannot set user authentication: $e") println("Cannot set user authentication: $e")

View File

@@ -7,11 +7,12 @@ import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
import java.util.Date import java.util.Date
import javax.crypto.SecretKey import javax.crypto.SecretKey
import javax.crypto.spec.SecretKeySpec
@Component @Component
class JwtUtil { class JwtUtil {
@Value($$"${jwt.secret}") @Value($$"${jwt.secret}")
private val jwtSecret: String? = null private val jwtSecret: String = ""
@Value($$"${jwt.expiration}") @Value($$"${jwt.expiration}")
private val jwtExpirationMs = 0 private val jwtExpirationMs = 0
@@ -22,7 +23,7 @@ class JwtUtil {
// preventing the repeated creation of the key and enhancing performance // preventing the repeated creation of the key and enhancing performance
@PostConstruct @PostConstruct
fun init() { fun init() {
this.key = Jwts.SIG.HS256.key().build() this.key = SecretKeySpec(jwtSecret.toByteArray(Charsets.UTF_8), "HmacSHA256")
} }
// Generate JWT token // Generate JWT token

View File

@@ -1,5 +1,6 @@
package net.halfbinary.scavengerhuntapi.config package net.halfbinary.scavengerhuntapi.config
import org.springframework.boot.web.servlet.FilterRegistrationBean
import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Configuration
import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.authentication.AuthenticationManager
@@ -27,6 +28,13 @@ class SecurityConfig(private val authEntrypointJwt: AuthEntrypointJwt,
return authTokenFilter return authTokenFilter
} }
@Bean
fun authTokenFilterRegistration(): FilterRegistrationBean<AuthTokenFilter> {
val registration = FilterRegistrationBean(authTokenFilter)
registration.isEnabled = false
return registration
}
@Bean @Bean
@Throws(Exception::class) @Throws(Exception::class)
fun authenticationManager( fun authenticationManager(
@@ -59,7 +67,7 @@ class SecurityConfig(private val authEntrypointJwt: AuthEntrypointJwt,
} }
.authorizeHttpRequests { authorizeRequests -> .authorizeHttpRequests { authorizeRequests ->
authorizeRequests authorizeRequests
.requestMatchers("/auth/**", "/signup") .requestMatchers("/auth/**", "/signup", "/docs/**")
.permitAll() .permitAll()
.anyRequest().authenticated() .anyRequest().authenticated()
} }

View File

@@ -4,10 +4,12 @@ import jakarta.servlet.http.HttpServletResponse
import jakarta.validation.Valid import jakarta.validation.Valid
import net.halfbinary.scavengerhuntapi.config.JwtUtil import net.halfbinary.scavengerhuntapi.config.JwtUtil
import net.halfbinary.scavengerhuntapi.model.converter.toDomain import net.halfbinary.scavengerhuntapi.model.converter.toDomain
import net.halfbinary.scavengerhuntapi.model.converter.toRefreshResponse
import net.halfbinary.scavengerhuntapi.model.request.LoginRequest import net.halfbinary.scavengerhuntapi.model.request.LoginRequest
import net.halfbinary.scavengerhuntapi.model.request.LogoutRequest import net.halfbinary.scavengerhuntapi.model.request.LogoutRequest
import net.halfbinary.scavengerhuntapi.model.request.RefreshRequest import net.halfbinary.scavengerhuntapi.model.request.RefreshRequest
import net.halfbinary.scavengerhuntapi.model.response.LoginResponse import net.halfbinary.scavengerhuntapi.model.response.LoginResponse
import net.halfbinary.scavengerhuntapi.model.response.RefreshResponse
import net.halfbinary.scavengerhuntapi.service.LoginService import net.halfbinary.scavengerhuntapi.service.LoginService
import net.halfbinary.scavengerhuntapi.service.RefreshTokenService import net.halfbinary.scavengerhuntapi.service.RefreshTokenService
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
@@ -26,7 +28,6 @@ class AuthController(private val loginService: LoginService, private val jwtUtil
@PostMapping("/login") @PostMapping("/login")
fun login(@Valid @RequestBody body: LoginRequest, response: HttpServletResponse): ResponseEntity<LoginResponse> { fun login(@Valid @RequestBody body: LoginRequest, response: HttpServletResponse): ResponseEntity<LoginResponse> {
val result = loginService.login(body.toDomain()) val result = loginService.login(body.toDomain())
// TODO: Figure out how to use the authorities
val hunterAuthorities = val hunterAuthorities =
if (result.isAdmin) { if (result.isAdmin) {
SimpleGrantedAuthority("ROLE_ADMIN") SimpleGrantedAuthority("ROLE_ADMIN")
@@ -41,8 +42,8 @@ class AuthController(private val loginService: LoginService, private val jwtUtil
} }
@PostMapping("/refresh") @PostMapping("/refresh")
fun refresh(@RequestBody body: RefreshRequest): String { fun refresh(@RequestBody body: RefreshRequest): ResponseEntity<RefreshResponse> {
return refreshTokenService.getAccessToken(body.refreshToken) return ResponseEntity.ok(refreshTokenService.getAccessToken(body.refreshToken).toRefreshResponse())
} }
@PostMapping("/logout") @PostMapping("/logout")

View File

@@ -0,0 +1,7 @@
package net.halfbinary.scavengerhuntapi.model.converter
import net.halfbinary.scavengerhuntapi.model.response.RefreshResponse
fun String.toRefreshResponse(): RefreshResponse {
return RefreshResponse(this)
}

View File

@@ -0,0 +1,5 @@
package net.halfbinary.scavengerhuntapi.model.response
data class RefreshResponse(
val accessToken: String
)

View File

@@ -4,10 +4,15 @@ spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.type.preferred_uuid_jdbc_type=CHAR spring.jpa.properties.hibernate.type.preferred_uuid_jdbc_type=CHAR
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver spring.datasource.driverClassName=org.mariadb.jdbc.Driver
spring.datasource.url=${DB_URL} spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USER} spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD} spring.datasource.password=${DB_PASSWORD}
jwt.secret=${JWT_SECRET} jwt.secret=${JWT_SECRET}
jwt.expiration=30000 jwt.expiration=300000
springdoc.api-docs.enabled=true
springdoc.api-docs.path=/docs/api-docs
springdoc.swagger-ui.enabled=true
springdoc.swagger-ui.path=/docs/swagger-ui.html