Skip to content

Commit

Permalink
login: validate user passwords
Browse files Browse the repository at this point in the history
  • Loading branch information
hex-agon committed Dec 28, 2023
1 parent 1d3eb6d commit 2387b42
Show file tree
Hide file tree
Showing 10 changed files with 32 additions and 14 deletions.
5 changes: 5 additions & 0 deletions login-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
<artifactId>service-discovery</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.password4j</groupId>
<artifactId>password4j</artifactId>
<version>${password4j.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-toml</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ package work.fking.pangya.login.auth
val NOOP_AUTHENTICATOR: Authenticator = Authenticator { _, _ -> InvalidCredentialsResult }

fun interface Authenticator {
fun authenticate(username: String, password: CharArray): AuthResult
fun authenticate(username: String, password: ByteArray): AuthResult
}

sealed interface AuthResult
data class SuccessResult(val userInfo: UserInfo) : AuthResult
data class ExceptionResult(val exception: Exception) : AuthResult
data object InvalidCredentialsResult : AuthResult
data object InvalidCredentialsResult : AuthResult
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package work.fking.pangya.login.auth

import com.password4j.Password
import work.fking.pangya.login.persistence.AccountRepository

class DatabaseAuthenticator(val repository: AccountRepository) : Authenticator {
class DatabaseAuthenticator(
private val repository: AccountRepository
) : Authenticator {

override fun authenticate(username: String, password: CharArray): AuthResult {
val userInfo = repository.loadUserInfo(username, password = ByteArray(0))
override fun authenticate(username: String, password: ByteArray): AuthResult {
val userInfo = repository.loadUserInfo(username) ?: return InvalidCredentialsResult

return userInfo?.let { SuccessResult(it) } ?: InvalidCredentialsResult
if (Password.check(password, userInfo.password).withBcrypt()) {
return SuccessResult(userInfo)
}
return InvalidCredentialsResult
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package work.fking.pangya.login.auth
@JvmRecord
data class UserInfo(
val uid: Int,
val password: ByteArray,
val username: String,
val nickname: String? = null,
val hasBaseCharacter: Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import work.fking.pangya.login.task.LoginTask
import work.fking.pangya.networking.crypt.PangCrypt
import work.fking.pangya.networking.crypt.PangCrypt.PangCryptException
import work.fking.pangya.networking.protocol.readPString
import work.fking.pangya.networking.protocol.readPStringCharArray
import work.fking.pangya.networking.protocol.readPStringBytes

private const val LOGIN_PACKET_ID = 0x1
private const val RECONNECT_PACKET_ID = 0xb
Expand Down Expand Up @@ -43,7 +43,7 @@ class LoginHandler(

private fun handleLogin(ctx: ChannelHandlerContext, buffer: ByteBuf) {
val username = buffer.readPString()
val passwordMd5 = buffer.readPStringCharArray()
val passwordMd5 = buffer.readPStringBytes()
val channel = ctx.channel()
LOGGER.debug("Queueing login request from {} for {}", channel.remoteAddress(), username)
loginServer.submitTask(LoginTask(loginServer, channel, cryptKey, username, passwordMd5))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,23 @@ class AccountRepository(private val dataSource: DataSource) {

private val query = """
SELECT a.uid AS uid,
a.password AS password,
a.username AS username,
a.nickname AS nickname,
EXISTS(SELECT 1 FROM player_character pc WHERE pc.account_uid = a.uid) AS hasbasecharacter
FROM account a
WHERE username = ?
""".trimIndent()

fun loadUserInfo(username: String, password: ByteArray): UserInfo? {
fun loadUserInfo(username: String): UserInfo? {
dataSource.connection.use { conn ->
conn.prepareStatement(query).use { stmt ->
stmt.setString(1, username)
stmt.executeQuery().use { rs ->
if (rs.next()) {
return UserInfo(
uid = rs.getInt("uid"),
password = rs.getBytes("password"),
username = rs.getString("username"),
nickname = rs.getString("nickname"),
hasBaseCharacter = rs.getBoolean("hasbasecharacter")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class LoginTask(
private val channel: Channel,
private val cryptKey: Int,
private val username: String,
private val password: CharArray
private val password: ByteArray
) : Runnable {

override fun run() {
Expand Down
3 changes: 3 additions & 0 deletions login-server/src/main/resources/psw4j.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
global.banner=false
hash.bcrypt.minor=b
hash.bcrypt.rounds=12
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ fun ByteBuf.readPString(): String {
return String(bytes, StandardCharsets.US_ASCII)
}

fun ByteBuf.readPStringCharArray(): CharArray {
fun ByteBuf.readPStringBytes(): ByteArray {
val size = readUnsignedShortLE()
val characters = CharArray(size)
val bytes = ByteArray(size)
for (i in 0 until size) {
characters[i] = readByte().toInt().toChar()
bytes[i] = readByte()
}
return characters
return bytes
}

fun ByteBuf.readFixedSizeString(size: Int): String {
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<maven.compiler.release>21</maven.compiler.release>
<kotlin.compiler.jvmTarget>21</kotlin.compiler.jvmTarget>
<kotlin.version>1.9.20</kotlin.version>
<password4j.version>1.7.3</password4j.version>
<flyway.version>9.21.1</flyway.version>
<jooq.version>3.18.5</jooq.version>
<hikari.version>5.0.1</hikari.version>
Expand Down

0 comments on commit 2387b42

Please sign in to comment.