diff --git a/Sources/WebAuthn/Ceremonies/Registration/PublicKeyCredentialCreationOptions.swift b/Sources/WebAuthn/Ceremonies/Registration/PublicKeyCredentialCreationOptions.swift index 9fdfabf..9930999 100644 --- a/Sources/WebAuthn/Ceremonies/Registration/PublicKeyCredentialCreationOptions.swift +++ b/Sources/WebAuthn/Ceremonies/Registration/PublicKeyCredentialCreationOptions.swift @@ -20,6 +20,7 @@ import Foundation /// /// - SeeAlso: https://www.w3.org/TR/webauthn-2/#dictionary-makecredentialoptions public struct PublicKeyCredentialCreationOptions: Encodable, Sendable { + /// A byte array randomly generated by the Relying Party. Should be at least 16 bytes long to ensure sufficient /// entropy. /// @@ -39,13 +40,27 @@ public struct PublicKeyCredentialCreationOptions: Encodable, Sendable { /// A time, in seconds, that the caller is willing to wait for the call to complete. This is treated as a /// hint, and may be overridden by the client. - /// - /// - Note: When encoded, this value is represented in milleseconds as a ``UInt32``. public let timeout: Duration? /// Sets the Relying Party's preference for attestation conveyance. At the time of writing only `none` is /// supported. public let attestation: AttestationConveyancePreference + + /// Use this enumeration to communicate hints to the user-agent about how a request may be best completed. These hints are not requirements, and do not bind the user-agent, but may guide it in providing the best experience by using contextual information that the Relying Party has about the request. + /// https://www.w3.org/TR/webauthn-3/#enum-hints + let hints: [Hint] + + /// This client registration extension facilitates reporting certain credential properties known by the client to the requesting WebAuthn Relying Party upon creation of a public key credential source as a result of a registration ceremony. + /// https://www.w3.org/TR/webauthn-2/#sctn-extensions-inputs-outputs + let extensions: Extensions + + /// This member is intended for use by Relying Parties that wish to limit the creation of multiple credentials for the same account on a single authenticator + /// https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialcreationoptions-excludecredentials + let excludeCredentials: [PublicKeyCredentialDescriptor] + + /// This member is intended for use by Relying Parties that wish to select the appropriate authenticators to participate in the create() operation. + /// https://www.w3.org/TR/webauthn-3/#dom-publickeycredentialcreationoptions-authenticatorselection + let authenticatorSelection: AuthenticatorSelectionCriteria public func encode(to encoder: any Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) @@ -56,6 +71,10 @@ public struct PublicKeyCredentialCreationOptions: Encodable, Sendable { try container.encode(publicKeyCredentialParameters, forKey: .publicKeyCredentialParameters) try container.encodeIfPresent(timeout?.milliseconds, forKey: .timeout) try container.encode(attestation, forKey: .attestation) + try container.encode(authenticatorSelection, forKey: .authenticatorSelection) + try container.encode(hints, forKey: .hints) + try container.encode(extensions, forKey: .extensions) + try container.encode(excludeCredentials, forKey: .excludeCredentials) } private enum CodingKeys: String, CodingKey { @@ -65,6 +84,10 @@ public struct PublicKeyCredentialCreationOptions: Encodable, Sendable { case publicKeyCredentialParameters = "pubKeyCredParams" case timeout case attestation + case authenticatorSelection + case hints + case extensions + case excludeCredentials } } @@ -156,3 +179,60 @@ public struct PublicKeyCredentialUserEntity: Encodable, Sendable { case displayName } } + +public struct Hint: UnreferencedStringEnumeration, Sendable { + public var rawValue: String + public init(_ rawValue: String) { + self.rawValue = rawValue + } + + /// Indicates that the Relying Party believes that users will satisfy this request with a platform authenticator attached to the client device. + public static let clientDevice: Self = "client-device" + + /// Indicates that the Relying Party believes that users will satisfy this request with a physical security key + public static let securityKey: Self = "security-key" + + /// Indicates that the Relying Party believes that users will satisfy this request with general-purpose authenticators such as smartphones. + public static let hybrid: Self = "hybrid" +} + + +struct Extensions: Encodable { + /// Indicate that this extension is requested by the Relying Party. + /// https://www.w3.org/TR/webauthn-3/#sctn-authenticator-credential-properties-extension + let credProps: Bool +} + +struct AuthenticatorSelectionCriteria: Encodable { + /// Specifies the extent to which the Relying Party desires to create a client-side discoverable credential. + /// https://www.w3.org/TR/webauthn-3/#dom-authenticatorselectioncriteria-residentkey + let residentKey: ResidentKeyRequirement + + /// Relying Parties SHOULD set this to true if, and only if, `residentKey` is set to `required`. + /// https://www.w3.org/TR/webauthn-3/#dom-authenticatorselectioncriteria-requireresidentkey + let requireResidentKey: Bool + + /// This member specifies the Relying Party's requirements regarding user verification for the create() operation. + /// https://www.w3.org/TR/webauthn-3/#dom-authenticatorselectioncriteria-userverification + let userVerification: UserVerificationRequirement +} + + +public struct ResidentKeyRequirement: UnreferencedStringEnumeration, Sendable { + public var rawValue: String + public init(_ rawValue: String) { + self.rawValue = rawValue + } + + /// The Relying Party requires a client-side discoverable credential. + /// https://www.w3.org/TR/webauthn-3/#dom-residentkeyrequirement-required + public static let required: Self = "required" + + /// The Relying Party strongly prefers creating a client-side discoverable credential, but will accept a server-side credential. + /// https://www.w3.org/TR/webauthn-3/#dom-residentkeyrequirement-preferred + public static let preferred: Self = "preferred" + + /// The Relying Party prefers creating a server-side credential, but will accept a client-side discoverable credential. + /// https://www.w3.org/TR/webauthn-3/#dom-residentkeyrequirement-discouraged + public static let discouraged: Self = "discouraged" +} diff --git a/Sources/WebAuthn/WebAuthnManager.swift b/Sources/WebAuthn/WebAuthnManager.swift index 299089b..512feb8 100644 --- a/Sources/WebAuthn/WebAuthnManager.swift +++ b/Sources/WebAuthn/WebAuthnManager.swift @@ -69,7 +69,13 @@ public struct WebAuthnManager: Sendable { relyingParty: .init(id: configuration.relyingPartyID, name: configuration.relyingPartyName), publicKeyCredentialParameters: publicKeyCredentialParameters, timeout: timeout, - attestation: attestation + attestation: attestation, + hints: [], + extensions: .init(credProps: true), + excludeCredentials: [], + authenticatorSelection: .init(residentKey: .preferred, + requireResidentKey: false, + userVerification: .preferred) ) }