Skip to content

Commit

Permalink
Update auth flow (#50)
Browse files Browse the repository at this point in the history
* Update auth flow

* #50 Update auth flow

---------

Co-authored-by: akselsf <akselsf>
  • Loading branch information
akselsf authored Feb 9, 2025
1 parent db6040d commit 32b0294
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 32 deletions.
2 changes: 2 additions & 0 deletions src/main/kotlin/com/example/autobank/AutobankApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.example.autobank

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.ComponentScan


@SpringBootApplication
class AutobankApplication
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.example.autobank.controller


import com.example.autobank.data.authentication.AuthenticatedUserResponse
import com.example.autobank.service.AuthenticationService
import com.example.autobank.service.OnlineUserService
import jakarta.servlet.http.HttpServletRequest
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.http.ResponseCookie
import org.springframework.web.bind.annotation.*


@RestController
Expand All @@ -20,16 +22,56 @@ class AuthenticationController {
@Autowired
lateinit var authenticationService: AuthenticationService;

@GetMapping("/check")
fun checkUser(): ResponseEntity<AuthenticatedUserResponse> {
@GetMapping("/setuser")
fun setCookie(@RequestHeader("Authorization") authHeader: String): ResponseEntity<Any> {
val token = authHeader.replace("Bearer ", "")

return try {
ResponseEntity.ok(onlineUserService.checkUser())
} catch (e: Exception) {
print(e)
ResponseEntity.badRequest().build();
}
val cookie = ResponseCookie.from("access_token", token)
.httpOnly(true)
.secure(true)
.path("/")
.maxAge(60)
.build()

return ResponseEntity.ok()
.header("Set-Cookie", cookie.toString())
.body(mapOf("success" to true))
}

@GetMapping("/getuser")
fun checkUser(@CookieValue("access_token") token: String?): ResponseEntity<AuthenticatedUserResponse> {
if (token.isNullOrEmpty()) {
return ResponseEntity.status(401).build()
}

println("Checking user")
val cookie = ResponseCookie.from("access_token", token)
.httpOnly(true)
.secure(true)
.path("/")
.maxAge(authenticationService.getSecondsUntilExpiration())
.build()

return try {
ResponseEntity.ok().header("Set-Cookie", cookie.toString()).body(onlineUserService.checkUser())
} catch (e: Exception) {
print(e)
ResponseEntity.badRequest().build();
}
}

@GetMapping("/logout")
fun logout(request: HttpServletRequest): ResponseEntity<Any> {
val cookie = ResponseCookie.from("access_token", "")
.httpOnly(true)
.secure(false)
.path("/")
.maxAge(0)
.build()

return ResponseEntity.ok()
.header("Set-Cookie", cookie.toString())
.body(mapOf("success" to true))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ class AuthenticatedUserResponse(
val success: Boolean,
val isadmin: Boolean,
val issuperadmin: Boolean,
val expiresat: Instant?
val expiresat: Instant?,
val fullname: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import jakarta.servlet.http.HttpServletRequest
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver
import org.springframework.util.StringUtils

class CookieTokenResolver : BearerTokenResolver {

private val tokenName = "access_token"

override fun resolve(request: HttpServletRequest): String? {
val cookies = request.cookies ?: return null
val tokenCookie = cookies.find { it.name == tokenName }

return tokenCookie?.value?.takeIf { StringUtils.hasText(it) }
}

}
53 changes: 37 additions & 16 deletions src/main/kotlin/com/example/autobank/security/SecurityConfig.kt
Original file line number Diff line number Diff line change
@@ -1,40 +1,61 @@
package com.example.autobank.security




import CookieTokenResolver
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator
import org.springframework.security.oauth2.core.OAuth2TokenValidator
import org.springframework.security.oauth2.jwt.*
import org.springframework.security.oauth2.jwt.JwtDecoders
import org.springframework.security.oauth2.jwt.JwtDecoder
import org.springframework.security.oauth2.jwt.JwtValidators
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.util.matcher.AntPathRequestMatcher

@EnableWebSecurity
class SecurityConfig() {
@Configuration
class SecurityConfig {

@Value("\${auth0.audience}")
private val audience: String = String()
private val audience: String = ""

@Value("\${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
private val issuer: String = String()
private val issuer: String = ""

@Bean
fun jwtDecoder(): JwtDecoder {
val jwtDecoder = JwtDecoders.fromOidcIssuerLocation(issuer) as NimbusJwtDecoder
val audienceValidator: OAuth2TokenValidator<Jwt> = AudienceValidator(audience)
val withIssuer: OAuth2TokenValidator<Jwt> = JwtValidators.createDefaultWithIssuer(issuer)
val withAudience: OAuth2TokenValidator<Jwt> = DelegatingOAuth2TokenValidator(withIssuer, audienceValidator)
jwtDecoder.setJwtValidator(withAudience)
val withIssuer = JwtValidators.createDefaultWithIssuer(issuer)
jwtDecoder.setJwtValidator(withIssuer)
return jwtDecoder
}

@Bean
@Throws(Exception::class)
fun filterChain(http: HttpSecurity): SecurityFilterChain {
return http.authorizeHttpRequests { authz ->
authz.anyRequest().authenticated()
}.build()
fun bearerTokenResolver(): BearerTokenResolver {
return CookieTokenResolver()
}

}
@Bean
@Override
fun filterChain(http: HttpSecurity, bearerTokenResolver: BearerTokenResolver): SecurityFilterChain {
println("YEEEEEEEEEEEEE")
return http
.authorizeHttpRequests { authz ->
authz
.requestMatchers(AntPathRequestMatcher("/api/auth/setuser")).permitAll()
.anyRequest().authenticated()
}
.oauth2ResourceServer { oauth2 ->
oauth2
.bearerTokenResolver(bearerTokenResolver)
.jwt { jwt -> jwt.decoder(jwtDecoder()) }
}
.csrf { csrf -> csrf.disable() }
.build()
}
}
4 changes: 2 additions & 2 deletions src/main/kotlin/com/example/autobank/security/WebConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ class WebConfig : WebMvcConfigurer {

override fun addCorsMappings(registry: CorsRegistry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000", "https://autobank-frontend.vercel.app") // Add your frontend URL here e.
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedOrigins("http://localhost:3000", "https://autobank-frontend.vercel.app")
.allowedMethods("GET", "POST")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ class AuthenticationService {
return Auth0User("sub", "email", "name")
}

fun getSecondsUntilExpiration(): Long {
val expiresAt = getExpiresAt()
return if (expiresAt != null) {
expiresAt.epochSecond - Instant.now().epochSecond
} else {
0
}
}

fun getUserSub(): String {
val authentication = SecurityContextHolder.getContext().authentication
return if (authentication is JwtAuthenticationToken) {
Expand All @@ -50,6 +59,10 @@ class AuthenticationService {
}
}

fun getFullName(): String {
return "";
}

fun getAccessToken(): String {
val authentication = SecurityContextHolder.getContext().authentication
return if (authentication is JwtAuthenticationToken) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ class OnlineUserService(
try {
createOnlineUser()
} catch (e: Exception) {
return AuthenticatedUserResponse(success = false, false, false, null)
return AuthenticatedUserResponse(success = false, false, false, null, "")
}
}

return AuthenticatedUserResponse(success = true, authenticationService.checkBankomMembership(), authenticationService.checkSuperAdmin(), expiresat = authenticationService.getExpiresAt())
return AuthenticatedUserResponse(success = true, authenticationService.checkBankomMembership(), authenticationService.checkSuperAdmin(), expiresat = authenticationService.getExpiresAt(), fullname = authenticationService.getFullName())
}

fun createOnlineUser(): OnlineUser {
Expand Down

0 comments on commit 32b0294

Please sign in to comment.