Is it possible to use dual authentication with symfony2? - symfony

Is it possible to use dual authentication with symfony2?
Users should be able to authenticate themselves with facebook and my own system.
I've read the documentation, and I know that there is the FacebookBundle with I can authenticate a user with facebook, but I don't know how to combinate the two.

Yes. "You can configure a firewall to use more than one authentication mechanisms" : http://symfony.com/doc/current/book/security.html#using-multiple-user-providers
I didn't try it yet but I think it should be something like:
security:
firewalls:
public:
pattern: ^/.*
form_login: true
fos_facebook:
login_path: ^/facebook$
check_path: ^/facebook-check$
default_target_path: /facebook
provider: my_fos_facebook_provider
You can define multiple providers as well.

Related

Symfony, How can I use Guard with FosUserBundle?

With Symfony 3.2 I want to use CAS to authenticate users. Currently, I'm using fosuserbundle to authenticate users against MySQL, but I want to switch to Guard.
I read all about guard and I understand that I need to implement some methods, like getCredentials, getUser, onAuthenticationFailure, etc, but is there any parameter that I need to update in the security.yml? How can I have Guard to handle the authentications and fosuserbundle just handle the forms?
Here is my security.yml file
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
main:
form_login:
#provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
login_path: /login
check_path: /login_check
I have a class that extending AbstractGuardAuthenticator but nothing seems to ge called.
In summary how can I use Guard with fosuserbundle.?
Thank you all in advance.

Symfony Chain Multiple Authentication Listeners

I have implemented custom authentication, with the whole shebang (custom Token, Listener, Factory, Provider) which I will call as a whole WebserviceAuthentication.
This, as the name implies, authenticates with a custom webservice, receives a few API tokens, etc. etc. and is working fine by itself.
I now want use the FOSUserBundle to authenticate. I have enabled it in my security.yml file, and the cleaned up version is below. The entire point is to authenticate locally, and if that fails, then authenticate with the webservice.
Both of my providers use different tokens. My token for WebserviceAuthentication has a couple of custom attributes, and is not the same as the UsernamePasswordToken that FOSUserBundle uses.
My question is, how do I use one authentication mechanism first, and then go onto the second one? When I enable it as it is now, I can authenticate with FOSUserBundle Users, but I can't authenticate with my webservice users.
In the current state, if the local authentication fails, it tries to invoke the second WebserviceAuthentication provider. However, it supports() a different a token, which means that it's skipped and never called.
Any advice on how to do this? Is there any way to chain authentication listeners to try the FOSUser listener first, and then try the Webservice? The reason I am thinking Listeners is because that's where the Token is initially created. Any advice is appreciated.
security.yml
providers:
#chain_provider:
# chain:
# providers: [ws_provider, fos_userbundle]
fos_userbundle:
id: fos_user.user_provider.username
ws_provider:
id: ws.user_provider
firewalls:
ws_secured:
pattern: ^/
logout:
path: /logout
target: /
success_handler: bo.logout.success.handler
anonymous: true
wslogin:
check_path: /login_check
login_path: /login
provider: ws_provider
default_target_path: /
success_handler: some.success.handler
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
failure_handler: some.failure.handler
success_handler: some.success.handler

Will FOSFacebookBundle create apllication(user) session in symfony2?

I am using Facebook integration for one of my symfony2 application.
I have used FOSUserBundle and FOSFacebookUserBundle.
I can able to login through form in my application and user session was created.
Same when I am using FB to login my application FB session created. Here I want to create my User session as like we do it via form_login.
Will FOSFacebookBundle providing any authentication or Do we need to write separate authentication provider for the same?
I have done all the setup what is given in FOsUserBUndle and FOSFacebookBundle.
Can anyone help me on this?
Finally, I have fixed the issue.
Yes, FosFacebookBundle will create user session for application.
We no need to write authentication provider.(But we should have Facebook Provider to authenticate on it. like given in FosFacebookBundle basic usage document).
my security.yml firewall config:
firewalls:
main:
pattern: ^/
anonymous: true
form_login:
login_path: /
check_path: _security_check
failure_path: login_failure
success_handler: Projectfolder.authentication.success_handler
fos_facebook:
login_path: /
check_path: _security_check_facebook
provider: fos_facebook_provider
default_target_path: /
logout:
path: /logout
target: /
My routing.yml :
_security_check_facebook:
pattern: /facebook/login_check
defaults: { _controller: ProjectfolderUserBundle:Security:loginFb }
_security_facebook_logout:
pattern: /facebook/logout
Note:
_security_facebook_logout, we won't use in our application. While logout we will remove only application user session not facebook session. We can use this url during development.
I have called login_check instead of /facebook/login_check. So User session is not set in my application. Now it's working fine.

