Skip to content

Commit 65bbd80

Browse files
authored
Merge pull request #2511 from constantine2nd/develop
Check mandatory headers of Berlin Group
2 parents 50478e1 + 921fa75 commit 65bbd80

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,10 @@ default_auth_context_update_request_key=CUSTOMER_NUMBER
11201120
# Show the path inside of Berlin Group error message
11211121
#berlin_group_error_message_show_path = true
11221122

1123+
# Check presence of the mandatory headers
1124+
#berlin_group_mandatory_headers = X-Request-ID,PSU-IP-Address,PSU-Device-ID,PSU-Device-Name
1125+
#berlin_group_mandatory_header_consent = TPP-Redirect-URL
1126+
11231127
## Berlin Group Create Consent Frequency per Day Upper Limit
11241128
#berlin_group_frequency_per_day_upper_limit = 4
11251129

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3244,8 +3244,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
32443244
val verb = result._2.map(_.verb).getOrElse("None")
32453245
val body = result._2.flatMap(_.httpBody)
32463246
val reqHeaders = result._2.map(_.requestHeaders).getOrElse(Nil)
3247-
// Verify signed request (Berlin Group)
3248-
BerlinGroupSigning.verifySignedRequest(body, verb, url, reqHeaders, result)
3247+
// Berlin Group checks
3248+
BerlinGroupCheck.validate(body, verb, url, reqHeaders, result)
32493249
} map {
32503250
result =>
32513251
val excludeFunctions = getPropsValue("rate_limiting.exclude_endpoints", "root").split(",").toList
@@ -3300,8 +3300,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
33003300
val verb = result._2.map(_.verb).getOrElse("None")
33013301
val body = result._2.flatMap(_.httpBody)
33023302
val reqHeaders = result._2.map(_.requestHeaders).getOrElse(Nil)
3303-
// Verify signed request if need be
3304-
BerlinGroupSigning.verifySignedRequest(body, verb, url, reqHeaders, result)
3303+
// Berlin Group checks
3304+
BerlinGroupCheck.validate(body, verb, url, reqHeaders, result)
33053305
} map { result =>
33063306
result._1 match {
33073307
case Empty if result._2.flatMap(_.consumer).isDefined => // There is no error and Consumer is defined
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package code.api.util
2+
3+
import code.api.RequestHeader
4+
import com.openbankproject.commons.model.User
5+
import net.liftweb.common.{Box, Empty, Failure}
6+
import net.liftweb.http.provider.HTTPParam
7+
8+
object BerlinGroupCheck {
9+
10+
// Parse mandatory headers from a comma-separated string
11+
private val berlinGroupMandatoryHeaders: List[String] = APIUtil.getPropsValue("berlin_group_mandatory_headers", defaultValue = "X-Request-ID,PSU-IP-Address,PSU-Device-ID,PSU-Device-Name")
12+
.split(",")
13+
.map(_.trim.toLowerCase)
14+
.toList.filterNot(_.isEmpty)
15+
private val berlinGroupMandatoryHeaderConsent = APIUtil.getPropsValue("berlin_group_mandatory_header_consent", defaultValue = "TPP-Redirect-URL")
16+
.split(",")
17+
.map(_.trim.toLowerCase)
18+
.toList.filterNot(_.isEmpty)
19+
20+
private def validateHeaders(verb: String, url: String, reqHeaders: List[HTTPParam], forwardResult: (Box[User], Option[CallContext])): (Box[User], Option[CallContext]) = {
21+
val headerMap = reqHeaders.map(h => h.name.toLowerCase -> h).toMap
22+
val missingHeaders = if(url.contains("berlin-group") && url.endsWith("/consent"))
23+
berlinGroupMandatoryHeaders.filterNot(headerMap.contains)
24+
else
25+
(berlinGroupMandatoryHeaders ++ berlinGroupMandatoryHeaderConsent).filterNot(headerMap.contains)
26+
27+
if (missingHeaders.isEmpty) {
28+
forwardResult // All mandatory headers are present
29+
} else {
30+
(Failure(s"Missing mandatory headers: ${missingHeaders.mkString(", ")}"), forwardResult._2)
31+
}
32+
}
33+
34+
def validate(body: Box[String], verb: String, url: String, reqHeaders: List[HTTPParam], forwardResult: (Box[User], Option[CallContext])): (Box[User], Option[CallContext]) = {
35+
validateHeaders(verb, url, reqHeaders, forwardResult) match {
36+
case (user, _) if user.isDefined || user == Empty => // All good. Chain another check
37+
// Verify signed request (Berlin Group)
38+
BerlinGroupSigning.verifySignedRequest(body, verb, url, reqHeaders, forwardResult)
39+
case forwardError => // Forward error case
40+
forwardError
41+
}
42+
}
43+
44+
}

0 commit comments

Comments
 (0)