All Projects → symfonycorp → connect-bundle

symfonycorp / connect-bundle

Licence: MIT license
No description or website provided.

Programming Languages

PHP
23972 projects - #3 most used programming language

Projects that are alternatives of or similar to connect-bundle

stampie-bundle
stampie.github.io/
Stars: ✭ 26 (-25.71%)
Mutual labels:  bundle, symfony-bundle
SonataDashboardBundle
[Abandoned] Provides a Dashboard management through container and block services
Stars: ✭ 17 (-51.43%)
Mutual labels:  bundle, symfony-bundle
Fmelfinderbundle
📁 ElFinderBundle provides ElFinder integration with TinyMCE, CKEditor, Summernote editors
Stars: ✭ 231 (+560%)
Mutual labels:  bundle, symfony-bundle
SonataDoctrineMongoDBAdminBundle
Symfony Sonata / Integrate Doctrine MongoDB ODM into the SonataAdminBundle
Stars: ✭ 64 (+82.86%)
Mutual labels:  bundle, symfony-bundle
LiipImagineSerializationBundle
Provides integration between LiipImagineBundle and JMSSerializerBundle
Stars: ✭ 24 (-31.43%)
Mutual labels:  bundle, symfony-bundle
Sonataintlbundle
Symfony SonataIntlBundle
Stars: ✭ 212 (+505.71%)
Mutual labels:  bundle, symfony-bundle
LiipSearchBundle
[DEPRECATED] Google XML API for searching is discontinued
Stars: ✭ 35 (+0%)
Mutual labels:  bundle, symfony-bundle
Mercure Bundle
The MercureBundle allows to easily push updates to web browsers and other HTTP clients in the Symfony full-stack framework, using the Mercure protocol.
Stars: ✭ 195 (+457.14%)
Mutual labels:  bundle, symfony-bundle
SonataTimelineBundle
[Abandoned] Integrates SpyTimelineBundle into Sonata
Stars: ✭ 24 (-31.43%)
Mutual labels:  bundle, symfony-bundle
gulp-rev-versions-bundle
A bundle that allows symfony to get the version of assets versioned with gulp-rev
Stars: ✭ 13 (-62.86%)
Mutual labels:  bundle, symfony-bundle
SlackBundle
SlackBundle for Symfony2 with Guzzle-Integration
Stars: ✭ 39 (+11.43%)
Mutual labels:  bundle, symfony-bundle
jsonrpc-bundle
JSON-RPC server for Symfony: exposes services registered in the service container as JSON-RPC-webservices
Stars: ✭ 31 (-11.43%)
Mutual labels:  bundle, symfony-bundle
Liiphellobundle
[DEPRECATED] Alternative Hello World Bundle for Symfony2 using several FriendsOfSymfony Bundles
Stars: ✭ 206 (+488.57%)
Mutual labels:  bundle, symfony-bundle
Victoire
Fullstack Symfony CMS: The perfect mix between a framework and a CMS
Stars: ✭ 227 (+548.57%)
Mutual labels:  bundle, symfony-bundle
Gifexceptionbundle
😛 The GhostBuster of your exception page!
Stars: ✭ 197 (+462.86%)
Mutual labels:  bundle, symfony-bundle
Enqueue Bundle
[READ-ONLY] Message queue bundle for Symfony. RabbitMQ, Amazon SQS, Redis, Service bus, Async events, RPC over MQ and a lot more
Stars: ✭ 233 (+565.71%)
Mutual labels:  bundle, symfony-bundle
Twig Bundle
The Twig Bundle provides configuration for using Twig in your applications.
Stars: ✭ 2,150 (+6042.86%)
Mutual labels:  bundle, symfony-bundle
Sonatapagebundle
This bundle provides a Site and Page management through container and block services
Stars: ✭ 181 (+417.14%)
Mutual labels:  bundle, symfony-bundle
Lexikmaintenancebundle
This Symfony2 bundle allows you to place your website in maintenance mode by calling two commands in your console. A page with status code 503 appears to users, it is possible to authorize certain ips addresses stored in your configuration.
Stars: ✭ 253 (+622.86%)
Mutual labels:  bundle, symfony-bundle
SensioBuzzBundle
No description or website provided.
Stars: ✭ 89 (+154.29%)
Mutual labels:  bundle, symfony-bundle

symfony/connect-bundle

About

This is the official bundle of the SymfonyConnect SDK.

Installation

Step 1: Install symfony/connect-bundle using Composer

$ composer require symfonycorp/connect-bundle

If you're not using Symfony Flex, please take inspiration from this bundle's recipe to enable it.

Step 2: Configure your .env.local file

SYMFONY_CONNECT_APP_ID='Your app id'
SYMFONY_CONNECT_APP_SECRET='Your app secret'

Usage

Use SymfonyConnect to authenticate your user

Step 1: Configure the security

Note: If you want to persist your users, read the Cookbooks section.

If you don't want to persist your users, you can use ConnectInMemoryUserProvider:

# config/packages/security.yaml
security:
    providers:
        symfony_connect:
            connect_memory: ~
    firewalls:
        # [...]

        secured_area:
            pattern: ^/
            symfony_connect:
                check_path: symfony_connect_callback
                login_path: symfony_connect_login
                failure_path: home # need to be adapted to your config, see step 4
                remember_me: false
                provider: symfony_connect
            anonymous: true

You can also load specific roles for some users:

# config/packages/security.yaml
security:
    providers:
        symfony_connect:
            connect_memory:
                users:
                    90f28e69-9ce9-4a42-8b0e-e8c7fcc27713: "ROLE_CONNECT_USER ROLE_ADMIN"

Note: The username is the user uuid.