FOSFacebookBundle not adding users to database

I have successfully configured FOSUserBundle to connect to the admin section of the website, this works great.
We want public users to only be able to login to the website via Facebook so I have also installed FOSFacebookBundle, which works. Sort of. I can login, authenticate, access the user's profile page and logout; all that works as expected.
However, when a user logs in via Facebook, the user isn't added to the database. Am I mistaken that this is what the "Custom User Provider" at the bottom of the docs (https://github.com/FriendsOfSymfony/FOSFacebookBundle) is supposed to do?
Basically, when a Facebook login happens, the user is added (if necessary) and then fetched through FOSUserBundle.
I followed the docs time and time again, read questions here on SO and can't figure out what's (not) happening.
Anyone have ideas as to where in the code something could be causing the login action not to update the database with Facebook data?
In security.yml:
providers:
chain_provider:
chain:
providers: [my_fos_facebook_provider, fos_userbundle]
my_fos_facebook_provider:
id: my.facebook.user
fos_userbundle:
id: fos_user.user_manager
firewalls:
admin:
pattern: /admin(.*)
form_login:
provider: fos_userbundle
login_path: /admin/login
use_forward: false
check_path: /admin/login_check
failure_path: null
logout:
path: /admin/logout
anonymous: true
public:
# since anonymous is allowed users will not be forced to login
pattern: ^/.*
fos_facebook:
provider: my_fos_facebook_provider
app_url: "http://www.facebook.com/apps/application.php?id=your_app_id"
server_url: "http://localhost/facebookApp/"
login_path: /
check_path: /login_check_fb
default_target_path: /moi
anonymous: true
logout:
handlers: ["fos_facebook.logout_handler"]
The idea is that admin is accessed with a run of the mill username and password and normal users log in via Facebook.
Now, the key part is to define multiple providers (which I had), but perhaps most importantly is to specify the "provider" in each of the firewalls. fos_userbundle for admin and my_fos_facebook_provider for public

Symfony 2: Accessing a firewalled route with two separate providers

We have a system where the administrators and standard users are handled by their own separate security providers. This has caused a problem in the administrative pages because the administrators can't access any files or images that are behind the main site's firewall unless they are also signed in to the main site.
The images and files need to be accessible to all authenticated users and administrators, regardless of provider. They are served through a controller that provides more fine grained access control.
Is it possible to define more than one provider to allow access to a route?
Here's a stripped down version of our current security.yml:
security:
providers:
admin_user_db:
entity: { class: OurAdminUserBundle:AdminUser, property: username }
site_user_db:
entity: { class: OurSiteUserBundle:SiteUser, property: username }
firewalls:
admin_login:
pattern: ^/admin/login$
security: false
site_user_login:
pattern: ^/login
security: false
file_route:
pattern: ^/file
anonymous: ~
### We need to allow this route only for authorized users from
### either admin_user_db or site_user_db providers
admin_secured_area:
pattern: ^/admin
http_basic: ~
provider: admin_user_db
form_login:
check_path: /admin/login_check
login_path: /admin/login
logout:
path: /admin/logout
target: /
site_secured_area:
pattern: .*
http_basic: ~
provider: site_user_db
form_login:
check_path: /check_login
login_path: /login
failure_path: /login
failure_forward: false
logout:
path: /logout
target: /
I guess what you looking for is ChainProvider. This provider will be configured to use your two current providers in a sequential way.
The chain provider will first try to authenticate the user with the first provider it was configured with. If it's a success, the user is authenticated. If it's a failure, the chain provider will try the next one and so on until no more providers can be tried.
I used this technique to let users authenticate with either form login or facebook login. I had two providers, one for facebook, one for form. Then, in my firewall, the provider was the chain provider and then, users were able to login with their credentials or with their facebook account.
Since chain provider is sequential, what I suggest is to put the provider that will probably by used most often first.
Here a configuration sample taken from the Symfony documentation site:
security:
providers:
chain_provider:
chain:
providers: [in_memory, user_db]
in_memory:
users:
foo: { password: test }
user_db:
entity: { class: Acme\UserBundle\Entity\User, property: username
You can take a look at the documenation here:
Using Multiple User Providers
Regards,
Matt
I had some experience with this issue and the solution was the one that Matt wrote.
However, since out application had Administration, Student and Teacher firewalls I couldn't achieve successful impersonation when needed. That is, users from Administration could impersonate users from their firewall and those only.
Now, it is possible that I did something wrong but because this was time sensitive task we decided to put everything behind single firewall and let the different roles do the job. This turned out to be much simpler solution but ultimately it's up to you...

Resources