Skip to content

Passkey Endpoints do not Honor .permitAll() #16070

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Jyosua opened this issue Nov 12, 2024 · 5 comments
Open

Passkey Endpoints do not Honor .permitAll() #16070

Jyosua opened this issue Nov 12, 2024 · 5 comments
Assignees
Labels
in: web An issue in web modules (web, webmvc) status: feedback-provided Feedback has been provided type: bug A general bug

Comments

@Jyosua
Copy link

Jyosua commented Nov 12, 2024

Describe the bug
The auth/z check on this line in the filter implementation for registering passkey credentials seems to prevent access to the webauthn endpoints even if .anyRequest().permitAll() is used.

Note that I'm using the RC version of Spring Security 6.4.0.

To Reproduce

  1. Add a Security Configuration using the following implementation:
@Configuration
class SecurityConfig {

    @Bean
    fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
        http
            .webAuthn{ it
                    .rpName("Example")
                    .rpId("example.localhost")
                    .allowedOrigins("https://example.localhost")
            }
            .authorizeRequests { it
                    .anyRequest()
                    .permitAll()
            }
            .csrf { it.disable() }
            
        return http.build()
    }
}
  1. Try to POST to /webauthn/register/options

Expected behavior
The request would return a 200 with the Registration Options.

@Jyosua Jyosua added status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Nov 12, 2024
@Jyosua Jyosua changed the title Passkey Endpoints do not Honor .permitAll(). Passkey Endpoints do not Honor .permitAll() Nov 12, 2024
@sjohnr sjohnr added the in: web An issue in web modules (web, webmvc) label Nov 14, 2024
@rwinch
Copy link
Member

rwinch commented Dec 11, 2024

@Jyosua Thanks for reaching out. You are right that the registration endpoint does not honor the authorizeRequests DSL entries. Can you explain what you are trying to do and why? I ask because we obviously cannot allow registering a passkey to an anonymous user (if we did when we authenticated with that passkey who would we be authenticated as?).

@rwinch rwinch added status: waiting-for-feedback We need additional information before we can continue and removed status: waiting-for-triage An issue we've not yet triaged labels Dec 11, 2024
@Jyosua
Copy link
Author

Jyosua commented Dec 17, 2024

@rwinch The way you phrased that question might actually have cleared up some confusion I had when I was first trying to utilize the passkey feature. 😅

It's been quite a bit since I was working on the repository where I was using this so I've forgotten the particulars, but I think the gist of the use case was that we were just trying to test the flow of registering and using passkeys at all irrespective of the user. I think in order to do this we ended up being forced to switch to basic authentication and a hardcoded user with the deprecated password encoder.

In the long term, I think the goal was going to be that we would have a custom security filter that would set a security context, but then wanted to register a passkey and use that passkey for access to endpoints moving forward.

I ask because we obviously cannot allow registering a passkey to an anonymous user (if we did when we authenticated with that passkey who would we be authenticated as?).

I think maybe clearing up the coupling between users and passkeys in the documentation might be helpful here? The passkeys documentation has a code bit that creates an in-memory user details object, but the relationship here and why that's necessary isn't completely clear. Doing that also affects any calls to UsernamePasswordAuthenticationToken and the like, so if you were doing something custom elsewhere, that could break.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Dec 17, 2024
@justincranford
Copy link

justincranford commented Dec 26, 2024

I ran into the same issue. Visiting the /webauthn/registration or /webauthn/registration/options endpoints expects a username. I got a NullPointerException due to request.getRemoteUser()=null.

My use case is to create a password-less user via WebAuthn registration. This is supported by WebAuthn 2019 and 2021.

Support for anonymous registration is implemented in Yubico's Java WebAuthn Server. There is a demo for that too.

Lastly, I implemented anonymous registration in my own project.

image

I am in the process of trying to switch from Yubico Java WebAuthn Server to Spring Security 6.4. I ran into the anonymous registration issue mentioned in this issue #16070. I also ran into WebAuthn + Redis serialization issues in #16328, but that is probably separate from #16070.

I am hoping anonymous WebAuthn registration can be supported, which should be able to create the user automatically like in WebAuthn 2021, the official demo website https://webauthn.io/, and Yubico's Java WebAuthn Server implementation.

@justincranford
Copy link

justincranford commented Dec 26, 2024

If you want to try anonymous registration yourself, the official demo website https://webauthn.io/ supports it.

Official demo website

Heads up, there are two WebAuthn registration types: Non-Resident vs Resident. Client can choose via Advanced Settings.

Discoverable Credential:

  1. Discouraged (Client wants Non-Resident/Non-Discoverable)
  2. Preferred (Client wants Resident/Discoverable, but fallback to Non-Resident/Non-Discoverable is OK)
  3. Required (Client wants Resident/Discoverable)
image

Registration: Non-Resident or Resident

  1. Non-resident (WebAuthn 2019) => Cred stored in server (encrypted export), never in client
  2. Resident (WebAuthn 2021) => Cred stored in client (encrypted), optional in server (encrypted export||clear export||no export).

Authentication: Non-Discoverable or Discoverable

  • Non-Discoverable => Non-Resident credentials+usernames are stored in server, so usernames can't be discovered locally
  • Discoverable => Resident credentials+usernames are stored in client, so usernames can be discovered locally

WebAuthn 1.0 vs 2.0

WebAuthn 2021 is backwards compatible with WebAuthn 2019; so WebAuthn 2021 supports both Non-Resident and Resident.

Passkeys

Alias for Resident/Discoverable.

@Jyosua
Copy link
Author

Jyosua commented Dec 27, 2024

Ah, thank you Justin! This was actually the other part I forgot: yeah, we originally wanted to support completely passwordless user registration. This is also a major usecase for and reason to want to support passkeys, since registration is a barrier to entry on a lot of services and users forgetting passwords (password recovery tends to be expensive) is largely mitigated by the flow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web An issue in web modules (web, webmvc) status: feedback-provided Feedback has been provided type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants