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

Integrate with new "Authenticators" security #5

Closed
scheb opened this issue May 5, 2020 · 3 comments · Fixed by #8
Closed

Integrate with new "Authenticators" security #5

scheb opened this issue May 5, 2020 · 3 comments · Fixed by #8

Comments

@scheb
Copy link
Owner

scheb commented May 5, 2020

Integrate the bundle with the new "authenticator" security system, which was introduced as an experimental feature in Symfony 5.1.

The old approach doesn't work anymore, which was: retrieving all "authentication listeners" from security.authentication.manager to decorate them and effectively wrap away the authenticated token before it becomes visible to the security system. There are no more listeners that could be used as a hook-in point

Potentially the new concept of "badges" and event-based authentication can help. Could potentially lead the bundle towards a cleaner, less hacky integration. Currently unclear, needs more investigation.

References:

Notes:

Token is created by the authenticator:
https://github.com/wouterj/symfony/blob/b1e040f311e16f4888f42564a6d5da0a489c929a/src/Symfony/Component/Security/Http/Authentication/AuthenticatorManager.php#L169

Example:
https://github.com/wouterj/symfony/blob/b1e040f311e16f4888f42564a6d5da0a489c929a/src/Symfony/Component/Security/Http/Authenticator/AbstractAuthenticator.php#L35

@scheb
Copy link
Owner Author

scheb commented May 9, 2020

So I did some first investigations a few days ago and overall I have the impression not so much would change how to bundle would integrate 2fa. The main problems that I always needed to work around with "hacks" are still there:

  1. How do I prevent authentication listeners from passing the fully authenticated security token to the security layer, when 2fa is required and the user should actually not be fully authenticated?

There is no hook-in point to modify the security token in the authentication process, before it becomes available to the security layer. So my approach to this problem was so far: decorating all the authenication listeners to wrap the security token with a "TwoFactorToken", which is hiding away all privileges (roles) and signaling to the application that the user has to do 2fa. With authenticators I've figured out I'd need to decorate all authenticators instead to achieve the same effect, because there is still no way for anything but the authenticator itself, how the security token looks like before it becomes effective.

  1. How do I introduce an "intermediate state" (the user is not anonymous, but also not "fully authenticaticated")?.

In Symfony security, any token that is not anonymous or a remember-me token (see: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.php#L52) is considered "fully fledged" which is a problem for the 2fa use-case, because a "TwoFactorToken" should be in that intermediate state and therefore not "fully fledged". So I had to solve this once again with a decorator (https://github.com/scheb/2fa/blob/master/src/bundle/Security/Authentication/AuthenticationTrustResolver.php), which is decorating the original service from the Symfony security layer.

I had a quick look at the "badges" and they might in fact help to pass around information necessary for 2fa. For example, the 2fa bundle has a feature to flag your machine as a trusted device via a cookie. That could be implemented with a badge, similar to the remember-me feature. So that's good.

What I'm missing with badges is a way to modify a badge. For example, the remember-me feature adds a badge to the passport, but once it was added, there's no way to modify the badge. What I'd like to do, when the user requires 2fa, somehow disable or remove the remember-me badge from the passport, because as long as the user hasn't passed 2fa, I don't want a remember-me cookie to be set. This used to be a security issue in the bundle before, when the remember-me token was set to early and you could bypass 2fa with the remember-me cookie that has been set too early. I fixed this issue by decorating the security component's "remember-me services" and preventing the cookie to be set. But I believe, with badges it would be much easier to postpone setting the remember-me cookie, if there was a way to disable/remove the remember-me badge.

@Spomky
Copy link
Contributor

Spomky commented May 9, 2020

Hi @scheb,

I read this nice article and the new authentication system looks great.
The only concern I have in regard to my projects is the possibility to authenticate other entity than users (e.g. clients as per OAuth2 or servers in server to server communication). But it looks like it is possible now thanks to the PassportInterface.

Like you with this bundle, I have similar questions for Webauthn. In the bundle I created, I added security token attributes to allow routes to be protected depending on the security device and methods performed by the user.

I think you are right and now custom badges is the way to go i.e. you will attach badges to the users depending of the status of the 2fa and maybe depending on the 2fa used.
Maybe these badges could be inline with the RFC8176:

The following badges could be created and attached to the passport:

  • MfaBadge (mfa),
  • OtpBadge (otp),
  • PinBadge (pin),
  • SmsBadge (sms),
  • or TelBadge (tel).

Restriction could be applied e.g. if a user didn’t performed 2fa with OTP+PIN.
I will be happy to help you integrating this new feature!

@scheb
Copy link
Owner Author

scheb commented May 9, 2020

I'm in a conversation with @wouterj at the moment to get his opinion on this.

The thing with the passport and custom badges is - to my knowledge right now, I might be wrong - the passport and badges only exist within the one request that authenticates the user. It is not persisted between request like a security token. For multi-step authentication it doesn't really help, since you're loosing the state after every request. So the only way to store the state is still the security token. That leads me back to the current implementation of having a TwoFactorToken and "magically" wrapping away the authenticated token before it becomes visible to the security system.

So right now my impression is, not so much would change. But let's see where we're ending up, we're not in a hurry ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants