commit e0f1d57d1a46772437952a4224537b698ba324df
parent 9e9cfb04e56f23b9dac2a782fd8951151fd1e6ad
Author: Antoine A <>
Date: Tue, 21 Nov 2023 04:40:57 +0000
Basic auth challenge
Diffstat:
4 files changed, 18 insertions(+), 19 deletions(-)
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Authentication.kt b/bank/src/main/kotlin/tech/libeufin/bank/Authentication.kt
@@ -21,6 +21,7 @@ package tech.libeufin.bank
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.routing.Route
+import io.ktor.server.response.header
import io.ktor.util.AttributeKey
import io.ktor.util.pipeline.PipelineContext
import java.time.Instant
@@ -84,10 +85,16 @@ val ApplicationCall.isAdmin: Boolean get() = attributes.getOrNull(AUTH_IS_ADMIN)
*/
private suspend fun ApplicationCall.authenticateBankRequest(db: Database, requiredScope: TokenScope): String? {
// Extracting the Authorization header.
- val header = getAuthorizationRawHeader(this.request) ?: throw badRequest(
- "Authorization header not found.",
- TalerErrorCode.GENERIC_HTTP_HEADERS_MALFORMED
- )
+ val header = getAuthorizationRawHeader(this.request)
+ if (header == null) {
+ // Basic auth challenge
+ response.header(HttpHeaders.WWWAuthenticate, "Basic")
+ throw unauthorized(
+ "Authorization header not found.",
+ TalerErrorCode.GENERIC_PARAMETER_MISSING
+ )
+ }
+
val authDetails = getAuthorizationDetails(header) ?: throw badRequest(
"Authorization is invalid.",
TalerErrorCode.GENERIC_HTTP_HEADERS_MALFORMED
@@ -95,7 +102,7 @@ private suspend fun ApplicationCall.authenticateBankRequest(db: Database, requir
return when (authDetails.scheme) {
"Basic" -> doBasicAuth(db, authDetails.content)
"Bearer" -> doTokenAuth(db, authDetails.content, requiredScope)
- else -> throw unauthorized("Authorization method wrong or not supported.") // TODO basic auth challenge
+ else -> throw unauthorized("Authorization method wrong or not supported.")
}
}
@@ -134,7 +141,7 @@ private suspend fun doBasicAuth(db: Database, encodedCredentials: String): Strin
TalerErrorCode.GENERIC_HTTP_HEADERS_MALFORMED
)
val (login, plainPassword) = userAndPassSplit
- val passwordHash = db.account.passwordHash(login) ?: throw unauthorized()
+ val passwordHash = db.account.passwordHash(login) ?: throw unauthorized("Bad password")
if (!CryptoUtil.checkpw(plainPassword, passwordHash)) return null
return login
}
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Error.kt b/bank/src/main/kotlin/tech/libeufin/bank/Error.kt
@@ -63,8 +63,10 @@ fun forbidden(
error: TalerErrorCode = TalerErrorCode.END
): LibeufinBankException = libeufinError(HttpStatusCode.Forbidden, hint, error)
-fun unauthorized(hint: String? = "Login failed"): LibeufinBankException
- = libeufinError(HttpStatusCode.Unauthorized, hint, TalerErrorCode.GENERIC_UNAUTHORIZED)
+fun unauthorized(
+ hint: String,
+ error: TalerErrorCode = TalerErrorCode.GENERIC_UNAUTHORIZED
+): LibeufinBankException = libeufinError(HttpStatusCode.Unauthorized, hint, error)
fun internalServerError(hint: String?): LibeufinBankException
= libeufinError(HttpStatusCode.InternalServerError, hint, TalerErrorCode.GENERIC_INTERNAL_INVARIANT_FAILURE)
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
@@ -180,17 +180,8 @@ fun Application.corebankWebApp(db: Database, ctx: BankConfig) {
)
)
}
- /**
- * This branch triggers when a bank handler throws it, and namely
- * after one logical failure of the request(-handling). This branch
- * should be preferred to catch errors, as it allows to include the
- * Taler specific error detail.
- */
exception<LibeufinBankException> { call, cause ->
logger.error(cause.talerError.hint)
- // Stacktrace if bank's fault
- if (cause.httpStatus.toString().startsWith('5'))
- cause.printStackTrace()
call.respond(
status = cause.httpStatus,
message = cause.talerError
diff --git a/util/src/main/kotlin/HTTP.kt b/util/src/main/kotlin/HTTP.kt
@@ -54,8 +54,7 @@ fun ApplicationCall.maybeUriComponent(name: String): String? {
// Extracts the Authorization:-header line, or returns null if not found.
fun getAuthorizationRawHeader(request: ApplicationRequest): String? {
- val authorization = request.headers["Authorization"]
- return authorization ?: run {
+ return request.headers["Authorization"] ?: run {
logger.error("Authorization header not found")
return null
}