Completed
Push — master ( ef12ad...9c45e8 )
by Christian
03:34
created

AuthController::checkAuthAction()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 1
Metric Value
c 5
b 0
f 1
dl 0
loc 27
rs 8.5806
cc 4
eloc 16
nc 3
nop 1
1
<?php
2
3
/**
4
 * This file is part of tenside/core-bundle.
5
 *
6
 * (c) Christian Schiffler <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * This project is provided in good faith and hope to be usable by anyone.
12
 *
13
 * @package    tenside/core-bundle
14
 * @author     Christian Schiffler <[email protected]>
15
 * @author     Yanick Witschi <[email protected]>
16
 * @copyright  2015 Christian Schiffler <[email protected]>
17
 * @license    https://github.com/tenside/core-bundle/blob/master/LICENSE MIT
18
 * @link       https://github.com/tenside/core-bundle
19
 * @filesource
20
 */
21
22
namespace Tenside\CoreBundle\Controller;
23
24
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
25
use Symfony\Component\HttpFoundation\JsonResponse;
26
use Symfony\Component\HttpFoundation\Request;
27
use Tenside\Core\Util\JsonArray;
28
use Tenside\CoreBundle\Annotation\ApiDescription;
29
use Tenside\CoreBundle\Security\UserInformationInterface;
30
31
/**
32
 * The main entry point.
33
 */
34
class AuthController extends AbstractController
35
{
36
    /**
37
     * Try to validate the user from the request and return a jwt authentication result then.
38
     *
39
     * @param Request $request The request.
40
     *
41
     * @return JsonResponse
42
     *
43
     * @throws \RuntimeException For invalid user classes.
44
     *
45
     * @ApiDoc(
46
     *   section="auth",
47
     *   statusCodes = {
48
     *     200 = "When everything worked out ok",
49
     *     401 = "When the request was unauthorized."
50
     *   },
51
     *   parameters = {
52
     *     {
53
     *       "name": "ttl",
54
     *       "dataType" = "string",
55
     *       "format" = "\d+",
56
     *       "description" = "The amount of seconds the token shall be valid or -1 for unlimited (default: 3600).",
57
     *       "required" = false
58
     *     },
59
     *     {
60
     *       "name": "username",
61
     *       "dataType" = "string",
62
     *       "description" = "The username.",
63
     *       "required" = true
64
     *     },
65
     *     {
66
     *       "name": "password",
67
     *       "dataType" = "string",
68
     *       "description" = "The pssword.",
69
     *       "required" = true
70
     *     }
71
     *   }
72
     * )
73
     * @ApiDescription(
74
     *   response={
75
     *    "status" = {
76
     *      "dataType" = "choice",
77
     *      "description" = "OK or unauthorized",
78
     *      "format" = "['OK', 'unauthorized']",
79
     *    },
80
     *    "token" = {
81
     *      "dataType" = "string",
82
     *      "description" = "The JWT (only if status ok).",
83
     *    },
84
     *    "acl" = {
85
     *      "actualType" = "collection",
86
     *      "subType" = "string",
87
     *      "description" = "The roles of the authenticated user.",
88
     *    },
89
     *    "username" = {
90
     *      "actualType" = "string",
91
     *      "description" = "The username of the authenticated user.",
92
     *    },
93
     *   },
94
     * )
95
     */
96
    public function checkAuthAction(Request $request)
97
    {
98
        $user = $this->getUser();
99
100
        if (null !== $user) {
101
            if (!$user instanceof UserInformationInterface) {
102
                throw new \RuntimeException('Invalid user object');
103
            }
104
105
            $lifetime = $this->determineLifeTime($request);
106
107
            $token = $this->get('tenside.jwt_authenticator')->getTokenForData($user, $lifetime);
108
            return new JsonResponse(
109
                [
110
                    'status'    => 'OK',
111
                    'token'     => $token,
112
                    'acl'       => $user->getRoles(),
113
                    'username'  => $user->getUsername(),
114
                    'ttl'       => (null === $lifetime) ? 'unlimited' : date('r', (time() + $lifetime))
115
                ],
116
                JsonResponse::HTTP_OK,
117
                ['Authentication' => $token]
118
            );
119
        }
120
121
        return new JsonResponse(['status' => 'unauthorized'], JsonResponse::HTTP_UNAUTHORIZED);
122
    }
123
124
    /**
125
     * Determine the life time for the token.
126
     *
127
     * This examines the GET parameters if a field "ttl" has been set.
128
     * If not, it examines the JSON post data for a field named ttl.
129
     *
130
     * @param Request $request The request.
131
     *
132
     * @return int|null
133
     */
134
    private function determineLifeTime(Request $request)
135
    {
136
        if ($lifetime = $request->query->getInt('ttl')) {
137
            return $this->revertToNullOnMinusOne($lifetime);
138
        }
139
140
        try {
141
            $inputData = new JsonArray($request->getContent());
0 ignored issues
show
Bug introduced by
It seems like $request->getContent() targeting Symfony\Component\HttpFo...n\Request::getContent() can also be of type resource; however, Tenside\Core\Util\JsonArray::__construct() does only seem to accept string|array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
142
            if ($inputData->has('ttl')) {
143
                return $this->revertToNullOnMinusOne(intval($inputData->get('ttl')));
144
            }
145
        } catch (\Exception $e) {
146
            // Swallow exception, we need to return a defined result.
147
        }
148
149
        return 3600;
150
    }
151
152
    /**
153
     * Return the value if it is different than -1, null otherwise.
154
     *
155
     * @param int $lifetime The life time.
156
     *
157
     * @return null|int
158
     */
159
    private function revertToNullOnMinusOne($lifetime)
160
    {
161
        if (-1 === $lifetime) {
162
            return null;
163
        }
164
165
        return $lifetime;
166
    }
167
}
168