Skip to content

Commit

Permalink
Many Auth, permission things
Browse files Browse the repository at this point in the history
  • Loading branch information
MichiBaum committed Oct 15, 2024
1 parent f00e57c commit 7c0c9d0
Show file tree
Hide file tree
Showing 30 changed files with 203 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import com.michibaum.usermanagement_library.LoginDto
import com.michibaum.authentication_library.PublicKeyDto
import com.michibaum.usermanagement_library.UserDetailsDto
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Lazy
import org.springframework.http.HttpStatus
Expand All @@ -24,12 +25,10 @@ class AuthenticationController (
@PostMapping(value = ["/api/authenticate"])
fun authenticate(@RequestBody authenticationDto: AuthenticationDto): ResponseEntity<AuthenticationResponse> {
val loginDto = LoginDto(authenticationDto.username, authenticationDto.password)
val passwordCorrect: Boolean = usermanagementClient.checkPassword(loginDto)
val userDetailsDto: UserDetailsDto = usermanagementClient.checkUserDetails(loginDto)
?: return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()

if (!passwordCorrect)
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()

val jws = authenticationService.generateJWS(loginDto.username)!!
val jws = authenticationService.generateJWS(userDetailsDto)!!
val responseBody = AuthenticationResponse(authenticationDto.username, jws)
return ResponseEntity.ok(responseBody)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.michibaum.authentication_service.authentication
import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import com.michibaum.authentication_library.PublicKeyDto
import com.michibaum.usermanagement_library.UserDetailsDto
import org.springframework.stereotype.Service
import java.security.KeyPair
import java.security.interfaces.RSAPrivateKey
Expand All @@ -21,13 +22,15 @@ class AuthenticationService (
keyPair.public.encoded
)

fun generateJWS(username: String): String? {
fun generateJWS(userDetails: UserDetailsDto): String? {
return JWT.create()
.withHeader(jwsHeaders())
.withIssuer("authentication-service")
.withSubject(username)
.withSubject(userDetails.username)
.withExpiresAt(Instant.now().plusSeconds(60*60*8))
.withIssuedAt(Instant.now())
.withClaim("userId", userDetails.id)
.withArrayClaim("permissions", userDetails.permissions.toTypedArray())
.sign(algorithm)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package com.michibaum.authentication_service.authentication

import com.michibaum.usermanagement_library.UserDetailsDto
import com.michibaum.usermanagement_library.UsermanagementClient
import io.mockk.every
import io.mockk.mockk
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.junit.jupiter.MockitoExtension
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus

@ExtendWith(MockitoExtension::class)
Expand All @@ -26,7 +24,12 @@ class AuthenticationControllerUT {
@Test
fun `Authentication successful`(){
// GIVEN
every { usermanagementClient.checkPassword(any()) } returns true
val userDetailsDto = UserDetailsDto(
id = "ubdf-sdfg-sdfv-sdfv",
username = "UName",
permissions = emptySet()
)
every { usermanagementClient.checkUserDetails(any()) } returns userDetailsDto

val jws = "1234qwer"
val authenticationDto = AuthenticationDto("UName", "Passwört")
Expand All @@ -44,7 +47,12 @@ class AuthenticationControllerUT {
@Test
fun `Bad credentials`(){
// GIVEN
every { usermanagementClient.checkPassword(any()) } returns false
val userDetailsDto = UserDetailsDto(
id = "ubdf-sdfg-sdfv-sdfv",
username = "UName",
permissions = emptySet()
)
every { usermanagementClient.checkUserDetails(any()) } returns userDetailsDto
val authenticationDto = AuthenticationDto("UName", "Passwört")

// WHEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ class Game(
val gameType: GameType,

@ManyToMany(fetch = FetchType.LAZY, targetEntity = Account::class)
@JoinTable(name = "ACCOUNT_GAME_MAPPING", joinColumns = [JoinColumn(name = "game_id")],
inverseJoinColumns = [JoinColumn(name = "account_id")])
@JoinTable(name = "ACCOUNT_GAME_MAPPING", joinColumns = [JoinColumn(name = "game_id")], inverseJoinColumns = [JoinColumn(name = "account_id")])
val accounts: Set<Account>,

@OneToMany(mappedBy="game", fetch = FetchType.EAGER, targetEntity = Player::class, cascade = [CascadeType.ALL])
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
package com.michibaum.gatewayservice

import com.michibaum.permission_library.PermissionUtil
import org.slf4j.LoggerFactory
import org.springframework.cloud.gateway.filter.GatewayFilter
import org.springframework.cloud.gateway.filter.GatewayFilterChain
import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono

class AuthorizationPreFilter() : GatewayFilter {

private val logger = LoggerFactory.getLogger(AuthorizationPreFilter::class.java)
private lateinit var permissions: List<PermissionUtil>
private lateinit var permissions: List<String>

constructor(vararg permissions: PermissionUtil) : this() {
constructor(vararg permissions: String) : this() {
this.permissions = permissions.asList()
}

override fun filter(exchange: ServerWebExchange?, chain: GatewayFilterChain?): Mono<Void> {
exchange?.let {
permissions[0].toPermissionString()
permissions[0]
}
chain?.let {

Expand Down
7 changes: 7 additions & 0 deletions permission-library/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
</properties>

<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

</dependencies>

<build>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,32 +1,18 @@
package com.michibaum.permission_library

enum class Permissions: PermissionUtil { // TODO write this better
enum class Permissions {

ADMIN_SERVICE { override fun toPermissionString(): String = createPermissionString(this) },
REGISTRY_SERVICE { override fun toPermissionString(): String = createPermissionString(this) },
AUTHENTICATION_SERVICE { override fun toPermissionString(): String = createPermissionString(this) },
USERMANAGEMENT_SERVICE { override fun toPermissionString(): String = createPermissionString(this) };
ADMIN_SERVICE,

enum class AdminService: PermissionUtil {
CAN_SEND_REQUEST { override fun toPermissionString(): String = createPermissionString(this) },
EVERYTHING { override fun toPermissionString(): String = createPermissionString(this) }
}
REGISTRY_SERVICE,

enum class RegistryService: PermissionUtil {
CAN_SEND_REQUEST { override fun toPermissionString(): String = createPermissionString(this) },
EVERYTHING { override fun toPermissionString(): String = createPermissionString(this) }
}
AUTHENTICATION_SERVICE,

enum class AuthenticationService: PermissionUtil {
REFRESH_AUTH { override fun toPermissionString(): String = createPermissionString(this) }
}
USERMANAGEMENT_SERVICE,
USERMANAGEMENT_SERVICE_EDIT_OWN_USER,
SERMANAGEMENT_SERVICE_EDIT_ALL_USER,

enum class UsermanagementService: PermissionUtil {
EDIT_OWN_USER { override fun toPermissionString(): String = createPermissionString(this) },
EDIT_ALL_USER { override fun toPermissionString(): String = createPermissionString(this) }
}
JAVADOC_SERVICE,

enum class JavaDocService: PermissionUtil {
CAN_READ { override fun toPermissionString(): String = createPermissionString(this) }
}
CHESS_SERVICE;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.michibaum.usermanagement_library

data class UserDetailsDto(
val id: String,
val username: String,
val permissions: Set<String>
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import org.springframework.web.bind.annotation.RequestBody

interface UserManagementEndpoints {

@PostMapping(value = ["/checkPassword"])
fun checkPassword(@RequestBody loginDto: LoginDto): Boolean
@PostMapping(value = ["/checkUserDetails"])
fun checkUserDetails(@RequestBody loginDto: LoginDto): UserDetailsDto?

}
5 changes: 5 additions & 0 deletions usermanagement-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@
<artifactId>usermanagement-library</artifactId>
<version>1.0.0-TEST-9</version>
</dependency>
<dependency>
<groupId>com.michibaum</groupId>
<artifactId>permission-library</artifactId>
<version>1.0.0-TEST-9</version>
</dependency>

<dependency>
<groupId>com.michibaum</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.michibaum.usermanagement_service

import jakarta.persistence.*

@Entity
class Permission(
@Id
@Column(nullable = false, unique = true)
val permission: String,

@ManyToMany(fetch = FetchType.LAZY, targetEntity = User::class)
@JoinTable(name = "USER_PERMISSION_MAPPING", joinColumns = [JoinColumn(name = "permission_id")], inverseJoinColumns = [JoinColumn(name = "user_id")])
val users: Set<User>
)
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package com.michibaum.usermanagement_service

import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.*
import jakarta.persistence.FetchType.EAGER
import org.hibernate.annotations.UuidGenerator
import java.util.*

Expand All @@ -17,6 +16,10 @@ class User (
@Column(nullable = false)
val password: String,

@ManyToMany(fetch = EAGER, targetEntity = Permission::class)
@JoinTable(name = "USER_PERMISSION_MAPPING", joinColumns = [JoinColumn(name = "user_id")], inverseJoinColumns = [JoinColumn(name = "permission_id")])
val permissions: Set<Permission>,

@Id
@UuidGenerator
val id: UUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package com.michibaum.usermanagement_service

import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
import java.util.*

@Repository
interface UserRepository : JpaRepository<User, String> {

fun findByUsername(username: String): Optional<User>
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ class UserService(

private fun findUserById(id: String) = userRepository.findById(id).orElseNull()

fun findByUsername(username: String): User? {
return userRepository.findByUsername(username).orElseNull()
}

fun checkPassword(dtoPassword: String, passwordHash: String): Boolean {
return passwordEncoder.matches(dtoPassword, passwordHash)
}

}

private fun <T> Optional<T>.orElseNull(): T? = this.orElse(null)
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.michibaum.usermanagement_service
import org.springframework.web.bind.annotation.RestController
import com.michibaum.usermanagement_library.UserManagementEndpoints
import com.michibaum.usermanagement_library.LoginDto
import com.michibaum.usermanagement_library.UserDetailsDto
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
Expand All @@ -14,8 +15,16 @@ class UsermanagementController (
private val userService: UserService
) : UserManagementEndpoints {

override fun checkPassword(loginDto: LoginDto): Boolean {
return true
override fun checkUserDetails(loginDto: LoginDto): UserDetailsDto? {
val user = userService.findByUsername(loginDto.username) ?: return null
val matching = userService.checkPassword(loginDto.password, user.password)
if (!matching) return null

return UserDetailsDto(
id = user.id.toString(),
username = user.username,
permissions = user.permissions.map { it.permission }.toSet()
)
}

@GetMapping("/user/{id}")
Expand Down
10 changes: 10 additions & 0 deletions website/package-lock.json

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

1 change: 1 addition & 0 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@ngx-translate/core": "^15.0.0",
"@ngx-translate/http-loader": "^8.0.0",
"jwt-decode": "^4.0.0",
"ngx-cookie-service": "^18.0.0",
"primeflex": "^3.3.1",
"primeicons": "^7.0.0",
Expand Down
16 changes: 16 additions & 0 deletions website/src/app/core/config/permissions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export enum Permissions {
ADMIN_SERVICE,
ADMIN_SERVICE_CAN_SEND_REQUEST,

REGISTRY_SERVICE,

AUTHENTICATION_SERVICE,

USERMANAGEMENT_SERVICE,
USERMANAGEMENT_SERVICE_EDIT_OWN_USER,
SERMANAGEMENT_SERVICE_EDIT_ALL_USER,

JAVADOC_SERVICE,

CHESS_SERVICE
}
Loading

0 comments on commit 7c0c9d0

Please sign in to comment.