-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature/24 prepare backend auth (#37)
* add BE auth (FilterChain, loadByUser, authUser, SecurityConfiguration), also add authUser entity. * add test, changed liquibase authUser emailt to unique, add logout with bean handlers and registrastion with login --------- Co-authored-by: Štěpán Moc <[email protected]>
- Loading branch information
Showing
46 changed files
with
1,692 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,3 +41,4 @@ out/ | |
|
||
### custom ### | ||
config/application.yml | ||
*.jpb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
backend/src/main/kotlin/com/tul/backend/BackendApplication.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 0 additions & 17 deletions
17
backend/src/main/kotlin/com/tul/backend/auth/base/SecurityConfig.kt
This file was deleted.
Oops, something went wrong.
26 changes: 26 additions & 0 deletions
26
backend/src/main/kotlin/com/tul/backend/auth/base/config/JwtAuthenticationFilter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.tul.backend.auth.base.config | ||
|
||
import com.tul.backend.auth.base.service.TokenFilterService | ||
import jakarta.servlet.FilterChain | ||
import jakarta.servlet.http.HttpServletRequest | ||
import jakarta.servlet.http.HttpServletResponse | ||
import org.springframework.stereotype.Component | ||
import org.springframework.web.filter.OncePerRequestFilter | ||
|
||
@Component | ||
class JwtAuthenticationFilter( | ||
private val tokenFilterService: TokenFilterService | ||
|
||
) : OncePerRequestFilter() { | ||
override fun doFilterInternal( | ||
request: HttpServletRequest, | ||
response: HttpServletResponse, | ||
filterChain: FilterChain | ||
) { | ||
val userDetails = tokenFilterService.validateRequest(request) | ||
if (userDetails != null) { | ||
tokenFilterService.updateContext(userDetails, request, response) | ||
} | ||
filterChain.doFilter(request, response) | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
backend/src/main/kotlin/com/tul/backend/auth/base/config/JwtConfiguration.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.tul.backend.auth.base.config | ||
|
||
import com.tul.backend.auth.base.service.CustomPasswordEncoder | ||
import com.tul.backend.auth.base.service.CustomUserDetailsService | ||
import com.tul.backend.auth.repository.AuthUserRepository | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.security.authentication.AuthenticationManager | ||
import org.springframework.security.authentication.AuthenticationProvider | ||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider | ||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration | ||
import org.springframework.security.core.userdetails.UserDetailsService | ||
import org.springframework.security.crypto.password.PasswordEncoder | ||
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler | ||
import org.springframework.security.web.authentication.logout.LogoutHandler | ||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler | ||
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler | ||
|
||
|
||
@Configuration | ||
class JwtConfiguration { | ||
|
||
@Bean | ||
fun userDetailService(authUserRepository: AuthUserRepository): UserDetailsService = | ||
CustomUserDetailsService(authUserRepository) | ||
|
||
@Bean | ||
fun encoder(): PasswordEncoder = CustomPasswordEncoder() | ||
|
||
@Bean | ||
fun authenticationProvider(authUserRepository: AuthUserRepository): AuthenticationProvider = | ||
DaoAuthenticationProvider() | ||
.also { | ||
it.setUserDetailsService(userDetailService(authUserRepository)) | ||
it.setPasswordEncoder(encoder()) | ||
} | ||
|
||
@Bean | ||
fun authenticationManager(config: AuthenticationConfiguration): AuthenticationManager = | ||
config.authenticationManager | ||
|
||
@Bean | ||
fun logoutSuccessHandler(): LogoutSuccessHandler { | ||
val handler = SimpleUrlLogoutSuccessHandler() | ||
handler.setUseReferer(true) | ||
return handler | ||
} | ||
|
||
@Bean | ||
fun cookieClearingLogoutHandler(): LogoutHandler { | ||
return CookieClearingLogoutHandler("access_token") | ||
} | ||
} |
81 changes: 81 additions & 0 deletions
81
backend/src/main/kotlin/com/tul/backend/auth/base/config/SecurityConfiguration.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package com.tul.backend.auth.base.config | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import com.tul.backend.auth.base.dto.ErrorDTO | ||
import com.tul.backend.auth.base.valueobject.AuthUserRole | ||
import jakarta.servlet.http.HttpServletRequest | ||
import jakarta.servlet.http.HttpServletResponse | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.http.MediaType | ||
import org.springframework.security.authentication.AuthenticationProvider | ||
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.configuration.EnableWebSecurity | ||
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer | ||
import org.springframework.security.config.http.SessionCreationPolicy | ||
import org.springframework.security.core.AuthenticationException | ||
import org.springframework.security.web.DefaultSecurityFilterChain | ||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter | ||
import org.springframework.security.web.authentication.logout.LogoutHandler | ||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler | ||
|
||
|
||
@Configuration | ||
@EnableWebSecurity | ||
@EnableMethodSecurity | ||
class SecurityConfiguration( | ||
private val objectMapper: ObjectMapper, | ||
private val authenticationProvider: AuthenticationProvider, | ||
private val logoutSuccessHandler: LogoutSuccessHandler, | ||
private val cookieClearingLogoutHandler: LogoutHandler | ||
) { | ||
private val userUnsecuredEndpoints = | ||
arrayOf( | ||
"/api/auth/login", | ||
"/api/auth/register", | ||
) | ||
|
||
private val adminUnsecuredEndpoints = | ||
arrayOf( | ||
"api/auth/test" | ||
) | ||
|
||
@Bean | ||
fun securityFilterChain( | ||
http: HttpSecurity, | ||
jwtAuthenticationFilter: JwtAuthenticationFilter | ||
): DefaultSecurityFilterChain = | ||
http | ||
.csrf { it.disable() } | ||
.cors { it.disable() } | ||
.authorizeHttpRequests { | ||
it | ||
.requestMatchers(*userUnsecuredEndpoints).permitAll() | ||
.requestMatchers(*adminUnsecuredEndpoints).hasRole(AuthUserRole.ADMIN.name) | ||
.anyRequest().fullyAuthenticated() | ||
} | ||
.sessionManagement { session: SessionManagementConfigurer<HttpSecurity> -> | ||
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS) | ||
} | ||
.authenticationProvider(authenticationProvider) | ||
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter::class.java) | ||
.exceptionHandling { | ||
it.authenticationEntryPoint(authenticationExceptionHandler) | ||
} | ||
.logout { | ||
it.logoutUrl("/api/auth/logout") | ||
.addLogoutHandler(cookieClearingLogoutHandler) | ||
.logoutSuccessHandler(logoutSuccessHandler) | ||
.deleteCookies("access_token") | ||
.permitAll() | ||
} | ||
.build() | ||
|
||
private val authenticationExceptionHandler = | ||
{ _: HttpServletRequest, response: HttpServletResponse, authException: AuthenticationException -> | ||
response.contentType = MediaType.APPLICATION_JSON_VALUE | ||
response.status = HttpServletResponse.SC_UNAUTHORIZED | ||
objectMapper.writeValue(response.writer, ErrorDTO("${authException.message}")) | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
backend/src/main/kotlin/com/tul/backend/auth/base/dto/ErrorDTO.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.tul.backend.auth.base.dto | ||
|
||
data class ErrorDTO( | ||
val message: String, | ||
) |
19 changes: 19 additions & 0 deletions
19
backend/src/main/kotlin/com/tul/backend/auth/base/service/CustomPasswordEncoder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.tul.backend.auth.base.service | ||
|
||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder | ||
import org.springframework.security.crypto.password.PasswordEncoder | ||
import org.springframework.stereotype.Component | ||
|
||
@Component | ||
class CustomPasswordEncoder( | ||
private val encoder: BCryptPasswordEncoder = BCryptPasswordEncoder(), | ||
) : PasswordEncoder { | ||
|
||
override fun encode(rawPassword: CharSequence?): String { | ||
return encoder.encode(rawPassword) | ||
} | ||
|
||
override fun matches(rawPassword: CharSequence?, encodedPassword: String?): Boolean { | ||
return encoder.matches(rawPassword, encodedPassword) | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
backend/src/main/kotlin/com/tul/backend/auth/base/service/CustomUserDetailsService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.tul.backend.auth.base.service | ||
|
||
import com.tul.backend.auth.entity.AuthUser | ||
import com.tul.backend.auth.repository.AuthUserRepository | ||
import jakarta.transaction.Transactional | ||
import org.springframework.security.core.userdetails.User | ||
import org.springframework.security.core.userdetails.UserDetails | ||
import org.springframework.security.core.userdetails.UserDetailsService | ||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
@Transactional | ||
class CustomUserDetailsService( | ||
private val authUserRepository: AuthUserRepository | ||
) : UserDetailsService { | ||
override fun loadUserByUsername(email: String?): UserDetails { | ||
return authUserRepository.findByEmail(email!!) | ||
?.mapToUserDetails() | ||
?: throw Exception("User not found") | ||
} | ||
|
||
private fun AuthUser.mapToUserDetails(): UserDetails { | ||
return User.builder() | ||
.username(email.value) | ||
.password(password) | ||
.roles(this.role.name) | ||
.build() | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
backend/src/main/kotlin/com/tul/backend/auth/base/service/TokenFilterService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package com.tul.backend.auth.base.service | ||
|
||
import jakarta.servlet.http.HttpServletRequest | ||
import jakarta.servlet.http.HttpServletResponse | ||
import org.springframework.beans.factory.annotation.Qualifier | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken | ||
import org.springframework.security.core.context.SecurityContextHolder | ||
import org.springframework.security.core.userdetails.UserDetails | ||
import org.springframework.security.core.userdetails.UserDetailsService | ||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource | ||
import org.springframework.stereotype.Component | ||
|
||
@Component | ||
class TokenFilterService( | ||
@Qualifier("customUserDetailsService") private val userDetailsService: UserDetailsService, | ||
private val tokenService: TokenService | ||
) { | ||
|
||
fun validateRequest(request: HttpServletRequest): UserDetails? { | ||
val (email, token) = extractEmailAndToken(request) | ||
|
||
if (email != null && SecurityContextHolder.getContext().authentication == null) { | ||
val userDetails = userDetailsService.loadUserByUsername(email) | ||
if (tokenService.isValidToken(token, userDetails)) { | ||
return userDetails | ||
} | ||
} | ||
return null | ||
} | ||
|
||
fun updateContext( | ||
userDetails: UserDetails, | ||
request: HttpServletRequest, | ||
response: HttpServletResponse, | ||
) { | ||
val authToken = UsernamePasswordAuthenticationToken( | ||
userDetails, | ||
null, | ||
userDetails.authorities | ||
) | ||
authToken.details = WebAuthenticationDetailsSource().buildDetails(request) | ||
|
||
SecurityContextHolder.getContext().authentication = authToken | ||
} | ||
|
||
private fun extractEmailAndToken(request: HttpServletRequest): Pair<String?, String?> { | ||
val authHeader = request.getHeader("Cookie") | ||
var token: String? = null | ||
var email: String? = null | ||
|
||
if (authHeader != null && authHeader.startsWith("access_token=")) { | ||
token = authHeader.substring(13) | ||
email = tokenService.extractEmail(token) | ||
} | ||
return Pair(email, token) | ||
} | ||
} |
Oops, something went wrong.