This is my (dirty) solution, but I hope people understand what I want to.
From the client side, the user send the request to get authorization from the google account (I'm using Symfony2 with HWIOauthBundle)
http://myserver.com/connect/google
This present the Google login form. The user fill the form and submit it. If success exists, there will be a redirect to myserver.com where the user will logged.
I catch the event onAuthenticationSuccess ...
<?php
namespace App\Bundle\Handler;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\HttpFoundation\Request,
Symfony\Component\HttpFoundation\RedirectResponse,
Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Router;
class SecurityHandler implements AuthenticationSuccessHandlerInterface
{
private $router;
public function __construct(Router $router)
{
$this->router = $router;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token)
{
$user = $token->getUser();
return new RedirectResponse($this->router->generate('api_get_token', array(
'clientRandomId' => '5ewv02jcis08wsgggk4wow4so0gokco0g4s8kkoc4so4s0gw4c'
)));
}
}
... to redirect to a Controller where it will generate an access_token and refresh_token, where they will be saved in the database. At the end, it will be sent a json response to the user, like FOSOauthServerBundle does.
<?php
namespace App\Bundle\Controller\Api;
use Symfony\Bundle\FrameworkBundle\Controller\Controller,
Symfony\Component\HttpFoundation\JsonResponse,
Symfony\Component\Security\Core\Exception\AccessDeniedException;
use FOS\RestBundle\Controller\FOSRestController,
FOS\RestBundle\Controller\Annotations\Route,
FOS\RestBundle\Controller\Annotations\NamePrefix,
FOS\RestBundle\Controller\Annotations\Prefix;
use FOS\RestBundle\Routing\ClassResourceInterface;
use App\Bundle\Entity\AccessToken;
use App\Bundle\Entity\RefreshToken;
class TokenController extends FOSRestController implements ClassResourceInterface {
public function getAction($clientRandomId)
{
$user = $this->get('security.context')->getToken()->getUser();
$this->container->get('security.context')->setToken(null);
$em = $this->get('doctrine')->getManager();
$client = $em->getRepository('AppBundle:Client')->findOneBy(array('randomId' => $clientRandomId));
$expiresAt = time() + 3600;
$accessToken = new AccessToken;
$accessToken->setClient($client);
$accessToken->setToken('access_token');
$accessToken->setExpiresAt($expiresAt);
$accessToken->setUser($user);
$refreshToken = new RefreshToken;
$refreshToken->setClient($client);
$refreshToken->setToken('refresh_token');
$refreshToken->setExpiresAt($expiresAt);
$refreshToken->setUser($user);
$em->persist($accessToken);
$em->persist($refreshToken);
$em->flush();
$jsonData = array(
'access_token' => $accessToken->getToken(),
'expires_in' => 3600,
'token_type' => 'bearer',
'scope' => null,
'refresh_token' => $refreshToken->getToken()
);
$response = new JsonResponse($jsonData);
return $response;
}}
I know this is not the best solution but maybe it guide you to a better solution.