How to restfully login, Symfony2 Security, FOSUserBundle, FOSRestBundle?

21,141

Solution 1

There are many ways to provide authentication and authorization to a REST Web Service but the most accepted one seems to be OAuth. Facebook, Twitter, Google, Github and the like use it.

The people at Friends Of Symfony has a bundle to implement OAuth authentication and authorization on Symfony2: https://github.com/FriendsOfSymfony/FOSOAuthServerBundle and I think this is what you are looking for.

EDIT: For more information on Oauth, the people at Cloudfoundry posted an interesting article a couple of days ago.

About other options you can use, a simple one is basic authentication:

firewalls:
    main:         
        pattern: ^/rest
        anonymous: ~
        form_login: false            
        provider: fos_user_bundle
        http_basic:
            realm: "REST Service Realm"

EDIT2: As I see that there is still people voting this answer I think that it is needed to note that at the time of writing this answer JWT was not an option yet, but that maybe it is a better option than OAuth on some use cases (e.g. When the API is going to be consumed by your own apps). So here is a link to a good JWT implementation for Symfony2/3: https://github.com/lexik/LexikJWTAuthenticationBundle/blob/master/Resources/doc/index.md

Solution 2

You should not use CURL to authenticate the user with your web service.

Take a look into ResettingController.php (in FOSUserBundle/Controller) and LoginManager.php (in Security), there is an example how to authenticate the user using Symfony Security :

Controller/ResettingController.php

    /**
 * Authenticate a user with Symfony Security
 *
 * @param \FOS\UserBundle\Model\UserInterface        $user
 * @param \Symfony\Component\HttpFoundation\Response $response
 */
protected function authenticateUser(UserInterface $user, Response $response)
{
    try {
        $this->container->get('fos_user.security.login_manager')->loginUser(
            $this->container->getParameter('fos_user.firewall_name'),
            $user,
            $response);
    } catch (AccountStatusException $ex) {
        // We simply do not authenticate users which do not pass the user
        // checker (not enabled, expired, etc.).
    }
}

and in Security/LoginManager.php

    final public function loginUser($firewallName, UserInterface $user, Response $response = null)
{
    $this->userChecker->checkPostAuth($user);

    $token = $this->createToken($firewallName, $user);

    if ($this->container->isScopeActive('request')) {
        $this->sessionStrategy->onAuthentication($this->container->get('request'), $token);

        if (null !== $response) {
            $rememberMeServices = null;
            if ($this->container->has('security.authentication.rememberme.services.persistent.'.$firewallName)) {
                $rememberMeServices = $this->container->get('security.authentication.rememberme.services.persistent.'.$firewallName);
            } elseif ($this->container->has('security.authentication.rememberme.services.simplehash.'.$firewallName)) {
                $rememberMeServices = $this->container->get('security.authentication.rememberme.services.simplehash.'.$firewallName);
            }

            if ($rememberMeServices instanceof RememberMeServicesInterface) {
                $rememberMeServices->loginSuccess($this->container->get('request'), $response, $token);
            }
        }
    }

    $this->securityContext->setToken($token);
}
Share:
21,141
Trent
Author by

Trent

Updated on June 09, 2020

Comments

  • Trent
    Trent almost 4 years

    I'd like to be able to login via a ws.

    I've tried to simulate this with curl pointing to /login but it only handles HTML, etc. By the way, it requires a CSRF which I don't want.

    So I'd like to either disable the CRSF (from the login_check) or find a way to do it myself.

    Can I override the LoginListener (where is it?) which is used when the route login_check is catched.

    ANy clues?

  • thenetimp
    thenetimp over 9 years
    Oauth is only necessary when you are creating an API for 3rd parties to authenticate against your API. If his API is only being used by his application oAuth is overkill and http basic over SSL is more then sufficient.
  • adosaiguas
    adosaiguas over 9 years
    @thenetimp well, that is not 100% true. Although I agree that in many cases basic auth over SSL is enough (That's why I also added it), ouath is not only useful when 3rd parties are going to use your API, but also when your own apps (mobile, web, etc...) are going to use it (see the different grant types). Another method can be to use authentication tokens.
  • thomaskonrad
    thomaskonrad almost 7 years
    Don't use JWT or OAuth for sessions. As @thenetimp said, these technologies are made for 3rd-party authentication or single sign-on. See cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessi‌​ons.