Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ public struct AttestationObject: Sendable {
let format: AttestationFormat
let attestationStatement: CBOR

/// The Authenticator Attestation Globally Unique Identifier (AAGUID) from the attestation object.
/// Returns nil if attested credential data is not present.
/// - SeeAlso: [WebAuthn Level 3 Editor's Draft §6.5.1. Attested Credential Data](https://w3c.github.io/webauthn/#sctn-attested-credential-data)
public var aaguid: AAGUID? {
authenticatorData.attestedData?.authenticatorAttestationGUID
}

func verify(
relyingPartyID: String,
verificationRequired: Bool,
Expand Down
7 changes: 7 additions & 0 deletions Sources/WebAuthn/Ceremonies/Registration/Credential.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,11 @@ public struct Credential: Sendable {
public let attestationObject: AttestationObject

public let attestationClientDataJSON: CollectedClientData

/// The Authenticator Attestation Globally Unique Identifier (AAGUID) from the attestation object.
/// Returns nil if attested credential data is not present.
/// - SeeAlso: [WebAuthn Level 3 Editor's Draft §6.5.1. Attested Credential Data](https://w3c.github.io/webauthn/#sctn-attested-credential-data)
public var aaguid: AAGUID? {
attestationObject.aaguid
}
}
65 changes: 65 additions & 0 deletions Tests/WebAuthnTests/WebAuthnManagerRegistrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,71 @@ struct WebAuthnManagerRegistrationTests {
#expect(credential.publicKey == credentialPublicKey)
}

@Test(arguments: [
TestKeyConfiguration.ecdsa,
TestKeyConfiguration.rsa,
])
func credentialAAGUIDAccessorReturnsCorrectValue(keyConfiguration: TestKeyConfiguration) async throws {
let testAAGUID = AAGUID(uuidString: "dd4ec289-e01d-41c9-bb89-70fa845d4bf2")!
let credentialID: [UInt8] = [0, 1, 0, 1, 0, 1]
let credentialPublicKey: [UInt8] = keyConfiguration.credentialPublicKey
let authData = keyConfiguration.authDataBuilder
.attestedCredData(
authenticatorAttestationGUID: testAAGUID,
credentialPublicKey: credentialPublicKey
)
.noExtensionData()
let attestationObject = keyConfiguration.attestationObjectBuilder
.authData(authData)
.build()
.cborEncoded

let credential = try await finishRegistration(
rawID: credentialID,
attestationObject: attestationObject
)

// Test that credential.aaguid returns the correct AAGUID
#expect(credential.aaguid != nil)
#expect(credential.aaguid?.id == testAAGUID.id)
#expect(credential.aaguid?.bytes == testAAGUID.bytes)

// Test that credential.attestationObject.aaguid returns the same value
#expect(credential.attestationObject.aaguid != nil)
#expect(credential.attestationObject.aaguid?.id == testAAGUID.id)
#expect(credential.attestationObject.aaguid?.bytes == testAAGUID.bytes)

// Verify they return the same value
#expect(credential.aaguid == credential.attestationObject.aaguid)
}

@Test(arguments: [
TestKeyConfiguration.ecdsa,
TestKeyConfiguration.rsa,
])
func credentialAAGUIDAccessorReturnsAnonymousByDefault(keyConfiguration: TestKeyConfiguration) async throws {
// When no AAGUID is specified, it defaults to .anonymous
let credentialID: [UInt8] = [0, 1, 0, 1, 0, 1]
let credentialPublicKey: [UInt8] = keyConfiguration.credentialPublicKey
let authData = keyConfiguration.authDataBuilder
.attestedCredData(credentialPublicKey: credentialPublicKey) // Uses .anonymous by default
.noExtensionData()
let attestationObject = keyConfiguration.attestationObjectBuilder
.authData(authData)
.build()
.cborEncoded

let credential = try await finishRegistration(
rawID: credentialID,
attestationObject: attestationObject
)

// Test that credential.aaguid returns the anonymous AAGUID
#expect(credential.aaguid != nil)
#expect(credential.aaguid == .anonymous)
#expect(credential.aaguid?.bytes == Array(repeating: 0, count: 16))
}

@Test
func finishRegistrationFuzzying() async throws {
for _ in 1...50 {
Expand Down