Skip to content

Commit 2b1fe1a

Browse files
Updated AuthenticatorProtocol to include essential members for registration and authentication
1 parent bab5128 commit 2b1fe1a

File tree

3 files changed

+110
-5
lines changed

3 files changed

+110
-5
lines changed

Sources/WebAuthn/Authenticators/Protocol/AuthenticatorCredentialSourceProtocol.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,19 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
import Foundation
16+
import Crypto
17+
1518
public protocol AuthenticatorCredentialSourceProtocol: Sendable, Identifiable where ID: AuthenticatorCredentialSourceIdentifier {
1619

1720
var id: ID { get }
21+
var credentialParameters: PublicKeyCredentialParameters { get }
22+
var relyingPartyID: PublicKeyCredentialRelyingPartyEntity.ID { get }
23+
var userHandle: PublicKeyCredentialUserEntity.ID { get }
24+
var counter: UInt32 { get }
1825

19-
init(
20-
id: ID
21-
) throws
26+
func signAssertion(
27+
authenticatorData: [UInt8],
28+
clientDataHash: SHA256Digest
29+
) async throws -> [UInt8]
2230
}

Sources/WebAuthn/Authenticators/Protocol/AuthenticatorProtocol.swift

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,103 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
import Crypto
16+
import SwiftCBOR
17+
1518
public protocol AuthenticatorProtocol<CredentialSource> {
1619
associatedtype CredentialSource: AuthenticatorCredentialSourceProtocol
20+
21+
var attestationGloballyUniqueID: AAGUID { get }
22+
var attachmentModality: AuthenticatorAttachment { get }
23+
var supportedPublicKeyCredentialParameters: Set<PublicKeyCredentialParameters> { get }
24+
var canPerformUserVerification: Bool { get }
25+
var canStoreCredentialSourceClientSide: Bool { get }
26+
27+
/// Generate a credential source for this authenticator.
28+
/// - Parameters:
29+
/// - requiresClientSideKeyStorage: `true` if the relying party requires that the credential ID is stored client size, as it won't be provided during authentication requests.
30+
/// - credentialParameters: The chosen credential parameters.
31+
/// - relyingPartyID: The ID of the relying party the credential is being generated for.
32+
/// - userHandle: The user handle the credential is being generated for.
33+
/// - Returns: A new credential source to be returned to the caller upon successful registration.
34+
func generateCredentialSource(
35+
requiresClientSideKeyStorage: Bool,
36+
credentialParameters: PublicKeyCredentialParameters,
37+
relyingPartyID: PublicKeyCredentialRelyingPartyEntity.ID,
38+
userHandle: PublicKeyCredentialUserEntity.ID
39+
) async throws -> CredentialSource
40+
41+
/// The preferred attestation format for the authenticator, optionally taking into account the provided list of formats the relying party prefers.
42+
///
43+
/// The default implementation returns ``AttestationFormat/none``.
44+
///
45+
/// - Parameter attestationFormats: A list of attestation formats the relying party prefers.
46+
/// - Returns: The attestation format that will be used to sign an attestation statement.
47+
func preferredAttestationFormat(from attestationFormats: [AttestationFormat]) -> AttestationFormat
48+
49+
/// Sign an attestation statement for the provided authenticator data and client data using the specified format.
50+
/// - Parameters:
51+
/// - attestationFormat: The attestation format to sign with.
52+
/// - authenticatorData: The authenticator data to be signed.
53+
/// - clientDataHash: The client data to be signed.
54+
/// - Returns: A signiture in the specified format.
55+
func signAttestationStatement(
56+
attestationFormat: AttestationFormat,
57+
authenticatorData: [UInt8],
58+
clientDataHash: SHA256.Digest
59+
) async throws -> CBOR
60+
61+
/// Filter the provided credential descriptors to determine which, if any, should be handled by this authenticator.
62+
///
63+
/// This method should execute a client platform-specific procedure to determine which, if any, public key credentials described by `pkOptions.allowCredentials` are bound to this authenticator, by matching with `rpId`, `pkOptions.allowCredentials.id`, and `pkOptions.allowCredentials.type`
64+
///
65+
/// The default implementation returns the list as is.
66+
/// - Parameters:
67+
/// - credentialDescriptors: A list of credentials that will be used assert authorization against.
68+
/// - relyingPartyID: The relying party ID the credentials belong to.
69+
/// - Returns: A filtered list of credentials that are suitable for this authenticator.
70+
func filteredCredentialDescriptors(
71+
credentialDescriptors: [PublicKeyCredentialDescriptor],
72+
relyingPartyID: PublicKeyCredentialRelyingPartyEntity.ID
73+
) -> [PublicKeyCredentialDescriptor]
74+
75+
/// Collect an authorization gesture from the user for one of the specified credential sources, making sure to increment the counter for the credential source if relevant.
76+
/// - Parameters:
77+
/// - requiresUserVerification: The user is required to verify that the credential should be used to assert authorization. If the user cannot perform this task, this method should throw an error.
78+
/// - requiresUserPresence: The user is required to be present in order for authorization to be attempted. ie. authorization should not be done in the background without the user's knowledge while they are away from this device.
79+
/// - credentialOptions: A list of available credentials to verify against.
80+
/// - Returns: The chosen credential to use for authorization.
81+
func collectAuthorizationGesture(
82+
requiresUserVerification: Bool,
83+
requiresUserPresence: Bool,
84+
credentialOptions: [CredentialSource]
85+
) async throws -> CredentialSource
86+
}
87+
88+
// MARK: - Default Implementations
89+
90+
extension AuthenticatorProtocol {
91+
public func preferredAttestationFormat(
92+
from attestationFormats: [AttestationFormat]
93+
) -> AttestationFormat {
94+
.none
95+
}
96+
97+
public func signAttestationStatement(
98+
attestationFormat: AttestationFormat,
99+
authenticatorData: [UInt8],
100+
clientDataHash: SHA256.Digest
101+
) async throws -> CBOR {
102+
guard attestationFormat == .none
103+
else { throw WebAuthnError.attestationFormatNotSupported }
104+
105+
return [:]
106+
}
107+
108+
public func filteredCredentialDescriptors(
109+
credentialDescriptors: [PublicKeyCredentialDescriptor],
110+
relyingPartyID: PublicKeyCredentialRelyingPartyEntity.ID
111+
) -> [PublicKeyCredentialDescriptor] {
112+
return credentialDescriptors
113+
}
17114
}