Step 2: Add some link to your templates

You can generate a link to the SymfonyConnect login page:

<a href="{{ url('symfony_connect_login') }}">Connect</a>

You can also specify the target URL after connection:

<a href="{{ url('symfony_connect_login') }}?target=XXX">Connect</a>

Step 3: Play with the user

The API user is available through the token storage, which you can get by autowiring Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface $tokenStorage.

$user = $tokenStorage->getToken()->getApiUser();

If you use the built-in security component, you can access to the root api directly by autowiring SymfonyCorp\Connect\Api\Api $api:

$user = $api->getRoot()->getCurrentUser();

You can also get access to the API root object by providing an access token explicitly:

$accessToken = $tokenStorage->getToken()->getAccessToken();
$api->setAccessToken($accessToken);
$root = $api->getRoot();
$user = $root->getCurrentUser();

Step 4: Handling Failures

Several errors can occur during the OAuth dance, for example the user can deny your application or the scope you defined in symfony_connect.yaml can be different from what you selected while creating your application on SymfonyConnect. Theses failures arehandled by the default Symfony failure handling.

Therefore, if an error occurred, the error is stored in the session (with a fallback on query attributes) and the user is redirected to the route/path specificed in failure_path node of the symfony_connect section of your firewall in security.yaml.

Warning: You need to specifiy failure_path. If you don't, the user will be redirected back to login_path, meaning that will launch the SymfonyConnect authentication and redirect the user to SymfonyConnect which can lead to a redirection loop.

This means you need to fetch the authentication error if there is one and display it in the view. This is similar to what you do for a typical login form on Symfony (here we assume you have a home route pointing to the following controller):

// src/Controller/HomeController.php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;

class HomeController extends AbstractController
{
    /**
     * @Route("/", name="home")
     */
    public function home(Request $request)
    {
        $session = $request->hasSession() ? $request->getSession() : null;

        // get the authentication error if there is one
        if ($request->attributes->has(Security::AUTHENTICATION_ERROR)) {
            $error = $request->attributes->get(Security::AUTHENTICATION_ERROR);
        } elseif (null !== $session && $session->has(Security::AUTHENTICATION_ERROR)) {
            $error = $session->get(Security::AUTHENTICATION_ERROR);
            $session->remove(Security::AUTHENTICATION_ERROR);
        } else {
            $error = '';
        }

        return $this->render('home.html.twig', ['error' => $error]);
    }
}

And then adapt your twig template:

{# templates/home.html.twig #}

{% if app.user %}
    Congrats! You are authenticated with SymfonyConnect
{% elseif error %}
    {{ error.messageKey | trans(error.messageData, 'security') }}
{% else %}
    <a href="{{ url('symfony_connect_login') }}">Log in with SymfonyConnect</a>
{% endif %}

Cookbooks

How to persist users

Step 1 - Create a User entity

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use SymfonyCorp\Connect\Api\Entity\User as ConnectApiUser;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 */
class User implements UserInterface
{
    /** @ORM\Column(type="integer") @ORM\Id @ORM\GeneratedValue(strategy="AUTO") */
    private $id;

    /** @ORM\Column(type="string", length=255) */
    private $uuid;

    /** @ORM\Column(type="string", length=255) */
    private $username;

    /** @ORM\Column(type="string", length=255) */
    private $name;

    public function __construct($uuid)
    {
        $this->uuid = $uuid;
    }

    public function updateFromConnect(ConnectApiUser $apiUser)
    {
        $this->username = $apiUser->getUsername();
        $this->name = $apiUser->getName();
    }

    public function getUuid()
    {
        return $this->uuid;
    }

    public function getUsername()
    {
        return $this->username;
    }

    public function getName()
    {
        return $this->name;
    }

    public function getRoles()
    {
        return ['ROLE_USER'];
    }

    public function getPassword()
    {
    }

    public function getSalt()
    {
    }

    public function eraseCredentials()
    {
    }
}

Step 2 - Create the repository

<?php

namespace App\Repository;

use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;

class UserRepository extends ServiceEntityRepository implements UserProviderInterface
{
    public function __construct(RegistryInterface $registry)
    {
        parent::__construct($registry, User::class);
    }

    public function loadUserByUsername($uuid)
    {
        return $this->findOneByUuid($uuid) ?: new User($uuid);
    }

    public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof User) {
            throw new UnsupportedUserException(sprintf('class %s is not supported', get_class($user)));
        }

        return $this->loadUserByUsername($user->getUuid());
    }

    public function supportsClass($class)
    {
        return User::class === $class;
    }
}

Don't forget to update your database.

Step 3 - Create the event listener

<?php

namespace App\EventListener;

use Doctrine\ORM\EntityManagerInterface;
use SymfonyCorp\Connect\Security\Authentication\Token\ConnectToken;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;

class SecurityInteractiveLoginListener implements EventSubscriberInterface
{
    private $em;

    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    public function registerUser(InteractiveLoginEvent $event)
    {
        $token = $event->getAuthenticationToken();

        if (!$token instanceof ConnectToken) {
            return;
        }

        $user = $token->getUser();
        $user->updateFromConnect($token->getApiUser());

        $this->em->persist($user);
        $this->em->flush($user);
    }

    public static function getSubscribedEvents()
    {
        return [
            SecurityEvents::INTERACTIVE_LOGIN => 'registerUser',
        ];
    }
}

Step 4 - Configure security

# config/packages/security.yaml
security:
    encoders:
        App\Entity\User: plaintext

    providers:
        symfony_connect:
            id: App\Repository\UserRepository

Step 5 - Enjoy

You can store more things if you want. But don't forget to update your application scope.

License

This bundle is licensed under the MIT license.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].