Skip to content

Commit a1e7ccd

Browse files
authored
Replaced public enums with string-based structs to be more resiliant against decoding unknown future values (#108)
1 parent d906591 commit a1e7ccd

File tree

6 files changed

+61
-31
lines changed

6 files changed

+61
-31
lines changed

Sources/WebAuthn/Ceremonies/Authentication/PublicKeyCredentialRequestOptions.swift

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,25 @@ public struct PublicKeyCredentialRequestOptions: Encodable, Sendable {
7070
public struct PublicKeyCredentialDescriptor: Equatable, Encodable, Sendable {
7171
/// Defines hints as to how clients might communicate with a particular authenticator in order to obtain an
7272
/// assertion for a specific credential
73-
public enum AuthenticatorTransport: String, Equatable, Encodable, Sendable {
73+
public struct AuthenticatorTransport: UnreferencedStringEnumeration, Sendable {
74+
public var rawValue: String
75+
public init(_ rawValue: String) {
76+
self.rawValue = rawValue
77+
}
78+
7479
/// Indicates the respective authenticator can be contacted over removable USB.
75-
case usb
80+
public static let usb: Self = "usb"
7681
/// Indicates the respective authenticator can be contacted over Near Field Communication (NFC).
77-
case nfc
82+
public static let nfc: Self = "nfc"
7883
/// Indicates the respective authenticator can be contacted over Bluetooth Smart (Bluetooth Low Energy / BLE).
79-
case ble
84+
public static let ble: Self = "ble"
8085
/// Indicates the respective authenticator can be contacted using a combination of (often separate)
8186
/// data-transport and proximity mechanisms. This supports, for example, authentication on a desktop
8287
/// computer using a smartphone.
83-
case hybrid
88+
public static let hybrid: Self = "hybrid"
8489
/// Indicates the respective authenticator is contacted using a client device-specific transport, i.e., it is
8590
/// a platform authenticator. These authenticators are not removable from the client device.
86-
case `internal`
91+
public static let `internal`: Self = "internal"
8792
}
8893

8994
/// Will always be ``CredentialType/publicKey``
@@ -124,13 +129,18 @@ public struct PublicKeyCredentialDescriptor: Equatable, Encodable, Sendable {
124129

125130
/// The Relying Party may require user verification for some of its operations but not for others, and may use this
126131
/// type to express its needs.
127-
public enum UserVerificationRequirement: String, Encodable, Sendable {
132+
public struct UserVerificationRequirement: UnreferencedStringEnumeration, Sendable {
133+
public var rawValue: String
134+
public init(_ rawValue: String) {
135+
self.rawValue = rawValue
136+
}
137+
128138
/// The Relying Party requires user verification for the operation and will fail the overall ceremony if the
129139
/// user wasn't verified.
130-
case required
140+
public static let required: Self = "required"
131141
/// The Relying Party prefers user verification for the operation if possible, but will not fail the operation.
132-
case preferred
142+
public static let preferred: Self = "preferred"
133143
/// The Relying Party does not want user verification employed during the operation (e.g., in the interest of
134144
/// minimizing disruption to the user interaction flow).
135-
case discouraged
145+
public static let discouraged: Self = "discouraged"
136146
}

Sources/WebAuthn/Ceremonies/Authentication/VerifiedAuthentication.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,14 @@ import Foundation
1515

1616
/// On successful authentication, this structure contains a summary of the authentication flow
1717
public struct VerifiedAuthentication: Sendable {
18-
public enum CredentialDeviceType: String, Sendable {
19-
case singleDevice = "single_device"
20-
case multiDevice = "multi_device"
18+
public struct CredentialDeviceType: UnreferencedStringEnumeration, Sendable {
19+
public var rawValue: String
20+
public init(_ rawValue: String) {
21+
self.rawValue = rawValue
22+
}
23+
24+
public static let singleDevice: Self = "single_device"
25+
public static let multiDevice: Self = "multi_device"
2126
}
2227

2328
/// The credential id associated with the public key

Sources/WebAuthn/Ceremonies/Registration/AttestationConveyancePreference.swift

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,15 @@
1414
/// Options to specify the Relying Party's preference regarding attestation conveyance during credential generation.
1515
///
1616
/// Currently only supports `none`.
17-
public enum AttestationConveyancePreference: String, Encodable, Sendable {
17+
public struct AttestationConveyancePreference: UnreferencedStringEnumeration, Sendable {
18+
public var rawValue: String
19+
public init(_ rawValue: String) {
20+
self.rawValue = rawValue
21+
}
22+
1823
/// Indicates the Relying Party is not interested in authenticator attestation.
19-
case none
20-
// case indirect
21-
// case direct
22-
// case enterprise
24+
public static let none: Self = "none"
25+
// public static let indirect: Self = "indirect"
26+
// public static let direct: Self = "direct"
27+
// public static let enterprise: Self = "enterprise"
2328
}

Sources/WebAuthn/Ceremonies/Registration/AttestationFormat.swift

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,17 @@
1111
//
1212
//===----------------------------------------------------------------------===//
1313

14-
public enum AttestationFormat: String, RawRepresentable, Equatable, Sendable {
15-
case packed
16-
case tpm
17-
case androidKey = "android-key"
18-
case androidSafetynet = "android-safetynet"
19-
case fidoU2F = "fido-u2f"
20-
case apple
21-
case none
14+
public struct AttestationFormat: UnreferencedStringEnumeration, Sendable {
15+
public var rawValue: String
16+
public init(_ rawValue: String) {
17+
self.rawValue = rawValue
18+
}
19+
20+
public static let packed: Self = "packed"
21+
public static let tpm: Self = "tpm"
22+
public static let androidKey: Self = "android-key"
23+
public static let androidSafetynet: Self = "android-safetynet"
24+
public static let fidoU2F: Self = "fido-u2f"
25+
public static let apple: Self = "apple"
26+
public static let none: Self = "none"
2227
}

Sources/WebAuthn/Ceremonies/Registration/AuthenticatorAttestationResponse.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ struct ParsedAuthenticatorAttestationResponse {
6464
throw WebAuthnError.invalidAuthData
6565
}
6666
guard let formatCBOR = decodedAttestationObject["fmt"],
67-
case let .utf8String(format) = formatCBOR,
68-
let attestationFormat = AttestationFormat(rawValue: format) else {
67+
case let .utf8String(format) = formatCBOR else {
6968
throw WebAuthnError.invalidFmt
7069
}
70+
let attestationFormat = AttestationFormat(format)
7171

7272
guard let attestationStatement = decodedAttestationObject["attStmt"] else {
7373
throw WebAuthnError.missingAttStmt

Sources/WebAuthn/Ceremonies/Shared/CollectedClientData.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,14 @@ public struct CollectedClientData: Codable, Hashable, Sendable {
2222
case originDoesNotMatch
2323
}
2424

25-
public enum CeremonyType: String, Codable, Sendable {
26-
case create = "webauthn.create"
27-
case assert = "webauthn.get"
25+
public struct CeremonyType: UnreferencedStringEnumeration, Sendable {
26+
public var rawValue: String
27+
public init(_ rawValue: String) {
28+
self.rawValue = rawValue
29+
}
30+
31+
public static let create: Self = "webauthn.create"
32+
public static let assert: Self = "webauthn.get"
2833
}
2934

3035
/// Contains the string "webauthn.create" when creating new credentials,

0 commit comments

Comments
 (0)