Sources/WebAuthn/Ceremonies/Registration/PublicKeyCredentialCreationOptions.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ extension Set where Element == PublicKeyCredentialParameters {
111111
/// From §5.4.2 (https://www.w3.org/TR/webauthn/#sctn-rp-credential-params).
112112
/// The PublicKeyCredentialRelyingPartyEntity dictionary is used to supply additional Relying Party attributes when
113113
/// creating a new credential.
114-
public struct PublicKeyCredentialRelyingPartyEntity: Encodable, Sendable {
114+
public struct PublicKeyCredentialRelyingPartyEntity: Identifiable, Encodable, Sendable {
115115
/// A unique identifier for the Relying Party entity.
116116
public let id: String
117117

@@ -126,7 +126,7 @@ public struct PublicKeyCredentialRelyingPartyEntity: Encodable, Sendable {
126126
/// creating a new credential.
127127
///
128128
/// When encoding using `Encodable`, `id` is base64url encoded.
129-
public struct PublicKeyCredentialUserEntity: Encodable, Sendable {
129+
public struct PublicKeyCredentialUserEntity: Identifiable, Encodable, Sendable {
130130
/// Generated by the Relying Party, unique to the user account, and must not contain personally identifying
131131
/// information about the user.
132132
///

0 commit comments

Comments
 (0)