Skip to content
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

Combining x509 authentication and form login doesn't work #8226

Closed
alcaeus opened this issue Jun 7, 2013 · 0 comments
Closed

Combining x509 authentication and form login doesn't work #8226

alcaeus opened this issue Jun 7, 2013 · 0 comments
Labels

Comments

@alcaeus
Copy link
Contributor

alcaeus commented Jun 7, 2013

I've tried enabling x509 authentication and form login at the same time for a project and ran into some issues. First a bit of background:
The idea is to enable the x509 and form_login options in security.yml, combined with a SSLVerifyClient optional directive for apache. The configuration in security.yml is straightforward:

security:
  firewalls:
    main:
      pattern: .*
      form_login:
        [...]
      x509: true

Once this configuration is enabled, form login doesn't work anymore. No errors, no anything, it just keeps going to the login page.
Debugging through the code, the first piece of code that comes up is Symfony\Component\Security\Http\Firewall\X509AuthenticationListener::getPreAuthenticatedData. The method checks whether the userKey (normally SSL_CLIENT_S_DN_Email) is present and throws an exception if it's missing. Obviously, using the optional method I mentioned above won't ever work. So, I decided to remove that block and change the return line to include a default value for userKey, effectively giving "nothing" to the AbstractPreAuthenticatedListener. Still, no luck.
Next up, AbstractPreAuthenticatedListener::handle. This method checks whether a token is actually present (either its own token or a token from another listener). However, it only skips the following process if it's a PreAuthenticatedToken and it actually contains meaningful values:

if (null !== $token = $this->securityContext->getToken()) {
    if ($token instanceof PreAuthenticatedToken && $this->providerKey == $token->getProviderKey() && $token->isAuthenticated() && $token->getUsername() === $user) {
        return;
    }
}

So, if the form login has written its UsernamePasswordToken and authenticated it, the method will just go ahead, create a new PreAuthenticatedToken and try to authenticate with it (which won't work since we've just given it an empty username in the absence of a valid certificate). In case of an authentication failure, the AuthenticationProviderManager throws an exception, which is caught in the AbstractPreAuthenticationListener. This exception will actually remove any token from the securityContext, even if that token is not a PreAuthenticatedToken but belongs to another provider. So, we're back to where we were before: we're redirected back to the login form even though we've provided valid credentials.

In my opinion, there are two bugs:

  1. The X509AuthenticationListener shouldn't throw an exception if no credentials are given but instead just silently fail and let the authentication request pass to the next provider in line.
  2. In case of an AuthenticationException the AbstractPreAuthenticatedListener should only remove the token from the securityContext if it's a PreAuthenticatedToken. If it's a different token, it should be left alone since a different provider will take care of it.

Now, I would just make these changes and create a pull request, but considering that we're dealing with the security component here I'd rather have a few people look over there and provide their feedback. Once we've established a course of action I'd be more than happy to provide the code and PR to fix the issue (if it actually is a bug).

fabpot added a commit that referenced this issue Jul 20, 2013
This PR was merged into the 2.2 branch.

Discussion
----------

[Security] fixed issue where x509 authentication clears unrelated tokens

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #8226
| License       | MIT
| Doc PR        | symfony/symfony-docs#2825
| Notes          | Replaces PR #8283

TODO:
- [x] Feedback on change to make sure security is not affected
- [x] Fix other authentication listeners (they suffer the same problem)
- [x] Write unit tests for bug and maybe a few listener classes as well

This pull request is the summary of the problem mentioned in the ticket above.
It only fixes the "disappearing token" problem for one authentication provider, not all. If acceptable, the change needs to be applied to all authentication listeners since they always clear all tokens from the security context.

Commits
-------

2317443 [Security] fixed issue where authentication listeners clear unrelated tokens
@fabpot fabpot closed this as completed Jul 20, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants