Completed
Push — master ( 1de9b7...830752 )
by Kristof
38:46 queued 24:09
created

AdminBundle/Security/OAuthAuthenticator.php (1 issue)

possible assignment of superclass instead of class.

Bug Documentation Minor

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Kunstmaan\AdminBundle\Security;
4
5
use Kunstmaan\AdminBundle\FlashMessages\FlashTypes;
6
use Kunstmaan\AdminBundle\Helper\Security\OAuth\OAuthUserCreator;
7
use Kunstmaan\AdminBundle\Helper\Security\OAuth\OAuthUserCreatorInterface;
8
use Symfony\Component\HttpFoundation\RedirectResponse;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Component\HttpFoundation\Response;
11
use Symfony\Component\HttpFoundation\Session\SessionInterface;
12
use Symfony\Component\Routing\RouterInterface;
13
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
14
use Symfony\Component\Security\Core\Exception\AuthenticationException;
15
use Symfony\Component\Security\Core\User\UserInterface;
16
use Symfony\Component\Security\Core\User\UserProviderInterface;
17
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
18
use Symfony\Component\Translation\TranslatorInterface;
19
20
class OAuthAuthenticator extends AbstractGuardAuthenticator
21
{
22
    /** @var RouterInterface */
23
    private $router;
24
25
    /** @var SessionInterface */
26
    private $session;
27
28
    /** @var TranslatorInterface */
29
    private $translator;
30
31
    /** @var OAuthUserCreator */
32
    private $oAuthUserCreator;
33
34
    /** @var string */
35
    private $clientId;
36
37
    /** @var string */
38
    private $clientSecret;
39
40
    /**
41
     * OAuthAuthenticator constructor.
42
     *
43
     * @param RouterInterface           $router
44
     * @param SessionInterface          $session
45
     * @param TranslatorInterface       $translator
46
     * @param OAuthUserCreatorInterface $oAuthUserCreator
47
     * @param $clientId
48
     * @param $clientSecret
49
     */
50
    public function __construct(RouterInterface $router, SessionInterface $session, TranslatorInterface $translator, OAuthUserCreatorInterface $oAuthUserCreator, $clientId, $clientSecret)
51
    {
52
        $this->router = $router;
53
        $this->session = $session;
54
        $this->translator = $translator;
55
        $this->oAuthUserCreator = $oAuthUserCreator;
0 ignored issues
show
Documentation Bug introduced by
$oAuthUserCreator is of type object<Kunstmaan\AdminBu...thUserCreatorInterface>, but the property $oAuthUserCreator was declared to be of type object<Kunstmaan\AdminBu...OAuth\OAuthUserCreator>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
56
        $this->clientId = $clientId;
57
        $this->clientSecret = $clientSecret;
58
    }
59
60
    /**
61
     * @param Request $request
62
     *
63
     * @return bool
64
     */
65
    public function supports(Request $request)
66
    {
67
        return $request->attributes->get('_route') == 'KunstmaanAdminBundle_oauth_signin' || $request->request->has('_google_id_token');
68
    }
69
70
    /**
71
     * Returns a response that directs the user to authenticate.
72
     *
73
     * This is called when an anonymous request accesses a resource that
74
     * requires authentication. The job of this method is to return some
75
     * response that "helps" the user start into the authentication process.
76
     *
77
     * Examples:
78
     *  A) For a form login, you might redirect to the login page
79
     *      return new RedirectResponse('/login');
80
     *  B) For an API token authentication system, you return a 401 response
81
     *      return new Response('Auth header required', 401);
82
     *
83
     * @param Request                 $request       The request that resulted in an AuthenticationException
84
     * @param AuthenticationException $authException The exception that started the authentication process
85
     *
86
     * @return RedirectResponse
87
     */
88
    public function start(Request $request, AuthenticationException $authException = null)
89
    {
90
        return new RedirectResponse($this->router->generate('fos_user_security_login'));
91
    }
92
93
    /**
94
     * Get the authentication credentials from the request and return them
95
     * as any type (e.g. an associate array).
96
     *
97
     * Whatever value you return here will be passed to getUser() and checkCredentials()
98
     *
99
     * For example, for a form login, you might:
100
     *
101
     *      return array(
102
     *          'username' => $request->request->get('_username'),
103
     *          'password' => $request->request->get('_password'),
104
     *      );
105
     *
106
     * Or for an API token that's on a header, you might use:
107
     *
108
     *      return array('api_key' => $request->headers->get('X-API-TOKEN'));
109
     *
110
     * @param Request $request
111
     *
112
     * @return array
113
     */
114
    public function getCredentials(Request $request)
115
    {
116
        $token = $request->request->get('_google_id_token');
117
118
        return [
119
            'token' => $token,
120
        ];
121
    }
122
123
    /**
124
     * Return a UserInterface object based on the credentials.
125
     *
126
     * The *credentials* are the return value from getCredentials()
127
     *
128
     * You may throw an AuthenticationException if you wish. If you return
129
     * null, then a UsernameNotFoundException is thrown for you.
130
     *
131
     * @param mixed                 $credentials
132
     * @param UserProviderInterface $userProvider
133
     *
134
     * @throws AuthenticationException
135
     *
136
     * @return UserInterface|null
137
     */
138
    public function getUser($credentials, UserProviderInterface $userProvider)
139
    {
140
        $idToken = $credentials['token'];
141
142
        $gc = new \Google_Client();
143
        $gc->setClientId($this->clientId);
144
        $gc->setClientSecret($this->clientSecret);
145
        $ticket = $gc->verifyIdToken($idToken);
146
        if (!$ticket instanceof \Google_LoginTicket) {
147
            return null;
148
        }
149
150
        $data = $ticket->getAttributes()['payload'];
151
        $email = $data['email'];
152
        $googleId = $data['sub'];
153
154
        return $this->oAuthUserCreator->getOrCreateUser($email, $googleId);
155
    }
156
157
    /**
158
     * Returns true if the credentials are valid.
159
     *
160
     * If any value other than true is returned, authentication will
161
     * fail. You may also throw an AuthenticationException if you wish
162
     * to cause authentication to fail.
163
     *
164
     * The *credentials* are the return value from getCredentials()
165
     *
166
     * @param mixed         $credentials
167
     * @param UserInterface $user
168
     *
169
     * @return bool
170
     *
171
     * @throws AuthenticationException
172
     */
173
    public function checkCredentials($credentials, UserInterface $user)
174
    {
175
        return true;
176
    }
177
178
    /**
179
     * Called when authentication executed, but failed (e.g. wrong username password).
180
     *
181
     * This should return the Response sent back to the user, like a
182
     * RedirectResponse to the login page or a 403 response.
183
     *
184
     * If you return null, the request will continue, but the user will
185
     * not be authenticated. This is probably not what you want to do.
186
     *
187
     * @param Request                 $request
188
     * @param AuthenticationException $exception
189
     *
190
     * @return RedirectResponse
191
     */
192
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
193
    {
194
        $this->session->getFlashBag()->add(FlashTypes::ERROR, $this->translator->trans('errors.oauth.invalid'));
195
196
        return new RedirectResponse($this->router->generate('fos_user_security_login'));
197
    }
198
199
    /**
200
     * Called when authentication executed and was successful!
201
     *
202
     * This should return the Response sent back to the user, like a
203
     * RedirectResponse to the last page they visited.
204
     *
205
     * If you return null, the current request will continue, and the user
206
     * will be authenticated. This makes sense, for example, with an API.
207
     *
208
     * @param Request        $request
209
     * @param TokenInterface $token
210
     * @param string         $providerKey The provider (i.e. firewall) key
211
     *
212
     * @return RedirectResponse
213
     */
214
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
215
    {
216
        $targetPath = $request->getSession()->get(
217
            sprintf('_security.%s.target_path', $providerKey),
218
            $this->router->generate('KunstmaanAdminBundle_homepage')
219
        );
220
221
        return new RedirectResponse($targetPath);
222
    }
223
224
    /**
225
     * Does this method support remember me cookies?
226
     *
227
     * Remember me cookie will be set if *all* of the following are met:
228
     *  A) This method returns true
229
     *  B) The remember_me key under your firewall is configured
230
     *  C) The "remember me" functionality is activated. This is usually
231
     *      done by having a _remember_me checkbox in your form, but
232
     *      can be configured by the "always_remember_me" and "remember_me_parameter"
233
     *      parameters under the "remember_me" firewall key
234
     *
235
     * @return bool
236
     */
237
    public function supportsRememberMe()
238
    {
239
        return false;
240
    }
241
}
242