Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 3 additions & 33 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,33 +1,3 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/
ordering/src/main/resources/application.properties
authentication/src/main/resources/application.properties
src/main/resources/application.properties
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions .idea/kotlinc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions authentication/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.coded.spring</groupId>
<artifactId>Barrak</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>

<artifactId>authentication</artifactId>


</project>
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.coded.spring.ordering
package authentication

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class Application
class AuthenticationApplication

fun main(args: Array<String>) {
runApplication<Application>(*args)
}
runApplication<AuthenticationApplication>(*args)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package authentication

import RegistrationRequestDTO
import authentication.jwt.JwtService
import authentication.users.UsersService
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.http.ResponseEntity
import org.springframework.security.authentication.*
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.web.bind.annotation.*
import java.security.Principal

@Tag(name = "AuthenticationAPI")
@RestController
@RequestMapping("/authentication")
class AuthController(
private val authenticationManager: AuthenticationManager,
private val userDetailsService: UserDetailsService,
private val jwtService: JwtService,
private val usersService: UsersService
) {

// login page
@PostMapping("/login")
fun login(@RequestBody authRequest: AuthRequest): AuthResponse {

// create a spring security authentication using the username and password from the request
val authToken = UsernamePasswordAuthenticationToken(authRequest.username, authRequest.password)
// then the credentials will be authenticated by authentication manager
val authentication = authenticationManager.authenticate(authToken)

// check if authentication is successful
if (authentication.isAuthenticated) {

// load the user details from the userDetailsService
val userDetails = userDetailsService.loadUserByUsername(authRequest.username)
// Uses a JWT (JSON Web Token) service to generate a token for the authenticated user.
val token = jwtService.generateToken(userDetails.username)
// Returns a response object containing the JWT token
return AuthResponse(token)
} else {
throw UsernameNotFoundException("Invalid user request!")
}
}

// register
@PostMapping("/register")
fun addUser(@RequestBody request: RegistrationRequestDTO) {
usersService.registerUsers(request)
ResponseEntity.ok()
}


// check the token
@PostMapping("/check-token")
fun checkToken(
principal: Principal
): CheckTokenResponse {
return CheckTokenResponse(
userId = usersService.findByUsername(principal.name)
)
}

}

data class CheckTokenResponse(
val userId: Long
)

data class AuthRequest(
val username: String,
val password: String
)

data class AuthResponse(
val token: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package authentication

import authentication.users.UserEntity
import authentication.users.UsersRepository
import jakarta.inject.Named
import org.springframework.security.core.userdetails.User
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.stereotype.Service


@Service
class CustomUserDetailsClass(
private val usersRepository: UsersRepository
): UserDetailsService{

override fun loadUserByUsername(username: String): UserDetails {
val user: UserEntity = usersRepository.findByUsername(username)
?: throw UsernameNotFoundException("User Not Found")

return User.builder()
.username(user.username)
.password(user.password)
// .roles(user.role.toString())
.build()
}
}
40 changes: 40 additions & 0 deletions authentication/src/main/kotlin/authentication/LoggingFilter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package authentication

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
import org.springframework.web.util.ContentCachingRequestWrapper
import org.springframework.web.util.ContentCachingResponseWrapper


@Component
class LoggingFilter: OncePerRequestFilter() {
override fun doFilterInternal(
request: HttpServletRequest,
response: HttpServletResponse,
filterChain: FilterChain
) {

val cachedRequest = ContentCachingRequestWrapper(request)
val cachedResponse = ContentCachingResponseWrapper(response)

filterChain.doFilter(cachedRequest, cachedResponse)

logRequest(cachedRequest)
logResponse(cachedResponse)
cachedResponse.copyBodyToResponse()
}

private fun logRequest(request: ContentCachingRequestWrapper){
val requestBody = String(request.contentAsByteArray)
logger.info("Request: method=${request.method}, uri=${request.requestURI}, body=$requestBody")
}

private fun logResponse(response: ContentCachingResponseWrapper) {
val responseBody = String(response.contentAsByteArray)
logger.info("Response: status=${response.status}, body=$responseBody")
}

}
65 changes: 65 additions & 0 deletions authentication/src/main/kotlin/authentication/SecurityConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package authentication

import authentication.jwt.JwtAuthFilter
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.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter

@Configuration
@EnableWebSecurity
class SecurityConfig(
private val jwtAuthFilter: JwtAuthFilter,
private val userDetailsService: UserDetailsService
) {

@Bean
fun passwordEncoder(): PasswordEncoder = BCryptPasswordEncoder()

@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http.csrf { it.disable() }
.authorizeHttpRequests {
it
.requestMatchers("/authentication/**").permitAll()
.requestMatchers("/authentication/login").permitAll()
.requestMatchers("/hello").permitAll()
.requestMatchers("/authentication/check-token").authenticated()
// swagger
.requestMatchers("/api-docs").permitAll()
// registration endpoint

// rest of endpoints will need authentication
.anyRequest().authenticated()
}
.sessionManagement {
it.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
}
.authenticationProvider(authenticationProvider())
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter::class.java)

return http.build();
}

@Bean
fun authenticationManager(config: AuthenticationConfiguration): AuthenticationManager =
config.authenticationManager

@Bean
fun authenticationProvider(): AuthenticationProvider {
val provider = DaoAuthenticationProvider()
provider.setUserDetailsService(userDetailsService)
provider.setPasswordEncoder(passwordEncoder())
return provider
}
}
Loading