Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -664,19 +664,22 @@ where the consent was directly managed between ASPSP and PSU e.g. in a re-direct
"lastActionDate": "2019-06-30",
"consentStatus": "received"
}"""),
List(UserNotLoggedIn, UnknownError),
List(UserNotLoggedIn, ConsentNotFound, UnknownError),
ApiTag("Account Information Service (AIS)") :: apiTagBerlinGroupM :: Nil
)

lazy val getConsentInformation : OBPEndpoint = {
case "consents" :: consentId :: Nil JsonGet _ => {
cc =>
for {
(Full(u), callContext) <- authenticatedAccess(cc)
(_, callContext) <- applicationAccess(cc)
_ <- passesPsd2Aisp(callContext)
consent <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map {
unboxFullOrFail(_, callContext, s"$ConsentNotFound ($consentId)")
}
}
_ <- Helper.booleanToFuture(failMsg = s"${consent.mConsumerId.get} != ${cc.consumer.map(_.consumerId.get).getOrElse("None")}", failCode = 404, cc = cc.callContext) {
consent.mConsumerId.get == callContext.map(_.consumer.map(_.consumerId.get).getOrElse("None")).getOrElse("None")
}
} yield {
(createGetConsentResponseJson(consent), HttpCode.`200`(callContext))
}
Expand Down
4 changes: 3 additions & 1 deletion obp-api/src/main/scala/code/api/constant/constant.scala
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ object RequestHeader {
final lazy val `Consent-JWT` = "Consent-JWT"
final lazy val `PSD2-CERT` = "PSD2-CERT"
final lazy val `If-None-Match` = "If-None-Match"
final lazy val `TPP-Redirect-URL` = "TPP-Redirect-URL"
final lazy val `TPP-Redirect-URL` = "TPP-Redirect-URL" // Berlin Group
final lazy val `TPP-Signature-Certificate` = "TPP-Signature-Certificate" // Berlin Group
final lazy val `X-Request-ID` = "X-Request-ID" // Berlin Group
/**
* The If-Modified-Since request HTTP header makes the request conditional:
* the server sends back the requested resource, with a 200 status,
Expand Down
15 changes: 14 additions & 1 deletion obp-api/src/main/scala/code/api/util/APIUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,16 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
case _ => None
}
}
/**
* Purpose of this helper function is to get the PSD2-CERT value from a Request Headers.
* @return the PSD2-CERT value from a Request Header as a String
*/
def getTppSignatureCertificate(requestHeaders: List[HTTPParam]): Option[String] = {
requestHeaders.toSet.filter(_.name == RequestHeader.`TPP-Signature-Certificate`).toList match {
case x :: Nil => Some(x.values.mkString(", "))
case _ => None
}
}

def getRequestHeader(name: String, requestHeaders: List[HTTPParam]): String = {
requestHeaders.toSet.filter(_.name.toLowerCase == name.toLowerCase).toList match {
Expand Down Expand Up @@ -2983,6 +2993,9 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{

val authHeaders = AuthorisationUtil.getAuthorisationHeaders(reqHeaders)

// Identify consumer via certificate
val consumerByCertificate = Consent.getCurrentConsumerViaMtls(callContext = cc)

val res =
if (authHeaders.size > 1) { // Check Authorization Headers ambiguity
Future { (Failure(ErrorMessages.AuthorizationHeaderAmbiguity + s"${authHeaders}"), None) }
Expand Down Expand Up @@ -3109,7 +3122,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
// - Authorization: Basic mF_9.B5f-4.1JqM
Future { (Failure(ErrorMessages.InvalidAuthorizationHeader), Some(cc)) }
} else {
Future { (Empty, Some(cc)) }
Future { (Empty, Some(cc.copy(consumer = consumerByCertificate))) }
}
}

Expand Down
7 changes: 4 additions & 3 deletions obp-api/src/main/scala/code/api/util/ConsentUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,10 @@ object Consent extends MdcLoggable {
* @return the boxed Consumer
*/
def getCurrentConsumerViaMtls(callContext: CallContext): Box[Consumer] = {
val clientCert: String = APIUtil.`getPSD2-CERT`(callContext.requestHeaders)
.getOrElse(SecureRandomUtil.csprng.nextLong().toString)

val clientCert: String = APIUtil.`getPSD2-CERT`(callContext.requestHeaders) // MTLS certificate QWAC (Qualified Website Authentication Certificate)
.orElse(APIUtil.getTppSignatureCertificate(callContext.requestHeaders)) // Signature certificate QSealC (Qualified Electronic Seal Certificate)
.getOrElse(SecureRandomUtil.csprng.nextLong().toString) // Force to fail

{ // 1st search is via the original value
logger.debug(s"getConsumerByPemCertificate ${clientCert}")
Consumers.consumers.vend.getConsumerByPemCertificate(clientCert)
Expand Down