Skip to content

Commit

Permalink
Authenticate against the database
Browse files Browse the repository at this point in the history
  • Loading branch information
bdmendes committed Nov 24, 2022
1 parent 5a0f2e2 commit a335f95
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ 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.oauth2.server.resource.OAuth2ResourceServerConfigurer
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.security.oauth2.jwt.JwtDecoder
import org.springframework.security.oauth2.jwt.JwtEncoder
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder
Expand Down Expand Up @@ -39,4 +41,9 @@ class AuthConfig(val rsaKeys: RSAKeyProperties) {
val jwt = RSAKey.Builder(rsaKeys::publicKey.get()).privateKey(rsaKeys::privateKey.get()).build()
return NimbusJwtEncoder(ImmutableJWKSet(JWKSet(jwt)))
}

@Bean
fun passwordEncoder(): PasswordEncoder {
return BCryptPasswordEncoder()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import pt.up.fe.ni.website.backend.service.AuthService
@RestController
@RequestMapping("/auth")
class AuthController(val authService: AuthService) {
@PostMapping
fun getToken(authentication: Authentication?): Map<String, String> {
@PostMapping("/new_token")
fun getNewToken(authentication: Authentication?): Map<String, String> {
if (authentication == null) {
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "No credentials were provided")
}
Expand Down
10 changes: 6 additions & 4 deletions src/main/kotlin/pt/up/fe/ni/website/backend/model/Account.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,18 @@ import pt.up.fe.ni.website.backend.model.constants.AccountConstants as Constants

@Entity
class Account(
@JsonProperty(required = true)
@field:Size(min = Constants.Name.minSize, max = Constants.Name.maxSize)
var name: String,

@JsonProperty(required = true)
@Column(unique = true)
@field:NotEmpty
@field:Email
var email: String,

@field:Size(min = Constants.Name.minSize, max = Constants.Name.maxSize)
var name: String,

@field:Size(min = Constants.Password.minSize, max = Constants.Password.maxSize)
var password: String,

@field:Size(min = Constants.Bio.minSize, max = Constants.Bio.maxSize)
var bio: String?,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ object AccountConstants {
const val minSize = 5
const val maxSize = 500
}

object Password {
const val minSize = 8
const val maxSize = 100
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import pt.up.fe.ni.website.backend.model.Account
import java.util.Date

class AccountDto(
val name: String,
val email: String,
val password: String,
val name: String?,
val bio: String?,
val birthDate: Date?,
val photoPath: String?,
val linkedin: String?,
val github: String?,
val websites: List<CustomWebsiteDto>
val websites: List<CustomWebsiteDto>?
) : Dto<Account>()
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package pt.up.fe.ni.website.backend.service

import org.springframework.data.repository.findByIdOrNull
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Service
import pt.up.fe.ni.website.backend.model.Account
import pt.up.fe.ni.website.backend.model.dto.AccountDto
import pt.up.fe.ni.website.backend.repository.AccountRepository

@Service
class AccountService(private val repository: AccountRepository) {
class AccountService(private val repository: AccountRepository, private val encoder: PasswordEncoder) {
fun getAllAccounts(): List<Account> = repository.findAll().toList()

fun createAccount(dto: AccountDto): Account {
Expand All @@ -16,9 +17,13 @@ class AccountService(private val repository: AccountRepository) {
}

val account = dto.create()
account.password = encoder.encode(dto.password)
return repository.save(account)
}

fun getAccountById(id: Long): Account = repository.findByIdOrNull(id)
?: throw NoSuchElementException("account not found with id $id")

fun getAccountByEmail(email: String): Account = repository.findByEmail(email)
?: throw NoSuchElementException("account not found with email $email")
}
15 changes: 11 additions & 4 deletions src/main/kotlin/pt/up/fe/ni/website/backend/service/AuthService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package pt.up.fe.ni.website.backend.service
import org.springframework.http.HttpStatus
import org.springframework.security.core.Authentication
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.security.oauth2.jwt.JwtClaimsSet
import org.springframework.security.oauth2.jwt.JwtEncoder
import org.springframework.security.oauth2.jwt.JwtEncoderParameters
Expand All @@ -13,16 +14,22 @@ import java.time.Period
import java.util.stream.Collectors

@Service
class AuthService(val encoder: JwtEncoder) {
class AuthService(
val accountService: AccountService,
val jwtEncoder: JwtEncoder,
private val passwordEncoder: PasswordEncoder
) {
fun authenticate(authentication: Authentication): String {
if (!okCredentials(authentication)) {
throw ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY, "Invalid credentials")
}
return generateToken(authentication)
}

// When accounts are ready, check against the database for the user
private fun okCredentials(authentication: Authentication) = true
private fun okCredentials(authentication: Authentication): Boolean {
val account = accountService.getAccountByEmail(authentication.name)
return passwordEncoder.matches(authentication.credentials.toString(), account.password)
}

private fun generateToken(authentication: Authentication): String {
val scope = authentication
Expand All @@ -39,6 +46,6 @@ class AuthService(val encoder: JwtEncoder) {
.subject(authentication.name)
.claim("scope", scope)
.build()
return encoder.encode(JwtEncoderParameters.from(claims)).tokenValue
return jwtEncoder.encode(JwtEncoderParameters.from(claims)).tokenValue
}
}

0 comments on commit a335f95

Please sign in to comment.