MasterKale / SimpleWebAuthn

WebAuthn, Simplified. A collection of TypeScript-first libraries for simpler WebAuthn integration. Supports modern browsers, Node, Deno, and more.
https://simplewebauthn.dev
MIT License
1.62k stars 137 forks source link

The default MDS could not be parsed and verified as of June 3, 2023 #388

Closed WorldThirteen closed 1 year ago

WorldThirteen commented 1 year ago

Describe the issue

As of June 3, 2023, MetadataService could not initialize metadata from the default FIDO Alliance MDS ('https://mds.fidoalliance.org/).

Reproduction Steps

  1. On an empty nodejs env
  2. Initiate MetadataService with MetadataService.initialize().
  3. After the promise is resolved, try to get a statement for a well-known aaguid that exists in https://mds.fidoalliance.org with MetadataService.getStatement('ee882879-721c-4913-9775-3dfcce97072a')
  4. Get an undefined value.

Expected behavior

...

  1. Get a statement object about existing aaguid.

Code Samples + WebAuthn Options and Responses

Logs of the MetadataService are:

  SimpleWebAuthn:MetadataService MetadataService is REFRESHING +0ms
  SimpleWebAuthn:MetadataService Could not download BLOB from https://mds.fidoalliance.org/: Error: BLOB certificate path could not be validated: Too big integer
    at BaseMetadataService.downloadBlob (REDACTED/SimpleWebAuthn/packages/server/src/services/metadataService.ts:233:13)
    at BaseMetadataService.initialize (REDACTED/SimpleWebAuthn/packages/server/src/services/metadataService.ts:112:11)
    at Object.<anonymous> (REDACTED/SimpleWebAuthn/packages/server/src/services/metadataService.test.ts:14:5) +1s
  SimpleWebAuthn:MetadataService Cached 0 statements from 0 metadata server(s) +8ms
  SimpleWebAuthn:MetadataService MetadataService is READY +0ms

Here is a test code that might be helpful for reproduction. The fetch was not mocked intentionally to receive actual Metadata BLOB.

metadataService.test.ts ```ts import fetch from 'cross-fetch'; import { MetadataService, BaseMetadataService } from './metadataService'; describe('Get known aaguid metadata statement for live metadata BLOB', () => { test('should return actual statement for a known aagiud', async () => { const service = new BaseMetadataService(); await service.initialize(); const statement = await service.getStatement('ee882879-721c-4913-9775-3dfcce97072a'); console.log('statement', statement); expect(statement).toBeDefined(); }); }); ```

Dependencies

SimpleWebAuthn Libraries

$ npm list --depth=0 | grep @simplewebauthn
├── @simplewebauthn/server@7.2.0
# ...

Additional context

  1. The investigation showed that certificate normalization missed the case when PEM includes extra whitespaces, which was the case for one of the certificates in the path (notice the leading whitespace chars at the beginning of each line:

    -----BEGIN CERTIFICATE-----
    MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
    A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
    Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
    MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
    A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
    hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
    RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
    gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
    KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
    QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
    XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
    DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
    LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
    RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
    jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
    6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
    mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
    Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
    WD9f
    -----END CERTIFICATE-----
  2. After fixing this locally by modifying convertPEMToBytes helper, I found another error:

    SimpleWebAuthn:MetadataService MetadataService is REFRESHING +0ms
    SimpleWebAuthn:MetadataService Could not download BLOB from https://mds.fidoalliance.org/: Error: JWT verification with public key of kty 3 is not supported by this method
    at verifyJWT (REDACTED/SimpleWebAuthn/packages/server/src/metadata/verifyJWT.ts:31:9)
    at BaseMetadataService.downloadBlob (REDACTED/SimpleWebAuthn/packages/server/src/services/metadataService.ts:238:37)
    at BaseMetadataService.initialize (REDACTED/SimpleWebAuthn/packages/server/src/services/metadataService.ts:112:11)
    at Object.<anonymous> (REDACTED/SimpleWebAuthn/packages/server/src/services/metadataService.test.ts:13:5) +2s
    SimpleWebAuthn:MetadataService Cached 0 statements from 0 metadata server(s) +7ms
    SimpleWebAuthn:MetadataService MetadataService is READY +0ms

It seems that the official FIDO MDN now using RSA instead of the expected EC2.

  1. After locally modifying verifyJWT helper to support RSA using isoCrypto/verifyRSA.ts, metadata was successfully validated, and metadata for sample AAGUID was obtained.

These modifications could be looked at here: https://github.com/MasterKale/SimpleWebAuthn/compare/master...WorldThirteen:SimpleWebAuthn:w13-metadata-service-june-fix?expand=1


@MasterKale, would you like to receive a PR with the fixes I mentioned in the "Additional context" section?

MasterKale commented 1 year ago

@WorldThirteen thank you for the thorough breakdown of where exactly this was failing! I've published a fix for this as @simplewebauthn/server@7.3.0, which is available now. Please give it a try and report back if it still doesn't fix the issue.