I need to have a separate url for plain signin form (username/password) which already exist on /login, and some url like /login-via-facebook to login via FOSFacebookBundle oauth procedure.
Now I can't understand how to trigger oauth-facebook procedure by url, it works only if I try to access url which is listed in "access_control".
Thanks in advance!
@Matt, thank you very much for your the explanation! I tried to follow your answer, but still have a problem, I didn't mention that I already using FOSUserBundle,
my security.yml
:
providers:
chain_provider:
providers: [fos_userbundle, fos_facebook]
fos_userbundle:
id: fos_user.user_manager
fos_facebook:
id: fos_facebook.auth
firewalls:
public:
pattern: ^/
fos_facebook:
app_url: ""
server_url: ""
login_path: /login
check_path: /login_check/facebook
provider: fos_userbundle
fos_userbundle:
login_path: /login
check_path: /login_check/form
provider: fos_userbundle
anonymous: true
logout: true`
so, at this point it throws an exception: InvalidConfigurationException: Unrecognized options "fos_userbundle" under "security.firewalls.public"
, and if I change fos_userbundle to form_login in public firewalls (but should I do this at all?), it throws an exception You must configure the check path to be handled by the firewall using form_login in your security firewall configuration.
Did you check your security.yml for:
factories:
- "%kernel.root_dir%/../vendor/bundles/FOS/FacebookBundle/Resources/config/security_factories.xml"
It's important because it will charge the missing options for the service.
The trick is to have two separated entries in your firewall, one for the form login and one for the facebook login. But in my case, I have a single login url where the user can either log in using his credentials or click on a Facebook connect to authenticate via the Facebook OAuth2 API using the FOSFacebookBundle
. Here a sample of my security.yml
config file to make this work:
security:
factories:
- "%kernel.root_dir%/../vendor/bundles/FOS/FacebookBundle/Resources/config/security_factories.xml"
providers:
chain_provider:
providers: [acme.form_provider, acme.facebook_provider]
acme.form_provider:
id: acme.user_provider.form
acme.facebook_provider:
id: acme.user_provider.facebook
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
public:
pattern: ^/
fos_facebook:
app_url: "your_app_url"
server_url: "your_server_url"
login_path: /login
check_path: /login_check/facebook
provider: acme.facebook_provider
form_login:
login_path: /login
check_path: /login_check/form
provider: acme.form_provider
anonymous: true
logout: true
role_hierarchy:
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
And here a sample of my routing.yml
file that is used to define security routes required to make this work:
# This is defined to let the user log in. The controller for
# route display the login form and a facebook connect button
_security_login:
pattern: /login
defaults: { _controller: AcmeAcmeBundle:Main:login }
# This is defined for the form login authentication,
# no controller is associated with it
_security_check_form:
pattern: /login_check/form
# This is defined for facebook login authentication,
# a controller is associated with it but does nothing
_security_check_facebook:
pattern: /login_check/facebook
defaults: { _controller: AcmeAcmeBundle:Main:loginCheckFacebook }
_security_logout:
pattern: /logout
defaults: { _controller: AcmeAcmeBundle:Main:logout }
Using the security.yml
before, the security mechanism will check for user logged in using form prior to user logged in with facebook. This is because the order in which providers are defined in the chain_provider
. On each request, the FOSFacebookBundle
check if a facebook oauth2 cookie is present, if so, it tries to load your user. If it fails to find the cookie, the authentication process will try another provider, if it is defined after the facebook provider.
In your case, when the user tries to go to a protected url (in access_control), the facebook login page is shown and he authenticate, then he is redirected to your site, the cookie is found and the user is authenticated successfully by the FOSFacebookBundle
. To manually trigger the authentication process, place a facebook connect button on your site, then, in javascript, redirects the user to another page of your site. This way, the cookie will be set by the connect button and the FOSFacebookBundle
will authenticate him on the next request. What I do, is to redirect the user to the login_check path for facebook in javascript when the facebook connect button has been successfull. This way, the security mechanism will redirect him where it is stated in the security configuration.
I hope this will help you to achieve what you want. Do not hesite to ask further question if something is unclear.
@Follow-up #1
Indeed, you cannot put fos_userbundle
under the node public
in the firewall configuration because it is not a valid option. The string fos_userbundle
is used to reference FOSUserBundle
UserProvider class. I never used this bundle but reading the documentation, you should use form_login
. You can look at the documentation of FOSUserBundle
in Step #5 and below. The error you mentionning is odd because it tells you that the login_path
is not handled by the firewall but it's the case since the firewall matchs anything that start with a /
(^/
). Not sure what is going wrong but you're going in the right direction. Use form_login
and try to check why it's not working from there.
Regards,
Matt
There's a simple example Bundle which implements both FOSUserBundle and FOSFacebookBundle if you'd like to look https://github.com/ollietb/OhFOSFacebookUserBundle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With