Passed
Push — master ( 401cce...21cdfe )
by Derek Stephen
03:23
created

OAuthServerController::sendResponse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace App\Controller;
4
5
use DateInterval;
6
use Del\Common\ContainerService;
7
use Del\Form\Field\Radio;
8
use Del\Form\Field\Submit;
9
use Del\Form\Form;
10
use Exception;
11
use League\OAuth2\Server\AuthorizationServer;
12
use League\OAuth2\Server\Exception\OAuthServerException;
13
use League\OAuth2\Server\Grant\AuthCodeGrant;
14
use League\OAuth2\Server\Grant\ClientCredentialsGrant;
15
use League\OAuth2\Server\Grant\RefreshTokenGrant;
16
use OAuth\OAuthUser;
17
use Psr\Http\Message\ResponseInterface;
18
use Zend\Diactoros\Response;
19
use Zend\Diactoros\Response\SapiEmitter;
20
use Zend\Diactoros\Stream;
21
22
class OAuthServerController extends BaseController
23
{
24
    /** @var AuthorizationServer $oauth2Server */
25
    protected $oauth2Server;
26
27
    /**
28
     * @throws \Exception
29
     */
30 6
    public function init()
31
    {
32 6
        $container = ContainerService::getInstance()->getContainer();
33 6
        $clientRepository = $container['repository.Client'];
34 6
        $accessTokenRepository = $container['repository.AccessToken'];
35 6
        $scopeRepository = $container['repository.Scope'];
36 6
        $authCodeRepository = $container['repository.AuthCode'];
37 6
        $refreshTokenRepository = $container['repository.RefreshToken'];
38
39
        // Setup the authorization server
40 6
        $server = new AuthorizationServer($clientRepository, $accessTokenRepository, $scopeRepository,
41 6
            'file://'.APPLICATION_PATH.'/data/keys/private.key',    // path to private key
42 6
            'file://'.APPLICATION_PATH.'/data/keys/public.key'      // path to public key
43
        );
44
45 6
        $this->oauth2Server = $server;
46
47 6
        $this->oauth2Server->enableGrantType(
48 6
            new ClientCredentialsGrant(),
49 6
            new DateInterval('PT1H')
50
        );
51
52 6
        $this->oauth2Server->enableGrantType(
53 6
            new AuthCodeGrant(
54 6
                $authCodeRepository,
55 6
                $refreshTokenRepository,
56 6
                new DateInterval('PT10M')
57
            ),
58 6
            new DateInterval('PT1H')
59
        );
60
61 6
        $refreshGrant = new RefreshTokenGrant($refreshTokenRepository);
62 6
        $refreshGrant->setRefreshTokenTTL(new DateInterval('PT1M'));
63 6
        $this->oauth2Server->enableGrantType(
64 6
            $refreshGrant,
65 6
            new DateInterval('PT1H')
66
        );
67 6
    }
68
69
    /**
70
     *
71
     * @SWG\Get(
72
     *     path="/oauth2/authorize",
73
     *     @SWG\Response(response="200", description="An access token"),
74
     *     tags={"auth"},
75
     *     @SWG\Parameter(
76
     *         name="response_type",
77
     *         in="query",
78
     *         type="string",
79
     *         description="the type of response",
80
     *         required=true,
81
     *         default="code"
82
     *     ),
83
     *     @SWG\Parameter(
84
     *         name="client_id",
85
     *         in="query",
86
     *         type="string",
87
     *         description="the client identifier",
88
     *         required=true,
89
     *         default="testclient"
90
     *     ),
91
     *     @SWG\Parameter(
92
     *         name="client_secret",
93
     *         in="query",
94
     *         type="string",
95
     *         description="the client identifier",
96
     *         required=false,
97
     *         default="testclient"
98
     *     ),
99
     *     @SWG\Parameter(
100
     *         name="redirect_uri",
101
     *         in="query",
102
     *         type="string",
103
     *         description="where to send the response",
104
     *         required=false
105
     *     ),
106
     *     @SWG\Parameter(
107
     *         name="state",
108
     *         in="query",
109
     *         type="string",
110
     *         description="with a CSRF token. This parameter is optional but highly recommended.",
111
     *         required=false,
112
     *     ),
113
     *     @SWG\Parameter(
114
     *         name="scope",
115
     *         in="query",
116
     *         type="string",
117
     *         description="allowed scopes, space separated",
118
     *         required=false,
119
     *     )
120
     * )
121
     */
122 1
    public function authorizeAction()
123
    {
124
        /* @var AuthorizationServer $server */
125 1
        $server = $this->oauth2Server;
126
127 1
        $request = $this->getRequest();
128 1
        $response = new Response();
129
130
        try {
131
            // Validate the HTTP request and return an AuthorizationRequest object.
132
            // The auth request object can be serialized into a user's session
133 1
            $authRequest = $server->validateAuthorizationRequest($request);
134
            // Once the user has logged in set the user on the AuthorizationRequest
135 1
            $authRequest->setUser(new OAuthUser());
136
            // Once the user has approved or denied the client update the status
137
            // (true = approved, false = denied)
138 1
            $authRequest->setAuthorizationApproved(true);
139
            // Return the HTTP redirect response
140 1
            $response = $server->completeAuthorizationRequest($authRequest, $response);
141
142
        } catch (OAuthServerException $e) {
143
            $response = $e->generateHttpResponse($response);
144
145
        } catch (Exception $e) {
146
            $body = new Stream('php://temp', 'r+');
147
            $body->write($e->getMessage());
148
            $response = $response->withStatus(500)->withBody($body);
149
        }
150
151 1
        $redirectUri = $response->getHeader('Location');
152 1
        if (!empty($redirectUri)) {
153 1
            if (\substr($redirectUri[0], 0, 1) == '?') {
154
                $uri = \str_replace('?', '', $redirectUri[0]);
155
                \parse_str($uri, $vars);
156
                $this->sendJsonResponse($vars);
157
            }
158
        } else {
159
            $this->sendResponse($response);
160
        }
161
162 1
        return $response;
163
    }
164
165
    /**
166
     * @SWG\Post(
167
     *     path="/oauth2/access-token",
168
     *     operationId="accessToken",
169
     *     @SWG\Response(response="200", description="An access token"),
170
     *     tags={"auth"},
171
     *     @SWG\Parameter(
172
     *         name="grant_type",
173
     *         in="formData",
174
     *         type="string",
175
     *         description="the type of grant",
176
     *         required=true,
177
     *         default="client_credentials",
178
     *     ),
179
     *     @SWG\Parameter(
180
     *         name="client_id",
181
     *         in="formData",
182
     *         type="string",
183
     *         description="the client id",
184
     *         required=true,
185
     *         default="ceac682a9a4808bf910ad49134230e0e"
186
     *     ),
187
     *     @SWG\Parameter(
188
     *         name="client_secret",
189
     *         in="formData",
190
     *         type="string",
191
     *         description="the client secret",
192
     *         required=false,
193
     *         default="JDJ5JDEwJGNEd1J1VEdOY0YxS3QvL0pWQzMxay52"
194
     *     ),
195
     *     @SWG\Parameter(
196
     *         name="scope",
197
     *         in="formData",
198
     *         type="string",
199
     *         description="the scopes you wish to use",
200
     *         required=false,
201
     *         default="admin"
202
     *     ),
203
     *     @SWG\Parameter(
204
     *         name="redirect_uri",
205
     *         in="formData",
206
     *         type="string",
207
     *         description="with the same redirect URI the user was redirect back to",
208
     *         required=false,
209
     *     ),
210
     *     @SWG\Parameter(
211
     *         name="code",
212
     *         in="formData",
213
     *         type="string",
214
     *         description="with the authorization code from the query string",
215
     *         required=false,
216
     *     ),
217
     * )
218
     */
219 6
    public function accessTokenAction()
220
    {
221
        /* @var AuthorizationServer $server */
222 6
        $server = $this->oauth2Server;
223
224 6
        $request = $this->getRequest();
225 6
        $response = new Response();
226
227
        try {
228
            // Try to respond to the access token request
229 6
            $response = $server->respondToAccessTokenRequest($request, $response);
230 4
        } catch (OAuthServerException $e) {
231 3
            $response = $e->generateHttpResponse($response);
232 1
        } catch (Exception $e) {
233 1
            $code = $e->getCode() ?: 500;
234
            $response = $response
235 1
                ->withStatus($code)
236 1
                ->withHeader('content-type', 'application/json; charset=UTF-8');
237 1
            $response->getBody()->write(\json_encode([
238 1
                'error' => $code,
239 1
                'message' => $e->getMessage(),
240
            ]));
241
        }
242 6
        $this->sendResponse($response);
243
    }
244
245
    /**
246
     * @param ResponseInterface $response
247
     */
248 6
    protected function sendResponse(ResponseInterface $response)
249
    {
250 6
        $emitter = new SapiEmitter();
0 ignored issues
show
Deprecated Code introduced by
The class Zend\Diactoros\Response\SapiEmitter has been deprecated: since 1.8.0. The package zendframework/zend-httphandlerrunner now provides this functionality. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

250
        $emitter = /** @scrutinizer ignore-deprecated */ new SapiEmitter();
Loading history...
251 6
        $emitter->emit($response);
252 6
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
253
    }
254
255
    /**
256
     * @return Form
257
     */
258
    private function getForm()
259
    {
260
        $form = new Form('auth');
261
        $radio = new Radio('auth');
262
        $radio->setOptions([
263
            'yes' => 'Yes',
264
            'no' => 'No',
265
        ]);
266
        $radio->setLabel('Do you authorise TestClient?');
267
        $radio->setRenderInline(true);
268
        $radio->setRequired(true);
269
        $submit = new Submit('submit');
270
271
        $form->addField($radio)
272
            ->addField($submit);
273
274
        return $form;
275
    }
276
}
277