libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

auth.kt (2300B)


      1 /*
      2  * This file is part of LibEuFin.
      3  * Copyright (C) 2025 Taler Systems S.A.
      4 
      5  * LibEuFin is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU Affero General Public License as
      7  * published by the Free Software Foundation; either version 3, or
      8  * (at your option) any later version.
      9 
     10  * LibEuFin is distributed in the hope that it will be useful, but
     11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
     13  * Public License for more details.
     14 
     15  * You should have received a copy of the GNU Affero General Public
     16  * License along with LibEuFin; see the file COPYING.  If not, see
     17  * <http://www.gnu.org/licenses/>
     18  */
     19 
     20 package tech.libeufin.common.api
     21 
     22 import io.ktor.http.*
     23 import io.ktor.server.response.*
     24 import io.ktor.server.routing.*
     25 import tech.libeufin.common.*
     26 import tech.libeufin.common.api.intercept
     27 
     28 /** Apply authentication api configuration for a route */
     29 fun Route.apiAuth(auth: AuthMethod, callback: Route.() -> Unit): Route =
     30     intercept("Auth", callback) {
     31         if (auth != AuthMethod.None) {
     32             val header = this.request.headers[HttpHeaders.Authorization]
     33             val (expectedScheme, token) = when (auth) {
     34                 is AuthMethod.Basic -> "Basic" to auth.token
     35                 is AuthMethod.Bearer -> "Bearer" to auth.token
     36                 else -> throw UnsupportedOperationException()
     37             }
     38 
     39             if (header == null) {
     40                 this.response.header(HttpHeaders.WWWAuthenticate, expectedScheme)
     41                 throw unauthorized(
     42                     "Authorization header not found",
     43                     TalerErrorCode.GENERIC_PARAMETER_MISSING
     44                 )
     45             }
     46             val (scheme, content) = header.splitOnce(" ") ?: throw badRequest(
     47                 "Authorization is invalid",
     48                 TalerErrorCode.GENERIC_HTTP_HEADERS_MALFORMED
     49             )
     50             if (scheme == expectedScheme) {
     51                 if (content != token) {
     52                     throw unauthorized("Unknown token", TalerErrorCode.GENERIC_TOKEN_UNKNOWN)
     53                 }
     54             } else {
     55                 throw unauthorized("Expected scheme $expectedScheme got '$scheme'")
     56             }
     57         }
     58     }