LoginController::vkOAuthCallbackAction()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
c 0
b 0
f 0
rs 9.0856
cc 2
eloc 13
nc 2
nop 1
1
<?php
2
3
namespace AppBundle\Controller;
4
5
use AppBundle\Controller\Infrastructure\RestController;
6
use AppBundle\Response\ApiResponse;
7
use AppBundle\Service\Security\TokenAuthenticator;
8
use GuzzleHttp\Exception\ClientException;
9
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
10
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
11
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
12
use Symfony\Component\HttpFoundation\Request;
13
use Symfony\Component\HttpFoundation\Response;
14
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
15
16
/**
17
 * @author Vehsamrak
18
 * @Route("login")
19
 */
20
class LoginController extends RestController
21
{
22
23
    const VK_AUTHORIZATION_URL = 'https://oauth.vk.com/authorize';
24
    const VK_DISPLAY_POPUP = 'popup';
25
    const VK_DISPLAY_PAGE = 'page';
26
    const VK_RESPONSE_TYPE_CODE = 'code';
27
28
    /**
29
     * Login with Vkontakte OAuth.
30
     * Client should follow received location to authorize on vkontakte site.
31
     * If success, "token" will be received.
32
     * @Route("/vk", name="login_vk")
33
     * @Method("GET")
34
     * @ApiDoc(
35
     *     section="Login",
36
     *     statusCodes={
37
     *         302="Redirect to vkontakte login page",
38
     *     }
39
     * )
40
     */
41
    public function vkAction()
42
    {
43
        $parameters = [
44
            'client_id'     => $this->getParameter('vkontakte.client_id'),
45
            'redirect_uri'  => $this->generateVkCallbackUrl(),
46
            'display'       => self::VK_DISPLAY_PAGE,
47
            'response_type' => self::VK_RESPONSE_TYPE_CODE,
48
            'v'             => $this->getParameter('vkontakte.version'),
49
            'scope'         => $this->getPermissionMask(),
50
            'state'         => '', // string for state transfer. Can have any value
51
        ];
52
53
        $vkontakteAuthorizationUrl = sprintf(
54
            '%s?%s',
55
            self::VK_AUTHORIZATION_URL,
56
            http_build_query($parameters)
57
        );
58
59
        return $this->redirect($vkontakteAuthorizationUrl);
60
    }
61
62
    /**
63
     * Vkontakte OAuth callback url
64
     * @Route("/vk/callback", name="login_vk_oauth_callback")
65
     * @Method("GET")
66
     */
67
    public function vkOAuthCallbackAction(Request $request)
68
    {
69
        $vkAuthorizationCode = $request->get('code');
70
        $vkontakteClient = $this->get('rockparade.vkontakte');
71
72
        try {
73
            $vkontakteToken = $vkontakteClient->getTokenByCode($vkAuthorizationCode, $this->generateVkCallbackUrl());
74
        } catch (ClientException $e) {
75
            return $this->redirectToRoute('login_vk');
76
        }
77
78
        $userService = $this->get('rockparade.user');
79
        $user = $userService->createOrUpdateUser($vkontakteToken);
80
81
        $response = new ApiResponse(
82
            [
83
                TokenAuthenticator::TOKEN_HEADER => $user->getToken(),
84
            ],
85
            Response::HTTP_OK
86
        );
87
88
        return $this->respond($response);
89
    }
90
91
    /**
92
     * Vkontakte permission flags
93
     * @link https://vk.com/dev/permissions
94
     */
95
    private function getPermissionMask(): string
96
    {
97
        return join(
98
            ',',
99
            [
100
                'email',
101
                'offline',
102
            ]
103
        );
104
    }
105
106
    private function generateVkCallbackUrl(): string
107
    {
108
        return $this->generateUrl('login_vk_oauth_callback', [], UrlGeneratorInterface::ABSOLUTE_URL);
109
    }
110
}
111