You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
/// Initialize a key-pair based authenticator with a globally unique ID representing your application.
31
44
/// - Note: To generate an AAGUID, run `% uuidgen` in your terminal. This value should generally not change across installations or versions of your app, and should be the same for every user.
32
45
/// - Parameter attestationGloballyUniqueID: The AAGUID associated with the authenticator.
@@ -48,7 +61,13 @@ public struct KeyPairAuthenticator: AuthenticatorProtocol, Sendable {
Copy file name to clipboardExpand all lines: Sources/WebAuthn/Authenticators/Protocol/AuthenticatorProtocol.swift
+130-1Lines changed: 130 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -61,6 +61,8 @@ public protocol AuthenticatorProtocol<CredentialSource> {
61
61
/// Make credentials for the specified registration request, returning the credential source that the caller should store for subsequent authentication.
62
62
///
63
63
/// - Important: Depending on the authenticator being used, the credential source may contain private keys, and must be stored sequirely, such as in the user's Keychain, or in a Hardware Security Module appropriate with the level of security you wish to secure your user's account with.
/// See [WebAuthn Level 3 Editor's Draft §5.1.3. Create a New Credential - PublicKeyCredential’s Create(origin, options, sameOriginWithAncestors) Method, Step 25.]( https://w3c.github.io/webauthn/#CreateCred-async-loop)
130
+
/// Step 1. This authenticator is now the candidate authenticator.
131
+
/// Step 2. If pkOptions.authenticatorSelection is present:
132
+
/// 1. If pkOptions.authenticatorSelection.authenticatorAttachment is present and its value is not equal to authenticator’s authenticator attachment modality, continue.
133
+
/// 2. If pkOptions.authenticatorSelection.residentKey
134
+
/// → is present and set to required
135
+
/// If the authenticator is not capable of storing a client-side discoverable public key credential source, continue.
136
+
/// → is present and set to preferred or discouraged
137
+
/// No effect.
138
+
/// → is not present
139
+
/// if pkOptions.authenticatorSelection.requireResidentKey is set to true and the authenticator is not capable of storing a client-side discoverable public key credential source, continue.
140
+
/// 6. If pkOptions.authenticatorSelection.userVerification is set to required and the authenticator is not capable of performing user verification, continue.
141
+
// Skip.
142
+
143
+
/// Step 3. Let requireResidentKey be the effective resident key requirement for credential creation, a Boolean value, as follows:
144
+
/// If pkOptions.authenticatorSelection.residentKey
145
+
/// → is present and set to required
146
+
/// Let requireResidentKey be true.
147
+
/// → is present and set to preferred
148
+
/// If the authenticator
149
+
/// → is capable of client-side credential storage modality
150
+
/// Let requireResidentKey be true.
151
+
/// → is not capable of client-side credential storage modality, or if the client cannot determine authenticator capability,
152
+
/// Let requireResidentKey be false.
153
+
/// → is present and set to discouraged
154
+
/// Let requireResidentKey be false.
155
+
/// → is not present
156
+
/// Let requireResidentKey be the value of pkOptions.authenticatorSelection.requireResidentKey.
157
+
letrequiresClientSideKeyStorage=false
158
+
159
+
/// Step 10. Let userVerification be the effective user verification requirement for credential creation, a Boolean value, as follows. If pkOptions.authenticatorSelection.userVerification
160
+
/// → is set to required
161
+
/// Let userVerification be true.
162
+
/// → is set to preferred
163
+
/// If the authenticator
164
+
/// → is capable of user verification
165
+
/// Let userVerification be true.
166
+
/// → is not capable of user verification
167
+
/// Let userVerification be false.
168
+
/// → is set to discouraged
169
+
/// Let userVerification be false.
170
+
letshouldPerformUserVerification=false
171
+
172
+
/// Step 16. Let enterpriseAttestationPossible be a Boolean value, as follows. If pkOptions.attestation
173
+
/// → is set to enterprise
174
+
/// Let enterpriseAttestationPossible be true if the user agent wishes to support enterprise attestation for pkOptions.rp.id (see Step 8, above). Otherwise false.
175
+
/// → otherwise
176
+
/// Let enterpriseAttestationPossible be false.
177
+
letisEnterpriseAttestationPossible=false
178
+
179
+
/// Step 19. Let attestationFormats be a list of strings, initialized to the value of pkOptions.attestationFormats.
180
+
/// Step 20. If pkOptions.attestation
181
+
/// → is set to none
182
+
/// Set attestationFormats be the single-element list containing the string “none”
183
+
guard case .none = registration.options.attestation else{throwWebAuthnError.attestationFormatNotSupported }
184
+
185
+
/// Step 22. Let excludeCredentialDescriptorList be a new list.
186
+
/// Step 23. For each credential descriptor C in pkOptions.excludeCredentials:
187
+
/// 1. If C.transports is not empty, and authenticator is connected over a transport not mentioned in C.transports, the client MAY continue.
188
+
/// 2. Otherwise, Append C to excludeCredentialDescriptorList.
189
+
/// 3. Invoke the authenticatorMakeCredential operation on authenticator with clientDataHash, pkOptions.rp, pkOptions.user, requireResidentKey, userVerification, credTypesAndPubKeyAlgs, excludeCredentialDescriptorList, enterpriseAttestationPossible, attestationFormats, and authenticatorExtensions as parameters.
190
+
/// Step 24. Append authenticator to issuedRequests.
191
+
192
+
/// See [WebAuthn Level 3 Editor's Draft §6.3.2. The authenticatorMakeCredential Operation](https://w3c.github.io/webauthn/#sctn-op-make-cred)
193
+
/// Step 1. Check if all the supplied parameters are syntactically well-formed and of the correct length. If not, return an error code equivalent to "UnknownError" and terminate the operation.
194
+
/// Step 2. Check if at least one of the specified combinations of PublicKeyCredentialType and cryptographic parameters in credTypesAndPubKeyAlgs is supported. If not, return an error code equivalent to "NotSupportedError" and terminate the operation.
/// Step 3. For each descriptor of excludeCredentialDescriptorList:
199
+
/// 1. If looking up descriptor.id in this authenticator returns non-null, and the returned item's RP ID and type match rpEntity.id and excludeCredentialDescriptorList.type respectively, then collect an authorization gesture confirming user consent for creating a new credential. The authorization gesture MUST include a test of user presence. If the user
200
+
/// → confirms consent to create a new credential
201
+
/// return an error code equivalent to "InvalidStateError" and terminate the operation.
202
+
/// → does not consent to create a new credential
203
+
/// return an error code equivalent to "NotAllowedError" and terminate the operation.
204
+
/// NOTE: The purpose of this authorization gesture is not to proceed with creating a credential, but for privacy reasons to authorize disclosure of the fact that descriptor.id is bound to this authenticator. If the user consents, the client and Relying Party can detect this and guide the user to use a different authenticator. If the user does not consent, the authenticator does not reveal that descriptor.id is bound to it, and responds as if the user simply declined consent to create a credential.
205
+
/// Step 4. If requireResidentKey is true and the authenticator cannot store a client-side discoverable public key credential source, return an error code equivalent to "ConstraintError" and terminate the operation.
206
+
/// Step 5. If requireUserVerification is true and the authenticator cannot perform user verification, return an error code equivalent to "ConstraintError" and terminate the operation.
207
+
/// Step 6. Collect an authorization gesture confirming user consent for creating a new credential. The prompt for the authorization gesture is shown by the authenticator if it has its own output capability, or by the user agent otherwise. The prompt SHOULD display rpEntity.id, rpEntity.name, userEntity.name and userEntity.displayName, if possible.
208
+
/// → If requireUserVerification is true, the authorization gesture MUST include user verification.
209
+
/// → If requireUserPresence is true, the authorization gesture MUST include a test of user presence.
210
+
/// → If the user does not consent or if user verification fails, return an error code equivalent to "NotAllowedError" and terminate the operation.
211
+
/// Step 7. Once the authorization gesture has been completed and user consent has been obtained, generate a new credential object:
212
+
/// 1. Let (publicKey, privateKey) be a new pair of cryptographic keys using the combination of PublicKeyCredentialType and cryptographic parameters represented by the first item in credTypesAndPubKeyAlgs that is supported by this authenticator.
213
+
/// 2. Let userHandle be userEntity.id.
214
+
/// 3. Let credentialSource be a new public key credential source with the fields:
215
+
/// type
216
+
/// public-key.
217
+
/// privateKey
218
+
/// privateKey
219
+
/// rpId
220
+
/// rpEntity.id
221
+
/// userHandle
222
+
/// userHandle
223
+
/// otherUI
224
+
/// Any other information the authenticator chooses to include.
225
+
/// 4. If requireResidentKey is true or the authenticator chooses to create a client-side discoverable public key credential source:
226
+
/// 1. Let credentialId be a new credential id.
227
+
/// 2. Set credentialSource.id to credentialId.
228
+
/// 3. Let credentials be this authenticator’s credentials map.
229
+
/// 4. Set credentials[(rpEntity.id, userHandle)] to credentialSource.
230
+
/// 5. Otherwise:
231
+
/// Let credentialId be the result of serializing and encrypting credentialSource so that only this authenticator can decrypt it.
/// Step 8. If any error occurred while creating the new credential object, return an error code equivalent to "UnknownError" and terminate the operation.
238
+
/// Step 9. Let processedExtensions be the result of authenticator extension processing for each supported extension identifier → authenticator extension input in extensions.
239
+
/// Step 10. If the authenticator:
240
+
/// → is a U2F device
241
+
/// let the signature counter value for the new credential be zero. (U2F devices may support signature counters but do not return a counter when making a credential. See [FIDO-U2F-Message-Formats].)
242
+
/// → supports a global signature counter
243
+
/// Use the global signature counter's actual value when generating authenticator data.
244
+
/// → supports a per credential signature counter
245
+
/// allocate the counter, associate it with the new credential, and initialize the counter value as zero.
246
+
/// → does not support a signature counter
247
+
/// let the signature counter value for the new credential be constant at zero.
248
+
/// Step 15. Let attestedCredentialData be the attested credential data byte array including the credentialId and publicKey.
249
+
/// Step 16. Let attestationFormat be the first supported attestation statement format identifier from attestationFormats, taking into account enterpriseAttestationPossible. If attestationFormats contains no supported value, then let attestationFormat be the attestation statement format identifier most preferred by this authenticator.
250
+
/// Step 17. Let authenticatorData be the byte array specified in § 6.1 Authenticator Data, including attestedCredentialData as the attestedCredentialData and processedExtensions, if any, as the extensions.
251
+
/// Step 18. Create an attestation object for the new credential using the procedure specified in § 6.5.4 Generating an Attestation Object, the attestation statement format attestationFormat, and the values authenticatorData and hash, as well as taking into account the value of enterpriseAttestationPossible. For more details on attestation, see § 6.5 Attestation.
252
+
/// On successful completion of this operation, the authenticator returns the attestation object to the client.
0 commit comments