mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 19:16:53 +00:00
feature/Tweak OBP Consent Flow; Request Header
This commit is contained in:
parent
ef77829695
commit
a6cd0090f9
@ -2759,7 +2759,13 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
if (APIUtil.`hasConsent-ID`(reqHeaders)) { // Berlin Group's Consent
|
||||
Consent.applyBerlinGroupRules(APIUtil.`getConsent-ID`(reqHeaders), cc)
|
||||
} else if (APIUtil.hasConsentJWT(reqHeaders)) { // Open Bank Project's Consent
|
||||
Consent.applyRules(APIUtil.getConsentJWT(reqHeaders), cc)
|
||||
val consentValue = APIUtil.getConsentJWT(reqHeaders)
|
||||
Consent.getConsentsJwtValueByConsentId(consentValue.getOrElse("")) match {
|
||||
case Some(jwt) => // JWT value obtained via "Consent-Id" request header
|
||||
Consent.applyRules(Some(jwt), cc)
|
||||
case _ => // Assume it's JWT obtained via "Consent-JWT" request header
|
||||
Consent.applyRules(APIUtil.getConsentJWT(reqHeaders), cc)
|
||||
}
|
||||
} else if (hasAnOAuthHeader(cc.authReqHeaderField)) { // OAuth 1
|
||||
getUserFromOAuthHeaderFuture(cc)
|
||||
} else if (hasAnOAuth2Header(cc.authReqHeaderField)) { // OAuth 2
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
package code.api.util
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.{Date, UUID}
|
||||
|
||||
import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.{ConsentAccessJson, PostConsentJson}
|
||||
import code.api.v3_1_0.{PostConsentEntitlementJsonV310, PostConsentBodyCommonJson, PostConsentViewJsonV310}
|
||||
import code.api.v3_1_0.{PostConsentBodyCommonJson, PostConsentEntitlementJsonV310, PostConsentViewJsonV310}
|
||||
import code.api.{Constant, RequestHeader}
|
||||
import code.bankconnectors.Connector
|
||||
import code.consent
|
||||
@ -19,11 +19,12 @@ import code.views.Views
|
||||
import com.nimbusds.jwt.JWTClaimsSet
|
||||
import com.openbankproject.commons.ExecutionContext.Implicits.global
|
||||
import com.openbankproject.commons.model._
|
||||
import net.liftweb.common.{Box, Failure, Full}
|
||||
import net.liftweb.common.{Box, Empty, Failure, Full}
|
||||
import net.liftweb.http.provider.HTTPParam
|
||||
import net.liftweb.json.JsonParser.ParseException
|
||||
import net.liftweb.json.{Extraction, MappingException, compactRender, parse}
|
||||
import net.liftweb.mapper.By
|
||||
import net.liftweb.util.ControlHelpers
|
||||
import sh.ory.hydra.model.OAuth2TokenIntrospection
|
||||
|
||||
import scala.collection.immutable.{List, Nil}
|
||||
@ -312,7 +313,7 @@ object Consent {
|
||||
}
|
||||
}
|
||||
|
||||
private def hasConsentInternal(consentIdAsJwt: String, callContext: CallContext): Future[(Box[User], Option[CallContext])] = {
|
||||
private def hasConsentInternal(consentAsJwt: String, callContext: CallContext): Future[(Box[User], Option[CallContext])] = {
|
||||
implicit val dateFormats = CustomJsonFormats.formats
|
||||
|
||||
def applyConsentRules(consent: ConsentJWT): Future[(Box[User], Option[CallContext])] = {
|
||||
@ -335,15 +336,15 @@ object Consent {
|
||||
}
|
||||
}
|
||||
case _ =>
|
||||
(Failure("Cannot create or get the user based on: " + consentIdAsJwt), Some(cc))
|
||||
(Failure("Cannot create or get the user based on: " + consentAsJwt), Some(cc))
|
||||
}
|
||||
}
|
||||
|
||||
JwtUtil.getSignedPayloadAsJson(consentIdAsJwt) match {
|
||||
JwtUtil.getSignedPayloadAsJson(consentAsJwt) match {
|
||||
case Full(jsonAsString) =>
|
||||
try {
|
||||
val consent = net.liftweb.json.parse(jsonAsString).extract[ConsentJWT]
|
||||
checkConsent(consent, consentIdAsJwt, callContext) match { // Check is it Consent-JWT expired
|
||||
checkConsent(consent, consentAsJwt, callContext) match { // Check is it Consent-JWT expired
|
||||
case (Full(true)) => // OK
|
||||
applyConsentRules(consent)
|
||||
case failure@Failure(_, _, _) => // Handled errors
|
||||
@ -359,25 +360,36 @@ object Consent {
|
||||
case failure@Failure(_, _, _) =>
|
||||
Future(failure, Some(callContext))
|
||||
case _ =>
|
||||
Future(Failure("Cannot extract data from: " + consentIdAsJwt), Some(callContext))
|
||||
Future(Failure("Cannot extract data from: " + consentAsJwt), Some(callContext))
|
||||
}
|
||||
}
|
||||
|
||||
private def hasConsentOldStyle(consentIdAsJwt: String, callContext: CallContext): (Box[User], CallContext) = {
|
||||
(hasConsentInternalOldStyle(consentIdAsJwt, callContext), callContext)
|
||||
}
|
||||
private def hasConsent(consentIdAsJwt: String, callContext: CallContext): Future[(Box[User], Option[CallContext])] = {
|
||||
hasConsentInternal(consentIdAsJwt, callContext)
|
||||
private def hasConsent(consentAsJwt: String, callContext: CallContext): Future[(Box[User], Option[CallContext])] = {
|
||||
hasConsentInternal(consentAsJwt, callContext)
|
||||
}
|
||||
|
||||
def applyRules(consentId: Option[String], callContext: CallContext): Future[(Box[User], Option[CallContext])] = {
|
||||
def applyRules(consentJwt: Option[String], callContext: CallContext): Future[(Box[User], Option[CallContext])] = {
|
||||
val allowed = APIUtil.getPropsAsBoolValue(nameOfProperty="consents.allowed", defaultValue=false)
|
||||
(consentId, allowed) match {
|
||||
(consentJwt, allowed) match {
|
||||
case (Some(consentId), true) => hasConsent(consentId, callContext)
|
||||
case (_, false) => Future((Failure(ErrorMessages.ConsentDisabled), Some(callContext)))
|
||||
case (None, _) => Future((Failure(ErrorMessages.ConsentHeaderNotFound), Some(callContext)))
|
||||
}
|
||||
}
|
||||
|
||||
def getConsentsJwtValueByConsentId(consentId: String): Option[String] = {
|
||||
ControlHelpers.tryo(UUID.fromString(consentId)).isDefined match {
|
||||
case true => // String is a UUID
|
||||
Consents.consentProvider.vend.getConsentByConsentId(consentId) match {
|
||||
case Full(consent) => Some(consent.jsonWebToken)
|
||||
case _ => None // It's not valid UUID value
|
||||
}
|
||||
case false => None // It's not UUID at all
|
||||
}
|
||||
}
|
||||
|
||||
private def copyAuthContextOfConsentToUser(consentId: String, userId: String, newUser: Boolean): Box[List[UserAuthContext]] = {
|
||||
if(newUser) {
|
||||
|
||||
@ -131,7 +131,8 @@ class ConsentRequestTest extends V500ServerSetupAsync with PropsReset{
|
||||
val getConsentByRequestResponseJson = getConsentByRequestResponse.body.extract[ConsentJsonV500]
|
||||
getConsentByRequestResponseJson.consent_request_id.head should be(consentRequestId)
|
||||
getConsentByRequestResponseJson.status should be(ConsentStatus.ACCEPTED.toString)
|
||||
|
||||
|
||||
// Test Request Header "Consent-JWT:SOME_VALUE"
|
||||
val consentRequestHeader = (s"Consent-JWT", getConsentByRequestResponseJson.jwt)
|
||||
val requestGetUsers = (v5_0_0_Request / "users").GET
|
||||
val responseGetUsers = makeGetRequest(requestGetUsers, List(consentRequestHeader))
|
||||
@ -139,6 +140,16 @@ class ConsentRequestTest extends V500ServerSetupAsync with PropsReset{
|
||||
responseGetUsers.code should equal(200)
|
||||
val users = responseGetUsers.body.extract[UsersJsonV400].users
|
||||
users.size should be > 0
|
||||
|
||||
// Test Request Header "Consent-Id:SOME_VALUE"
|
||||
val consentIdRequestHeader = (s"Consent-Id", getConsentByRequestResponseJson.consent_id)
|
||||
val responseGetUsersSecond = makeGetRequest(requestGetUsers, List(consentRequestHeader))
|
||||
Then("We get successful response")
|
||||
responseGetUsersSecond.code should equal(200)
|
||||
val usersSecond = responseGetUsersSecond.body.extract[UsersJsonV400].users
|
||||
usersSecond.size should be > 0
|
||||
|
||||
users.size should equal(usersSecond.size)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user