0

I have an Angular 11 (Frontend) and Kotlin (Backend) Project where I have implemented a WebAuthn Login.

The registration of works straightforward, I get a challenge from the (WebAuthn4J) Backend and create the credentials with this:

...

const credentialOptions: CredentialCreationOptions = {
   publicKey: {
     attestation: 'direct',
     user: {
       name: 'UsernameXYZ',
       displayName: 'UsernameXYZ',
       id: decodeUrlSafeB64(btoa('<uuid-from-db>'))
     },
     rp: {
       id: 'my-company.com',
       name: 'My Company'
     },
     challenge: challenge, // Challenge from Backend as B64
     pubKeyCredParams: [
       {
         type: 'public-key',
         alg: -257 // RS256
       },
       {
         type: 'public-key',
         alg: -7 // ES256
       }
     ],
     authenticatorSelection: undefined // All options possible
   }
 };
 const credentials: Credential = await navigator.credentials.create(credentialOptions);

 ...

Now, I can login at my-company.com with no problems. But I CANNOT login at other.my-company.com and I do not understand why. The WebAuthn dialogue (from Win10) says "Authenticator not recognized" (not exactly, as the message is german).

All I do is hand valid credentialIds (which I receive from the backend) to the navigator.

...

const credIds: Array<PublicKeyCredentialDescriptor> = [];
credentialIds.forEach((credentialId) => {
  credIds.push({
    type: 'public-key',
    id: decodeUrlSafeB64(credentialId)
  });
});

// my-company.com --> WebAuthn Dialog as expected
// other.my-company.com --> WebAuthnDialog does not recognize key
navigator.credentials.get({
  publicKey: {
    challenge: challenge, // Challenge for Login from Backend
    allowCredentials: credIds,
    userVerification: 'preferred'
  }
});

...

However, when I make the registration from other.my-company.com with:

rp: {
  id: 'other.my-company.com',
  name: 'My Company'
},

I can now login from my-company.com AND other.my-company.com. This would work for the setup I have now, but when I ever plan to extend my project and make a login at another.my-company.com this won't work.

I read the spec, and it is very unspecific about this setup, though I think its fairly common: https://www.w3.org/TR/webauthn/#relying-party-identifier

In a similar SO question, it said that the setup I have here should work (without any source though): WebAuthn across multiple subdomain

I also followed this when implementing the logic: https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API

I am out of ideas on where to research. The WebAuthn4J implementation I use (https://github.com/webauthn4j/webauthn4j) works just fine, as proven that I can login in the two settings from above.

The only other option I came up with is to seperate the whole login/registration process from the rest of the app, so that every login gets redirected to sso.my-company.com, logs in with WebAuthn, gets a JWT and redirects back to the original app. But is that really the only option I have? It seems so overkill for what I want to do, namely "Register a domain and allow all subdomains."

Any hint (even only pointing to othe specs as the one I linked)

PrimuS
  • 2,505
  • 6
  • 33
  • 66

1 Answers1

3

You need to set the RP ID during assertion to the same RP ID used during creation. If you leave it unset, it will default to the current origin and include the subdomain so it will no longer match.

Nina Satragno
  • 561
  • 3
  • 8