Completed
Push — master ( 91fdab...75a7b9 )
by
unknown
13:37
created

AdminBundle/Security/OAuthAuthenticator.php (5 issues)

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\Session;
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 Session */
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
     * @param RouterInterface $router
43
     * @param Session $session
44
     * @param TranslatorInterface $translator
45
     * @param OAuthUserCreatorInterface $oAuthUserCreator
46
     * @param $clientId
47
     * @param $clientSecret
48
     */
49
    public function __construct(RouterInterface $router, Session $session, TranslatorInterface $translator, OAuthUserCreatorInterface $oAuthUserCreator, $clientId, $clientSecret)
50
    {
51
        $this->router = $router;
52
        $this->session = $session;
53
        $this->translator = $translator;
54
        $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...
55
        $this->clientId = $clientId;
56
        $this->clientSecret = $clientSecret;
57
    }
58
59
    /**
60
     * Returns a response that directs the user to authenticate.
61
     *
62
     * This is called when an anonymous request accesses a resource that
63
     * requires authentication. The job of this method is to return some
64
     * response that "helps" the user start into the authentication process.
65
     *
66
     * Examples:
67
     *  A) For a form login, you might redirect to the login page
68
     *      return new RedirectResponse('/login');
69
     *  B) For an API token authentication system, you return a 401 response
70
     *      return new Response('Auth header required', 401);
71
     *
72
     * @param Request $request The request that resulted in an AuthenticationException
73
     * @param AuthenticationException $authException The exception that started the authentication process
0 ignored issues
show
Should the type for parameter $authException not be null|AuthenticationException?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
74
     *
75
     * @return Response
0 ignored issues
show
Consider making the return type a bit more specific; maybe use RedirectResponse.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
76
     */
77
    public function start(Request $request, AuthenticationException $authException = null)
78
    {
79
        return new RedirectResponse($this->router->generate('fos_user_security_login'));
80
    }
81
82
    /**
83
     * Get the authentication credentials from the request and return them
84
     * as any type (e.g. an associate array). If you return null, authentication
85
     * will be skipped.
86
     *
87
     * Whatever value you return here will be passed to getUser() and checkCredentials()
88
     *
89
     * For example, for a form login, you might:
90
     *
91
     *      return array(
92
     *          'username' => $request->request->get('_username'),
93
     *          'password' => $request->request->get('_password'),
94
     *      );
95
     *
96
     * Or for an API token that's on a header, you might use:
97
     *
98
     *      return array('api_key' => $request->headers->get('X-API-TOKEN'));
99
     *
100
     * @param Request $request
101
     *
102
     * @return mixed|null
0 ignored issues
show
Consider making the return type a bit more specific; maybe use null|array.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
103
     */
104
    public function getCredentials(Request $request)
105
    {
106
        if ($request->attributes->get('_route') != 'KunstmaanAdminBundle_oauth_signin' || !$request->request->has('_google_id_token')) {
107
            return null;
108
        }
109
110
        $token = $request->request->get('_google_id_token');
111
        return array(
112
            'token' => $token,
113
        );
114
    }
115
116
    /**
117
     * Return a UserInterface object based on the credentials.
118
     *
119
     * The *credentials* are the return value from getCredentials()
120
     *
121
     * You may throw an AuthenticationException if you wish. If you return
122
     * null, then a UsernameNotFoundException is thrown for you.
123
     *
124
     * @param mixed $credentials
125
     * @param UserProviderInterface $userProvider
126
     *
127
     * @throws AuthenticationException
128
     *
129
     * @return UserInterface|null
0 ignored issues
show
Should the return type not be null|object?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
130
     */
131
    public function getUser($credentials, UserProviderInterface $userProvider)
132
    {
133
        $idToken = $credentials['token'];
134
135
        $gc = new \Google_Client();
136
        $gc->setClientId($this->clientId);
137
        $gc->setClientSecret($this->clientSecret);
138
        $ticket = $gc->verifyIdToken($idToken);
139
        if (!$ticket instanceof \Google_LoginTicket) {
140
            return null;
141
        }
142
143
        $data = $ticket->getAttributes()['payload'];
144
        $email = $data['email'];
145
        $googleId = $data['sub'];
146
147
        return $this->oAuthUserCreator->getOrCreateUser($email, $googleId);
148
    }
149
150
    /**
151
     * Returns true if the credentials are valid.
152
     *
153
     * If any value other than true is returned, authentication will
154
     * fail. You may also throw an AuthenticationException if you wish
155
     * to cause authentication to fail.
156
     *
157
     * The *credentials* are the return value from getCredentials()
158
     *
159
     * @param mixed $credentials
160
     * @param UserInterface $user
161
     *
162
     * @return bool
163
     *
164
     * @throws AuthenticationException
165
     */
166
    public function checkCredentials($credentials, UserInterface $user)
167
    {
168
        return true;
169
    }
170
171
    /**
172
     * Called when authentication executed, but failed (e.g. wrong username password).
173
     *
174
     * This should return the Response sent back to the user, like a
175
     * RedirectResponse to the login page or a 403 response.
176
     *
177
     * If you return null, the request will continue, but the user will
178
     * not be authenticated. This is probably not what you want to do.
179
     *
180
     * @param Request $request
181
     * @param AuthenticationException $exception
182
     *
183
     * @return Response|null
184
     */
185
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
186
    {
187
        $this->session->getFlashBag()->add(FlashTypes::ERROR, $this->translator->trans('errors.oauth.invalid'));
188
        return new RedirectResponse($this->router->generate('fos_user_security_login'));
189
    }
190
191
    /**
192
     * Called when authentication executed and was successful!
193
     *
194
     * This should return the Response sent back to the user, like a
195
     * RedirectResponse to the last page they visited.
196
     *
197
     * If you return null, the current request will continue, and the user
198
     * will be authenticated. This makes sense, for example, with an API.
199
     *
200
     * @param Request $request
201
     * @param TokenInterface $token
202
     * @param string $providerKey The provider (i.e. firewall) key
203
     *
204
     * @return Response|null
205
     */
206
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
207
    {
208
        $targetPath = $request->getSession()->get(
209
            sprintf('_security.%s.target_path', $providerKey),
210
            $this->router->generate('KunstmaanAdminBundle_homepage')
211
        );
212
213
        return new RedirectResponse($targetPath);
214
    }
215
216
    /**
217
     * Does this method support remember me cookies?
218
     *
219
     * Remember me cookie will be set if *all* of the following are met:
220
     *  A) This method returns true
221
     *  B) The remember_me key under your firewall is configured
222
     *  C) The "remember me" functionality is activated. This is usually
223
     *      done by having a _remember_me checkbox in your form, but
224
     *      can be configured by the "always_remember_me" and "remember_me_parameter"
225
     *      parameters under the "remember_me" firewall key
226
     *
227
     * @return bool
228
     */
229
    public function supportsRememberMe()
230
    {
231
        return false;
232
    }
233
}
234