Skip to content

Commit d52e940

Browse files
Refactored codable implementations into their own extensions for readability (#110)
1 parent 1fa7a47 commit d52e940

File tree

5 files changed

+64
-66
lines changed

5 files changed

+64
-66
lines changed

Sources/WebAuthn/Ceremonies/Authentication/AuthenticatorAssertionResponse.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ extension AuthenticatorAssertionResponse: Codable {
5858
userHandle = try container.decodeBytesFromURLEncodedBase64IfPresent(forKey: .userHandle)
5959
attestationObject = try container.decodeBytesFromURLEncodedBase64IfPresent(forKey: .attestationObject)
6060
}
61-
61+
6262
public func encode(to encoder: any Encoder) throws {
6363
var container = encoder.container(keyedBy: CodingKeys.self)
6464

@@ -69,7 +69,6 @@ extension AuthenticatorAssertionResponse: Codable {
6969
try container.encodeIfPresent(attestationObject?.base64URLEncodedString(), forKey: .attestationObject)
7070
}
7171

72-
7372
private enum CodingKeys: String, CodingKey {
7473
case clientDataJSON
7574
case authenticatorData

Sources/WebAuthn/Ceremonies/Authentication/PublicKeyCredentialRequestOptions.swift

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import Foundation
1818
/// When encoding using `Encodable`, the byte arrays are encoded as base64url.
1919
///
2020
/// - SeeAlso: https://www.w3.org/TR/webauthn-2/#dictionary-assertion-options
21-
public struct PublicKeyCredentialRequestOptions: Codable, Sendable {
21+
public struct PublicKeyCredentialRequestOptions: Sendable {
2222
/// A challenge that the authenticator signs, along with other data, when producing an authentication assertion
2323
///
2424
/// When encoding using `Encodable` this is encoded as base64url.
@@ -45,16 +45,6 @@ public struct PublicKeyCredentialRequestOptions: Codable, Sendable {
4545

4646
// let extensions: [String: Any]
4747

48-
public func encode(to encoder: any Encoder) throws {
49-
var container = encoder.container(keyedBy: CodingKeys.self)
50-
51-
try container.encode(challenge.base64URLEncodedString(), forKey: .challenge)
52-
try container.encodeIfPresent(timeout?.milliseconds, forKey: .timeout)
53-
try container.encode(relyingPartyID, forKey: .relyingPartyID)
54-
try container.encodeIfPresent(allowCredentials, forKey: .allowCredentials)
55-
try container.encodeIfPresent(userVerification, forKey: .userVerification)
56-
}
57-
5848
public init(
5949
challenge: [UInt8],
6050
timeout: Duration?,
@@ -68,7 +58,9 @@ public struct PublicKeyCredentialRequestOptions: Codable, Sendable {
6858
self.allowCredentials = allowCredentials
6959
self.userVerification = userVerification
7060
}
61+
}
7162

63+
extension PublicKeyCredentialRequestOptions: Codable {
7264
public init(from decoder: any Decoder) throws {
7365
let values = try decoder.container(keyedBy: CodingKeys.self)
7466

@@ -81,6 +73,16 @@ public struct PublicKeyCredentialRequestOptions: Codable, Sendable {
8173
self.allowCredentials = try values.decodeIfPresent([PublicKeyCredentialDescriptor].self, forKey: .allowCredentials)
8274
self.userVerification = try values.decodeIfPresent(UserVerificationRequirement.self, forKey: .userVerification)
8375
}
76+
77+
public func encode(to encoder: any Encoder) throws {
78+
var container = encoder.container(keyedBy: CodingKeys.self)
79+
80+
try container.encode(challenge.base64URLEncodedString(), forKey: .challenge)
81+
try container.encodeIfPresent(timeout?.milliseconds, forKey: .timeout)
82+
try container.encode(relyingPartyID, forKey: .relyingPartyID)
83+
try container.encodeIfPresent(allowCredentials, forKey: .allowCredentials)
84+
try container.encodeIfPresent(userVerification, forKey: .userVerification)
85+
}
8486

8587
private enum CodingKeys: String, CodingKey {
8688
case challenge
@@ -94,7 +96,7 @@ public struct PublicKeyCredentialRequestOptions: Codable, Sendable {
9496
/// Information about a generated credential.
9597
///
9698
/// When encoding using `Encodable`, `id` is encoded as base64url.
97-
public struct PublicKeyCredentialDescriptor: Equatable, Codable, Sendable {
99+
public struct PublicKeyCredentialDescriptor: Equatable, Sendable {
98100
/// Defines hints as to how clients might communicate with a particular authenticator in order to obtain an
99101
/// assertion for a specific credential
100102
public struct AuthenticatorTransport: UnreferencedStringEnumeration, Sendable {
@@ -138,15 +140,9 @@ public struct PublicKeyCredentialDescriptor: Equatable, Codable, Sendable {
138140
self.id = id
139141
self.transports = transports
140142
}
143+
}
141144

142-
public func encode(to encoder: any Encoder) throws {
143-
var container = encoder.container(keyedBy: CodingKeys.self)
144-
145-
try container.encode(type, forKey: .type)
146-
try container.encode(id.base64URLEncodedString(), forKey: .id)
147-
try container.encodeIfPresent(transports, forKey: .transports)
148-
}
149-
145+
extension PublicKeyCredentialDescriptor: Codable {
150146
public init(from decoder: any Decoder) throws {
151147
let container = try decoder.container(keyedBy: CodingKeys.self)
152148

@@ -155,6 +151,14 @@ public struct PublicKeyCredentialDescriptor: Equatable, Codable, Sendable {
155151
self.transports = try container.decodeIfPresent([AuthenticatorTransport].self, forKey: .transports) ?? []
156152
}
157153

154+
public func encode(to encoder: any Encoder) throws {
155+
var container = encoder.container(keyedBy: CodingKeys.self)
156+
157+
try container.encode(type, forKey: .type)
158+
try container.encode(id.base64URLEncodedString(), forKey: .id)
159+
try container.encodeIfPresent(transports, forKey: .transports)
160+
}
161+
158162
private enum CodingKeys: String, CodingKey {
159163
case type
160164
case id

Sources/WebAuthn/Ceremonies/Registration/AuthenticatorAttestationResponse.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,14 @@ extension AuthenticatorAttestationResponse: Codable {
3636
clientDataJSON = try container.decodeBytesFromURLEncodedBase64(forKey: .clientDataJSON)
3737
attestationObject = try container.decodeBytesFromURLEncodedBase64(forKey: .attestationObject)
3838
}
39-
39+
4040
public func encode(to encoder: any Encoder) throws {
4141
var container = encoder.container(keyedBy: CodingKeys.self)
4242

4343
try container.encode(clientDataJSON.base64URLEncodedString(), forKey: .clientDataJSON)
4444
try container.encode(attestationObject.base64URLEncodedString(), forKey: .attestationObject)
4545
}
4646

47-
4847
private enum CodingKeys: String, CodingKey {
4948
case clientDataJSON
5049
case attestationObject

Sources/WebAuthn/Ceremonies/Registration/PublicKeyCredentialCreationOptions.swift

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import Foundation
1919
/// `Encodable` byte arrays are base64url encoded.
2020
///
2121
/// - SeeAlso: https://www.w3.org/TR/webauthn-2/#dictionary-makecredentialoptions
22-
public struct PublicKeyCredentialCreationOptions: Codable, Sendable {
22+
public struct PublicKeyCredentialCreationOptions: Sendable {
2323
/// A byte array randomly generated by the Relying Party. Should be at least 16 bytes long to ensure sufficient
2424
/// entropy.
2525
///
@@ -47,30 +47,6 @@ public struct PublicKeyCredentialCreationOptions: Codable, Sendable {
4747
/// supported.
4848
public var attestation: AttestationConveyancePreference
4949

50-
public func encode(to encoder: any Encoder) throws {
51-
var container = encoder.container(keyedBy: CodingKeys.self)
52-
53-
try container.encode(challenge.base64URLEncodedString(), forKey: .challenge)
54-
try container.encode(user, forKey: .user)
55-
try container.encode(relyingParty, forKey: .relyingParty)
56-
try container.encode(publicKeyCredentialParameters, forKey: .publicKeyCredentialParameters)
57-
try container.encodeIfPresent(timeout?.milliseconds, forKey: .timeout)
58-
try container.encode(attestation, forKey: .attestation)
59-
}
60-
61-
public init(from decoder: any Decoder) throws {
62-
let values = try decoder.container(keyedBy: CodingKeys.self)
63-
64-
self.challenge = try values.decodeBytesFromURLEncodedBase64(forKey: .challenge)
65-
self.user = try values.decode(PublicKeyCredentialUserEntity.self, forKey: .user)
66-
self.relyingParty = try values.decode(PublicKeyCredentialRelyingPartyEntity.self, forKey: .relyingParty)
67-
self.publicKeyCredentialParameters = try values.decode([PublicKeyCredentialParameters].self, forKey: .publicKeyCredentialParameters)
68-
if let timeout = try values.decodeIfPresent(UInt32.self, forKey: .timeout) {
69-
self.timeout = .milliseconds(timeout)
70-
}
71-
self.attestation = try values.decode(AttestationConveyancePreference.self, forKey: .attestation)
72-
}
73-
7450
public init(
7551
challenge: [UInt8],
7652
user: PublicKeyCredentialUserEntity,
@@ -86,6 +62,32 @@ public struct PublicKeyCredentialCreationOptions: Codable, Sendable {
8662
self.timeout = timeout
8763
self.attestation = attestation
8864
}
65+
}
66+
67+
extension PublicKeyCredentialCreationOptions: Codable {
68+
public init(from decoder: any Decoder) throws {
69+
let values = try decoder.container(keyedBy: CodingKeys.self)
70+
71+
self.challenge = try values.decodeBytesFromURLEncodedBase64(forKey: .challenge)
72+
self.user = try values.decode(PublicKeyCredentialUserEntity.self, forKey: .user)
73+
self.relyingParty = try values.decode(PublicKeyCredentialRelyingPartyEntity.self, forKey: .relyingParty)
74+
self.publicKeyCredentialParameters = try values.decode([PublicKeyCredentialParameters].self, forKey: .publicKeyCredentialParameters)
75+
if let timeout = try values.decodeIfPresent(UInt32.self, forKey: .timeout) {
76+
self.timeout = .milliseconds(timeout)
77+
}
78+
self.attestation = try values.decode(AttestationConveyancePreference.self, forKey: .attestation)
79+
}
80+
81+
public func encode(to encoder: any Encoder) throws {
82+
var container = encoder.container(keyedBy: CodingKeys.self)
83+
84+
try container.encode(challenge.base64URLEncodedString(), forKey: .challenge)
85+
try container.encode(user, forKey: .user)
86+
try container.encode(relyingParty, forKey: .relyingParty)
87+
try container.encode(publicKeyCredentialParameters, forKey: .publicKeyCredentialParameters)
88+
try container.encodeIfPresent(timeout?.milliseconds, forKey: .timeout)
89+
try container.encode(attestation, forKey: .attestation)
90+
}
8991

9092
private enum CodingKeys: String, CodingKey {
9193
case challenge
@@ -116,13 +118,6 @@ public struct PublicKeyCredentialParameters: Equatable, Codable, Sendable {
116118
self.type = type
117119
self.alg = alg
118120
}
119-
120-
public init(from decoder: any Decoder) throws {
121-
let container = try decoder.container(keyedBy: CodingKeys.self)
122-
123-
self.type = try container.decode(CredentialType.self, forKey: .type)
124-
self.alg = try container.decode(COSEAlgorithmIdentifier.self, forKey: .alg)
125-
}
126121
}
127122

128123
extension Array where Element == PublicKeyCredentialParameters {
@@ -158,7 +153,7 @@ public struct PublicKeyCredentialRelyingPartyEntity: Codable, Sendable {
158153
/// creating a new credential.
159154
///
160155
/// When encoding using `Encodable`, `id` is base64url encoded.
161-
public struct PublicKeyCredentialUserEntity: Codable, Sendable {
156+
public struct PublicKeyCredentialUserEntity: Sendable {
162157
/// Generated by the Relying Party, unique to the user account, and must not contain personally identifying
163158
/// information about the user.
164159
///
@@ -181,15 +176,9 @@ public struct PublicKeyCredentialUserEntity: Codable, Sendable {
181176
self.name = name
182177
self.displayName = displayName
183178
}
179+
}
184180

185-
public func encode(to encoder: any Encoder) throws {
186-
var container = encoder.container(keyedBy: CodingKeys.self)
187-
188-
try container.encode(id.base64URLEncodedString(), forKey: .id)
189-
try container.encode(name, forKey: .name)
190-
try container.encode(displayName, forKey: .displayName)
191-
}
192-
181+
extension PublicKeyCredentialUserEntity: Codable {
193182
public init(from decoder: any Decoder) throws {
194183
let container = try decoder.container(keyedBy: CodingKeys.self)
195184

@@ -198,6 +187,13 @@ public struct PublicKeyCredentialUserEntity: Codable, Sendable {
198187
self.displayName = try container.decode(String.self, forKey: .displayName)
199188
}
200189

190+
public func encode(to encoder: any Encoder) throws {
191+
var container = encoder.container(keyedBy: CodingKeys.self)
192+
193+
try container.encode(id.base64URLEncodedString(), forKey: .id)
194+
try container.encode(name, forKey: .name)
195+
try container.encode(displayName, forKey: .displayName)
196+
}
201197

202198
private enum CodingKeys: String, CodingKey {
203199
case id

Sources/WebAuthn/Ceremonies/Registration/RegistrationCredential.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ extension RegistrationCredential: Codable {
4747
self.rawID = rawID
4848
attestationResponse = try container.decode(AuthenticatorAttestationResponse.self, forKey: .attestationResponse)
4949
}
50-
50+
5151
public func encode(to encoder: any Encoder) throws {
5252
var container = encoder.container(keyedBy: CodingKeys.self)
5353

0 commit comments

Comments
 (0)