mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 17:37:00 +00:00
feature/Dynamic Registration of Consumer - WIP 4
This commit is contained in:
parent
e12fecd8ed
commit
34a8954edc
@ -520,6 +520,7 @@ object ErrorMessages {
|
||||
val RegulatedEntityNotFound = "OBP-34100: Regulated Entity not found. Please specify a valid value for REGULATED_ENTITY_ID."
|
||||
val RegulatedEntityNotDeleted = "OBP-34101: Regulated Entity cannot be deleted. Please specify a valid value for REGULATED_ENTITY_ID."
|
||||
val RegulatedEntityNotFoundByCertificate = "OBP-34102: Regulated Entity cannot be found by provided certificate."
|
||||
val PostJsonIsNotSigned = "OBP-34110: JWT at the post json cannot be verified."
|
||||
|
||||
// Consents
|
||||
val ConsentNotFound = "OBP-35001: Consent not found by CONSENT_ID. "
|
||||
|
||||
@ -269,6 +269,15 @@ object JwtUtil extends MdcLoggable {
|
||||
jwk.toPublicJWK.toRSAKey
|
||||
}
|
||||
|
||||
def verifyJwt(jwtString: String, pemEncodedRsaPublicKey: String): Boolean = {
|
||||
// Parse PEM-encoded key to RSA public / private JWK
|
||||
val jwk: JWK = JWK.parseFromPEMEncodedObjects(pemEncodedRsaPublicKey);
|
||||
val rsaPublicKey: RSAKey = jwk.toPublicJWK.toRSAKey
|
||||
val signedJWT = SignedJWT.parse(jwtString)
|
||||
val verifier = new RSASSAVerifier(rsaPublicKey)
|
||||
signedJWT.verify(verifier)
|
||||
}
|
||||
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
val jwtToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjhhYWQ2NmJkZWZjMWI0M2Q4ZGIyN2U2NWUyZTJlZjMwMTg3OWQzZTgiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI0MDc0MDg3MTgxOTIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI0MDc0MDg3MTgxOTIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMTM5NjY4NTQyNDU3ODA4OTI5NTkiLCJhdF9oYXNoIjoiWGlpckZ1cnJ2X0ZxN3RHd25rLWt1QSIsIm5hbWUiOiJNYXJrbyBNaWxpxIciLCJwaWN0dXJlIjoiaHR0cHM6Ly9saDUuZ29vZ2xldXNlcmNvbnRlbnQuY29tLy1YZDQ0aG5KNlREby9BQUFBQUFBQUFBSS9BQUFBQUFBQUFBQS9BS3hyd2NhZHd6aG00TjR0V2s1RThBdnhpLVpLNmtzNHFnL3M5Ni1jL3Bob3RvLmpwZyIsImdpdmVuX25hbWUiOiJNYXJrbyIsImZhbWlseV9uYW1lIjoiTWlsacSHIiwibG9jYWxlIjoiZW4iLCJpYXQiOjE1NDczMTE3NjAsImV4cCI6MTU0NzMxNTM2MH0.UyOmM0rsO0-G_ibDH3DFogS94GcsNd9GtYVw7j3vSMjO1rZdIraV-N2HUtQN3yHopwdf35A2FEJaag6X8dbvEkJC7_GAynyLIpodoaHNtaLbww6XQSYuQYyF27aPMpROoGZUYkMpB_82LF3PbD4ecDPC2IA5oSyDF4Eya4yn-MzxYmXS7usVWvanREg8iNQSxpu7zZqj4UwhvSIv7wH0vskr_M-PnefQzNTrdUx74i-v9lVqC4E_bF5jWeDGO8k5dqWqg55QuZdyJdSh89KNiIjJXGZDWUBzGfsbetWRnObIgX264fuOW4SpRglUc8fzv41Sc7SSqjqRAFm05t60kg"
|
||||
|
||||
@ -8,6 +8,7 @@ import code.api.util.ApiRole._
|
||||
import code.api.util.ApiTag._
|
||||
import code.api.util.ErrorMessages.{$UserNotLoggedIn, BankNotFound, ConsentNotFound, InvalidJsonFormat, UnknownError, UserNotFoundByUserId, UserNotLoggedIn, _}
|
||||
import code.api.util.FutureUtil.{EndpointContext, EndpointTimeout}
|
||||
import code.api.util.JwtUtil.{getSignedPayloadAsJson, verifyJwt}
|
||||
import code.api.util.NewStyle.HttpCode
|
||||
import code.api.util.X509.{getCommonName, getEmailAddress, getOrganization}
|
||||
import code.api.util._
|
||||
@ -42,7 +43,7 @@ import com.openbankproject.commons.model._
|
||||
import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion}
|
||||
import net.liftweb.common.Full
|
||||
import net.liftweb.http.rest.RestHelper
|
||||
import net.liftweb.json.parse
|
||||
import net.liftweb.json.{compactRender, parse}
|
||||
import net.liftweb.mapper.By
|
||||
import net.liftweb.util.Helpers
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
@ -1781,21 +1782,28 @@ trait APIMethods510 {
|
||||
"/dynamic-registration/consumers",
|
||||
"Create a Consumer",
|
||||
s"""Create a Consumer (mTLS access).
|
||||
|
|
||||
| JWT payload:
|
||||
| - minimal
|
||||
| { "description":"Description" }
|
||||
| - full
|
||||
| {
|
||||
| "description": "Description",
|
||||
| "app_name": "Tesobe GmbH",
|
||||
| "app_type": "Sofit",
|
||||
| "developer_email": "marko@tesobe.com",
|
||||
| "redirect_url": "http://localhost:8082"
|
||||
| }
|
||||
| Please note that JWT must be signed with the counterpart private kew of the public key used to establish mTLS
|
||||
|
|
||||
|""",
|
||||
ConsumerPostJsonV510(
|
||||
None,
|
||||
None,
|
||||
"Description",
|
||||
None,
|
||||
None,
|
||||
),
|
||||
ConsumerJwtPostJsonV510("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkZXNjcmlwdGlvbiI6IkRlc2NyaXB0aW9uIn0.qDnzk1dGK8akdLFRl8fmJV_SeoDjRTDG_eMogCIzZ7M"),
|
||||
consumerJsonV510,
|
||||
List(
|
||||
InvalidJsonFormat,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagConsumer),
|
||||
List(apiTagDirectory, apiTagConsumer),
|
||||
Some(Nil))
|
||||
|
||||
|
||||
@ -1804,10 +1812,16 @@ trait APIMethods510 {
|
||||
cc =>
|
||||
implicit val ec = EndpointContext(Some(cc))
|
||||
for {
|
||||
postedJson <- NewStyle.function.tryons(InvalidJsonFormat, 400, cc.callContext) {
|
||||
json.extract[ConsumerPostJsonV510]
|
||||
postedJwt <- NewStyle.function.tryons(InvalidJsonFormat, 400, cc.callContext) {
|
||||
json.extract[ConsumerJwtPostJsonV510]
|
||||
}
|
||||
pem = APIUtil.`getPSD2-CERT`(cc.requestHeaders)
|
||||
_ <- Helper.booleanToFuture(PostJsonIsNotSigned, 400, cc.callContext) {
|
||||
verifyJwt(postedJwt.jwt, pem.getOrElse(""))
|
||||
}
|
||||
postedJson <- NewStyle.function.tryons(InvalidJsonFormat, 400, cc.callContext) {
|
||||
parse(getSignedPayloadAsJson(postedJwt.jwt).getOrElse("{}")).extract[ConsumerPostJsonV510]
|
||||
}
|
||||
certificateInfo: CertificateInfoJsonV510 <- Future(X509.getCertificateInfo(pem)) map {
|
||||
unboxFullOrFail(_, cc.callContext, X509GeneralError)
|
||||
}
|
||||
|
||||
@ -281,6 +281,8 @@ case class MetricJsonV510(
|
||||
)
|
||||
case class MetricsJsonV510(metrics: List[MetricJsonV510])
|
||||
|
||||
|
||||
case class ConsumerJwtPostJsonV510(jwt: String)
|
||||
case class ConsumerPostJsonV510(app_name: Option[String],
|
||||
app_type: Option[String],
|
||||
description: String,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user