rwinch / spring-security-webauthn

17 stars 7 forks source link

Should classes in the package org.springframework.security.web.webauthn depend on org.springframework.security.webauthn? #18

Open WakaWakaMan opened 1 month ago

WakaWakaMan commented 1 month ago

Hello, thanks for the great WebAuthn integration!

I am wondering if we need dependencies on org.springframework.security.webauthn in various repositories/filters like WebAuthnAuthenticationFilter, PublicKeyCredentialRequestOptionsFilter, etc.

Perhaps, if we abstract the typing of incoming/outgoing WebAuthn data or simply leave them as raw JSON strings, it might make integration with various WebAuthn providers easier.

For example WebAuthnAuthenticationRequestToken.webAuthnRequest could be a raw json string.

As a result, this part...

        ResolvableType resolvableType = ResolvableType.forClassWithGenerics(PublicKeyCredential.class, AuthenticatorAssertionResponse.class);
        PublicKeyCredential<AuthenticatorAssertionResponse> publicKeyCredential = null;
        try {
            publicKeyCredential = (PublicKeyCredential<AuthenticatorAssertionResponse>) this.converter.read(resolvableType.getType(), getClass(), httpRequest);
        }
        catch (Exception e) {
            throw new BadCredentialsException("Unable to authenticate the PublicKeyCredential", e);
        }
        PublicKeyCredentialRequestOptions requestOptions = this.requestOptionsRepository.load(request);
        if (requestOptions == null) {
            throw new BadCredentialsException("Unable to authenticate the PublicKeyCredential. No PublicKeyCredentialRequestOptions found.");
        }

can be moved to AuthnticationProvider.

Best regards, Dan!

rwinch commented 4 days ago

Thanks for your feedback. I understand your concern around deserializing to Spring Security types and then having to convert them to the types of the depending library. It is a lot of work.

However, I'm not keen on using JSON in the data objects because I do not want to tie objects that are stored in a database to the format that they are transmitted to the server.

It's important to note that there is no specification for how or what format the data is transmitted to the server. Some providers use JSON & others use form parameters. The spec is continuing to evolve including in how to serialize/deserialize the response from the server. For example, L3 introduced built in methods for (de)serialization but the spec is not finalized and the methods are not supported in all browsers yet. This is not necessarily the end of how the request/response will be made. There are discussions of how to support WebAuthn without JavasScript which might mean a new way of transporting the data.

The types may look different over other transports as well. I can imagine transports for WebSocket and GraphQL as well.

In short, the data types that we use in Spring Security should not mirror the format they are transported. Instead, they should mirror the required types in the specification. The data that is submitted to the server should be deserialized and when returning to the client it should be serialized. This ensures that we code plug in different (de)serialization strategies.