Skip to content

Commit da2b420

Browse files
authored
Merge pull request #2506 from constantine2nd/develop
TPP Signature Certificate
2 parents 1f8e5bc + f75c6e6 commit da2b420

File tree

3 files changed

+18
-7
lines changed

3 files changed

+18
-7
lines changed

obp-api/src/main/resources/props/sample.props.template

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ jwt.use.ssl=false
162162
# truststore.path.tpp_signature = path/to/ca.p12
163163
# truststore.password.tpp_signature = truststore-password
164164

165+
# Bypass TPP signature validation
166+
# bypass_tpp_signature_validation = false
167+
165168

166169
## Enable writing API metrics (which APIs are called) to RDBMS
167170
write_metrics=true

obp-api/src/main/scala/code/api/util/BerlinGroupSigning.scala

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
package code.api.util
22

3-
import code.api.{CertificateConstants, RequestHeader}
3+
import code.api.RequestHeader
44
import code.util.Helper.MdcLoggable
55
import com.openbankproject.commons.model.User
66
import net.liftweb.common.{Box, Failure, Full}
77
import net.liftweb.http.provider.HTTPParam
88

9-
import java.util.Base64
109
import java.nio.charset.StandardCharsets
1110
import java.nio.file.{Files, Paths}
1211
import java.security._
@@ -113,7 +112,7 @@ object BerlinGroupSigning extends MdcLoggable {
113112
* @param forwardResult Propagated result of calling function
114113
* @return Propagated result of calling function or signing request error
115114
*/
116-
def verifySignedRequest(body: Box[String], verb: String, url: String, reqHeaders: List[HTTPParam], forwardResult: (Box[User], Option[CallContext])) = {
115+
def verifySignedRequest(body: Box[String], verb: String, url: String, reqHeaders: List[HTTPParam], forwardResult: (Box[User], Option[CallContext])): (Box[User], Option[CallContext]) = {
117116
def checkRequestIsSigned(requestHeaders: List[HTTPParam]): Boolean = {
118117
requestHeaders.exists(_.name == RequestHeader.`TPP-Signature-Certificate`) &&
119118
requestHeaders.exists(_.name == RequestHeader.Signature) &&
@@ -132,8 +131,8 @@ object BerlinGroupSigning extends MdcLoggable {
132131

133132
val signatureHeaderValue = getHeaderValue(RequestHeader.Signature, requestHeaders)
134133
val signature = parseSignatureHeader(signatureHeaderValue).getOrElse("signature", "NONE")
135-
val headersss = parseSignatureHeader(signatureHeaderValue).getOrElse("headers", "").split(" ").toList
136-
val headers = headersss.map(h =>
134+
val headersToSign = parseSignatureHeader(signatureHeaderValue).getOrElse("headers", "").split(" ").toList
135+
val headers = headersToSign.map(h =>
137136
if(h.toLowerCase() == RequestHeader.Digest.toLowerCase()) {
138137
s"$h: SHA-256=$digest"
139138
} else {
@@ -143,8 +142,10 @@ object BerlinGroupSigning extends MdcLoggable {
143142
val signingString = headers.mkString("\n")
144143
val isVerified = verifySignature(signingString, signature, certificatePem)
145144
val isValidated = CertificateVerifier.validateCertificate(certificatePem)
145+
val bypassValidation = APIUtil.getPropsAsBoolValue("bypass_tpp_signature_validation", defaultValue = false)
146146
(isVerified, isValidated) match {
147147
case (true, true) => forwardResult
148+
case (true, false) if bypassValidation => forwardResult
148149
case (true, false) => (Failure(ErrorMessages.X509PublicKeyCannotBeValidated), forwardResult._2)
149150
case (false, _) => (Failure(ErrorMessages.X509PublicKeyCannotVerify), forwardResult._2)
150151
}
@@ -157,7 +158,7 @@ object BerlinGroupSigning extends MdcLoggable {
157158
def getHeaderValue(name: String, requestHeaders: List[HTTPParam]): String = {
158159
requestHeaders.find(_.name.toLowerCase() == name.toLowerCase()).map(_.values.mkString).getOrElse("None")
159160
}
160-
def getPem(requestHeaders: List[HTTPParam]): String = {
161+
private def getPem(requestHeaders: List[HTTPParam]): String = {
161162
val certificate = getHeaderValue(RequestHeader.`TPP-Signature-Certificate`, requestHeaders)
162163
// Decode the Base64 string
163164
val decodedBytes = Base64.getDecoder.decode(certificate)
@@ -184,6 +185,13 @@ object BerlinGroupSigning extends MdcLoggable {
184185
}
185186
}
186187

188+
def getTppSignatureCertificate(requestHeaders: List[HTTPParam]): Option[String] = {
189+
getPem(requestHeaders) match {
190+
case value if value.isEmpty => None
191+
case value => Some(value)
192+
}
193+
}
194+
187195
def parseSignatureHeader(signatureHeader: String): Map[String, String] = {
188196
val regex = new Regex("""(\w+)\s*=\s*"([^"]*)"""", "key", "value")
189197
regex.findAllMatchIn(signatureHeader).map(m => m.group("key") -> m.group("value")).toMap

obp-api/src/main/scala/code/api/util/ConsentUtil.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ object Consent extends MdcLoggable {
131131
*/
132132
def getCurrentConsumerViaMtls(callContext: CallContext): Box[Consumer] = {
133133
val clientCert: String = APIUtil.`getPSD2-CERT`(callContext.requestHeaders) // MTLS certificate QWAC (Qualified Website Authentication Certificate)
134-
.orElse(APIUtil.getTppSignatureCertificate(callContext.requestHeaders)) // Signature certificate QSealC (Qualified Electronic Seal Certificate)
134+
.orElse(BerlinGroupSigning.getTppSignatureCertificate(callContext.requestHeaders)) // Signature certificate QSealC (Qualified Electronic Seal Certificate)
135135
.getOrElse(SecureRandomUtil.csprng.nextLong().toString) // Force to fail
136136

137137
{ // 1st search is via the original value

0 commit comments

Comments
 (0)