Add exchange model and formatter
This commit is contained in:
Родитель
9b72f009ab
Коммит
a325ab6384
|
@ -60,6 +60,9 @@
|
|||
5577E86F251E8EB3005250BC /* IssuanceServiceResponseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5577E86E251E8EB3005250BC /* IssuanceServiceResponseTests.swift */; };
|
||||
5577E871251E8FE3005250BC /* OIDCClaimsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5577E870251E8FE3005250BC /* OIDCClaimsTests.swift */; };
|
||||
5577E873251E9007005250BC /* MockOIDCClaims.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5577E872251E9007005250BC /* MockOIDCClaims.swift */; };
|
||||
55793BCB255A0497007F7599 /* ExchangeResponseClaims.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55793BCA255A0497007F7599 /* ExchangeResponseClaims.swift */; };
|
||||
55793BCD255A070E007F7599 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55793BCC255A070E007F7599 /* Constants.swift */; };
|
||||
55793BCF255A08FE007F7599 /* ExchangeResponseFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55793BCE255A08FE007F7599 /* ExchangeResponseFormatter.swift */; };
|
||||
557BFC46251E6058005B5B24 /* IssuanceResponseClaimsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 557BFC45251E6058005B5B24 /* IssuanceResponseClaimsTests.swift */; };
|
||||
557BFC53251E665D005B5B24 /* IssuanceResponseFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 557BFC51251E665D005B5B24 /* IssuanceResponseFormatter.swift */; };
|
||||
557BFC56251E6701005B5B24 /* IssuanceResponseContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 557BFC55251E6701005B5B24 /* IssuanceResponseContainer.swift */; };
|
||||
|
@ -150,6 +153,9 @@
|
|||
5577E86E251E8EB3005250BC /* IssuanceServiceResponseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssuanceServiceResponseTests.swift; sourceTree = "<group>"; };
|
||||
5577E870251E8FE3005250BC /* OIDCClaimsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OIDCClaimsTests.swift; sourceTree = "<group>"; };
|
||||
5577E872251E9007005250BC /* MockOIDCClaims.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockOIDCClaims.swift; sourceTree = "<group>"; };
|
||||
55793BCA255A0497007F7599 /* ExchangeResponseClaims.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExchangeResponseClaims.swift; sourceTree = "<group>"; };
|
||||
55793BCC255A070E007F7599 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||
55793BCE255A08FE007F7599 /* ExchangeResponseFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExchangeResponseFormatter.swift; sourceTree = "<group>"; };
|
||||
557BFC45251E6058005B5B24 /* IssuanceResponseClaimsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssuanceResponseClaimsTests.swift; sourceTree = "<group>"; };
|
||||
557BFC51251E665D005B5B24 /* IssuanceResponseFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssuanceResponseFormatter.swift; sourceTree = "<group>"; };
|
||||
557BFC55251E6701005B5B24 /* IssuanceResponseContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssuanceResponseContainer.swift; sourceTree = "<group>"; };
|
||||
|
@ -248,6 +254,7 @@
|
|||
children = (
|
||||
557BFC50251E665D005B5B24 /* formatters */,
|
||||
5577E865251E830B005250BC /* identifier */,
|
||||
55793BC8255A0468007F7599 /* exchange */,
|
||||
5577E862251E8284005250BC /* issuance */,
|
||||
5584E49725255A8F00A9DE58 /* presentation */,
|
||||
5577E864251E82B2005250BC /* verifiableCredential */,
|
||||
|
@ -364,11 +371,28 @@
|
|||
path = issuance;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
55793BC8255A0468007F7599 /* exchange */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
55793BC9255A0484007F7599 /* claims */,
|
||||
);
|
||||
path = exchange;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
55793BC9255A0484007F7599 /* claims */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
55793BCA255A0497007F7599 /* ExchangeResponseClaims.swift */,
|
||||
);
|
||||
path = claims;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
557BFC50251E665D005B5B24 /* formatters */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
557BFC51251E665D005B5B24 /* IssuanceResponseFormatter.swift */,
|
||||
551F305A252E39540081D5E7 /* IdentifierFormatter.swift */,
|
||||
55793BCE255A08FE007F7599 /* ExchangeResponseFormatter.swift */,
|
||||
5518CC7125264C6F00C7A21B /* PresentationResponseFormatter.swift */,
|
||||
555CE08925267FE500C1C938 /* VerifiablePresentationFormatter.swift */,
|
||||
551F30422527DC050081D5E7 /* JwsHeaderFormatter .swift */,
|
||||
|
@ -433,6 +457,7 @@
|
|||
55AF7481252F6803006A8B25 /* util */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
55793BCC255A070E007F7599 /* Constants.swift */,
|
||||
55575762251BC6CF009979AB /* JSONCodingKeys.swift */,
|
||||
551F3062252E6E230081D5E7 /* Multihash.swift */,
|
||||
);
|
||||
|
@ -603,6 +628,7 @@
|
|||
55575773251BC6CF009979AB /* VerifiableCredentialDescriptor.swift in Sources */,
|
||||
555CE08F2526822300C1C938 /* VerifiablePresentationDescriptor.swift in Sources */,
|
||||
55575770251BC6CF009979AB /* OIDCClaims.swift in Sources */,
|
||||
55793BCF255A08FE007F7599 /* ExchangeResponseFormatter.swift in Sources */,
|
||||
5557576C251BC6CF009979AB /* CardDisplayDescriptor.swift in Sources */,
|
||||
55AF748E252F6BE0006A8B25 /* Identifier.swift in Sources */,
|
||||
55AF7486252F6B1F006A8B25 /* IdentifierDocumentServiceEndpoint.swift in Sources */,
|
||||
|
@ -611,10 +637,12 @@
|
|||
551F305D252E4C1B0081D5E7 /* IdentifierDocument.swift in Sources */,
|
||||
55575777251BC6CF009979AB /* IssuanceServiceResponse.swift in Sources */,
|
||||
55309B762539DDC300AF15AA /* VerifiableCredential.swift in Sources */,
|
||||
55793BCB255A0497007F7599 /* ExchangeResponseClaims.swift in Sources */,
|
||||
551F30432527DC050081D5E7 /* JwsHeaderFormatter .swift in Sources */,
|
||||
55575765251BC6CF009979AB /* ConsentDisplayDescriptor.swift in Sources */,
|
||||
5584E49C2525641600A9DE58 /* PresentationDefinition.swift in Sources */,
|
||||
555CE08D2526810100C1C938 /* VerifiablePresentationClaims.swift in Sources */,
|
||||
55793BCD255A070E007F7599 /* Constants.swift in Sources */,
|
||||
5584E4A2252565D900A9DE58 /* IssuanceMetadata.swift in Sources */,
|
||||
5518CC68252645D000C7A21B /* PresentationSubmission.swift in Sources */,
|
||||
5557576A251BC6CF009979AB /* Contract.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import VCJwt
|
||||
|
||||
public struct ExchangeResponseClaims: OIDCClaims {
|
||||
|
||||
public let issuer: String = Constants.SELF_ISSUED
|
||||
|
||||
public let publicKeyThumbprint: String
|
||||
|
||||
public let audience: String
|
||||
|
||||
public let did: String
|
||||
|
||||
public let publicJwk: ECPublicJwk?
|
||||
|
||||
public let contract: String
|
||||
|
||||
public let jti: String
|
||||
|
||||
public let iat: Double?
|
||||
|
||||
public let exp: Double?
|
||||
|
||||
public let exchangeableVc: String
|
||||
|
||||
public let recipientDid: String
|
||||
|
||||
public init(publicKeyThumbprint: String = "",
|
||||
audience: String = "",
|
||||
did: String = "",
|
||||
publicJwk: ECPublicJwk? = nil,
|
||||
contract: String = "",
|
||||
jti: String = "",
|
||||
iat: Double? = nil,
|
||||
exp: Double? = nil,
|
||||
exchangeableVc: String = "",
|
||||
recipientDid: String = "") {
|
||||
self.publicKeyThumbprint = publicKeyThumbprint
|
||||
self.audience = audience
|
||||
self.did = did
|
||||
self.publicJwk = publicJwk
|
||||
self.contract = contract
|
||||
self.jti = jti
|
||||
self.iat = iat
|
||||
self.exp = exp
|
||||
self.exchangeableVc = exchangeableVc
|
||||
self.recipientDid = recipientDid
|
||||
}
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case issuer = "iss"
|
||||
case publicKeyThumbprint = "sub"
|
||||
case audience = "aud"
|
||||
case publicJwk = "sub_jwk"
|
||||
case exchangeableVc = "vc"
|
||||
case recipientDid = "recipient"
|
||||
case contract, jti, did, iat, exp
|
||||
}
|
||||
}
|
||||
|
||||
public typealias ExchangeResponse = JwsToken<ExchangeResponseClaims>
|
|
@ -0,0 +1,62 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import VCJwt
|
||||
|
||||
public protocol ExchangeResponseFormatting {
|
||||
func format(usingIdentifier identifier: Identifier, andExchangeableVc vc: VerifiableCredential) throws -> ExchangeResponse
|
||||
}
|
||||
|
||||
public class ExchangeResponseFormatter: ExchangeResponseFormatting {
|
||||
|
||||
let signer: TokenSigning
|
||||
let headerFormatter = JwsHeaderFormatter()
|
||||
|
||||
public init(signer: TokenSigning = Secp256k1Signer()) {
|
||||
self.signer = signer
|
||||
}
|
||||
|
||||
public func format(usingIdentifier identifier: Identifier, andExchangeableVc vc: VerifiableCredential) throws -> ExchangeResponse {
|
||||
|
||||
guard let signingKey = identifier.didDocumentKeys.first else {
|
||||
throw FormatterError.noSigningKeyFound
|
||||
}
|
||||
|
||||
return try createToken(usingIdentifier: identifier, andExchangeableVc: vc, andSignWith: signingKey)
|
||||
}
|
||||
|
||||
private func createToken(usingIdentifier identifier: Identifier, andExchangeableVc vc: VerifiableCredential, andSignWith signingKey: KeyContainer) throws -> ExchangeResponse {
|
||||
|
||||
let headers = headerFormatter.formatHeaders(usingIdentifier: identifier, andSigningKey: signingKey)
|
||||
let tokenContents = try formatClaims(usingIdentifier: identifier, andExchangeableVc: vc, andSigningKey: signingKey)
|
||||
|
||||
guard var token = JwsToken(headers: headers, content: tokenContents) else {
|
||||
throw FormatterError.unableToFormToken
|
||||
}
|
||||
|
||||
try token.sign(using: self.signer, withSecret: signingKey.keyReference)
|
||||
return token
|
||||
}
|
||||
|
||||
private func formatClaims(usingIdentifier identifier: Identifier, andExchangeableVc vc: VerifiableCredential, andSigningKey key: KeyContainer) throws -> ExchangeResponseClaims {
|
||||
|
||||
guard let audience = vc.token.content.vc.exchangeService?.id else {
|
||||
throw FormatterError.noAudienceFoundInRequest
|
||||
}
|
||||
|
||||
let publicKey = try signer.getPublicJwk(from: key.keyReference, withKeyId: key.keyId)
|
||||
let timeConstraints = TokenTimeConstraints(expiryInSeconds: 5)
|
||||
|
||||
return ExchangeResponseClaims(publicKeyThumbprint: try publicKey.getThumbprint(),
|
||||
audience: audience,
|
||||
did: vc.token.content.sub,
|
||||
publicJwk: publicKey,
|
||||
jti: UUID().uuidString,
|
||||
iat: timeConstraints.issuedAt,
|
||||
exp: timeConstraints.expiration,
|
||||
exchangeableVc: vc.raw,
|
||||
recipientDid: identifier.longFormDid)
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ import VCJwt
|
|||
|
||||
public struct IssuanceResponseClaims: OIDCClaims {
|
||||
|
||||
public let issuer: String = "https://self-issued.me"
|
||||
public let issuer: String = Constants.SELF_ISSUED
|
||||
|
||||
public let publicKeyThumbprint: String
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import VCJwt
|
|||
|
||||
public struct PresentationResponseClaims: OIDCClaims {
|
||||
|
||||
public let issuer: String = "https://self-issued.me"
|
||||
public let issuer: String = Constants.SELF_ISSUED
|
||||
|
||||
public let publicKeyThumbprint: String
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
struct Constants {
|
||||
static let SELF_ISSUED = "https://self-issued.me"
|
||||
}
|
Загрузка…
Ссылка в новой задаче