Skip to content

Commit

Permalink
1417: Add unique index constraint for tokenHash column
Browse files Browse the repository at this point in the history
  • Loading branch information
seluianova committed Oct 14, 2024
1 parent 7c3d071 commit c6896d1
Show file tree
Hide file tree
Showing 7 changed files with 16 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class AdministratorEntity(id: EntityID<Int>) : IntEntity(id) {
const val TOKEN_LENGTH = 60

object ApiTokens : IntIdTable() {
val token = binary("token")
val tokenHash = binary("tokenHash").uniqueIndex()
val creatorId = reference("creatorId", Administrators)
val projectId = reference("projectId", Projects)
val expirationDate = date("expirationDate")
Expand All @@ -68,7 +68,7 @@ object ApiTokens : IntIdTable() {
class ApiTokenEntity(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<ApiTokenEntity>(ApiTokens)

var token by ApiTokens.token
var tokenHash by ApiTokens.tokenHash
var creator by ApiTokens.creatorId
var projectId by ApiTokens.projectId
var expirationDate by ApiTokens.expirationDate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ import java.time.LocalDate

object ApiTokensRepository {
fun insert(
token: ByteArray,
tokenHash: ByteArray,
adminId: EntityID<Int>,
expirationDate: LocalDate,
projectId: EntityID<Int>
): ApiTokenEntity {
return ApiTokenEntity.new {
this.token = token
this.tokenHash = tokenHash
this.creator = adminId
this.expirationDate = expirationDate
this.projectId = projectId
}
}

fun findByToken(token: ByteArray): ApiTokenEntity? {
return ApiTokenEntity.find { (ApiTokens.token eq token) }.singleOrNull()
fun findByTokenHash(tokenHash: ByteArray): ApiTokenEntity? {
return ApiTokenEntity.find { (ApiTokens.tokenHash eq tokenHash) }.singleOrNull()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ class ApiTokenService {
SecureRandom().nextBytes(bytes)
val token = Base64.getEncoder().encodeToString(bytes)

val encryptedToken = PasswordCrypto.hashWithSHA256(token.toByteArray())
val tokenHash = PasswordCrypto.hashWithSHA256(token.toByteArray())
val expirationDate = LocalDate.now().plusMonths(expiresIn.toLong())

transaction {
ApiTokensRepository.insert(encryptedToken, admin.id, expirationDate, admin.projectId)
ApiTokensRepository.insert(tokenHash, admin.id, expirationDate, admin.projectId)
}

return token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ internal class V0020_AddApiTokenTable : Migration() {
"""
CREATE TABLE apitokens (
id SERIAL PRIMARY KEY ,
"token" BYTEA NOT NULL,
"tokenHash" BYTEA NOT NULL,
"creatorId" INTEGER NOT NULL,
"projectId" INTEGER NOT NULL,
"expirationDate" DATE NOT NULL
);
ALTER TABLE apitokens ADD CONSTRAINT fk_apitokens_creator__id FOREIGN KEY ("creatorId") REFERENCES administrators(id) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE apitokens ADD CONSTRAINT fk_apitokens_projectid__id FOREIGN KEY ("projectId") REFERENCES projects(id) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE ONLY apitokens ADD CONSTRAINT apitokens_tokenHash_unique UNIQUE ("tokenHash");
""".trimIndent()
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,10 @@ class UserImportHandler(
private fun authenticate(ctx: Context): ApiTokenEntity {
val authHeader = ctx.header("Authorization")?.takeIf { it.startsWith("Bearer ") }
?: throw UnauthorizedException()

val encryptedToken = PasswordCrypto.hashWithSHA256(authHeader.substring(7).toByteArray())
val tokenHash = PasswordCrypto.hashWithSHA256(authHeader.substring(7).toByteArray())

return transaction {
ApiTokensRepository.findByToken(encryptedToken)?.takeIf { it.expirationDate > LocalDate.now() }
ApiTokensRepository.findByTokenHash(tokenHash)?.takeIf { it.expirationDate > LocalDate.now() }
?: throw ForbiddenException()
}
}
Expand Down
2 changes: 1 addition & 1 deletion backend/src/main/resources/config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ projects:
administrationBaseUrl: https://koblenz.sozialpass.app
administrationName: Koblenz-Pass-Verwaltung
timezone: "Europe/Berlin"
selfServiceEnabled: false
selfServiceEnabled: true
smtp:
host: mail.sozialpass.app
port: 587
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ object TestData {
creatorId: Int,
expirationDate: LocalDate = LocalDate.now().plusYears(1)
): Int {
val encryptedToken = PasswordCrypto.hashWithSHA256(token.toByteArray())
val tokenHash = PasswordCrypto.hashWithSHA256(token.toByteArray())
return transaction {
val admin = AdministratorEntity.findById(creatorId) ?: throw Exception("Test admin $creatorId not found")
ApiTokens.insertAndGetId {
it[ApiTokens.token] = encryptedToken
it[ApiTokens.tokenHash] = tokenHash
it[ApiTokens.creatorId] = creatorId
it[ApiTokens.expirationDate] = expirationDate
it[projectId] = admin.projectId
Expand Down

0 comments on commit c6896d1

Please sign in to comment.