Completed
Push — master ( 6e52f0...d9a404 )
by Alexandre
02:29
created

IdTokenResponseType::getDefaultResponseMode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: GCC-MED
5
 * Date: 19/01/2018
6
 * Time: 15:06
7
 */
8
9
namespace OAuth2OLD\OpenID\ResponseTypes;
10
11
12
use Firebase\JWT\JWT;
13
use OAuth2OLD\OpenID\Config;
14
use OAuth2OLD\Exceptions\OAuthException;
15
use OAuth2OLD\OpenID\Credentials\IdToken;
16
use OAuth2OLD\OpenID\ResponseModes\ResponseModeInterface;
17
use OAuth2OLD\OpenID\Storages\UserInfoClaimsStorage;
18
use OAuth2OLD\Repositories\ConfigurationRepository;
19
use OAuth2OLD\Roles\Clients\RegisteredClient;
20
use OAuth2OLD\Roles\ResourceOwnerInterface;
21
use OAuth2OLD\OpenID\Storages\IdTokenStorageInterface;
22
use Psr\Http\Message\ServerRequestInterface;
23
24
class IdTokenResponseType implements ResponseTypeInterface
25
{
26
    /**
27
     * @var ConfigurationRepository
28
     */
29
    private $configurationRepository;
30
    /**
31
     * @var IdTokenStorageInterface
32
     */
33
    private $idTokenStorage;
34
    /**
35
     * @var UserInfoClaimsStorage
36
     */
37
    private $userInfoClaimsStorage;
38
39
    public function __construct(ConfigurationRepository $configurationRepository,
40
                                IdTokenStorageInterface $idTokenStorage,
41
                                UserInfoClaimsStorage $userInfoClaimsStorage)
42
{
43
    $this->configurationRepository = $configurationRepository;
44
    $this->idTokenStorage = $idTokenStorage;
45
    $this->userInfoClaimsStorage = $userInfoClaimsStorage;
46
}
47
48
    public function getResponseType(): string
49
    {
50
        return 'id_token';
51
    }
52
53
    /**
54
     * @param ServerRequestInterface $request
55
     * @param ResourceOwnerInterface $resourceOwner
56
     * @param RegisteredClient $client
57
     * @param array|null $scope
58
     * @param array|null $extendedResponseTypes
59
     * @return array
60
     * @throws \Exception
61
     */
62
    public function handle(ServerRequestInterface $request, ResourceOwnerInterface $resourceOwner,
63
                           RegisteredClient $client, ?array $scope = null, ?array $extendedResponseTypes = null): array
64
    {
65
        $data = $request->getMethod() === 'GET' ? $request->getQueryParams() : $request->getParsedBody();
66
67
        // Get required claims
68
        $claims = [
69
            'iss' => $this->configurationRepository->getConfig(Config::OPENID_ISSUER),
70
            'sub' => $resourceOwner->getIdentifier(),
71
            'aud' => $client->getIdentifier(),
72
            'exp' => time() + $this->idTokenStorage->getLifetime(),
73
            'iat' => time()
74
        ];
75
76
        // todo, include if auth_time is marked as an essential claim by the client otherwise it is optional (conf ?)
77
        if(isset($data['max_age']) && $data['max_age']) {
78
            $claims['auth_time'] = $resourceOwner->getTimeWhenAuthenticationOccured();
79
        }
80
81
        if(isset($data['nonce']) && !is_null($data['nonce'])) {
82
            $claims['nonce'] = $data['nonce'];
83
        }
84
85
        if(empty($extendedResponseTypes)) {
86
            $standardClaims = $this->userInfoClaimsStorage->getClaims($resourceOwner);
87
88
            foreach ($this->userInfoClaimsStorage->getClaimsByScope($scope) as $claimRequested) {
89
                if(isset($standardClaims[$claimRequested]) && $standardClaims[$claimRequested]) {
90
                    $claims[$claimRequested] = $standardClaims[$claimRequested];
91
                }
92
            }
93
        }
94
95
        if(isset($extendedResponseTypes['code'])) {
96
            //c_hash
97
            /**
98
             * @var \OAuth2OLD\ResponseTypes\ResponseTypeInterface $responseType
99
             */
100
            $responseType = $extendedResponseTypes['code'];
101
            $code = $responseType->handle($request, $resourceOwner, $client, $scope)['code'];
102
            $result['code'] = $code;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$result was never initialized. Although not strictly required by PHP, it is generally a good practice to add $result = array(); before regardless.
Loading history...
103
            $claims['c_hash'] = 'todo'; //todo
104
        }
105
106
        if(isset($extendedResponseTypes['token'])) {
107
            //at_hash
108
            /**
109
             * @var \OAuth2OLD\ResponseTypes\ResponseTypeInterface $responseType
110
             */
111
            $responseType = $extendedResponseTypes['token'];
112
            $token = $responseType->handle($request, $resourceOwner, $client, $scope)['token'];
113
            $result['token'] = $token;
114
            $claims['at_hash'] = 'todo'; //todo
115
        }
116
        else {
117
            $requestedScopes = isset($data['scope']) ? explode(' ', $data['scope']) : [];
118
119
            if ((empty($requestedScopes) && !is_null($scope)) || (is_array($scope) && !empty(array_diff($requestedScopes, $scope)))) {
120
                $data['scope'] = implode(' ', $scope);
121
            }
122
        }
123
124
125
//        $idToken = new IdToken($claims);
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
126
        $key = 'mykey'; // todo
127
        $result['id_token'] = JWT::encode($claims, $key);
128
        return $result;
129
    }
130
131
    public function getDefaultResponseMode(): string
132
    {
133
        return ResponseModeInterface::RESPONSE_MODE_FRAGMENT;
134
    }
135
136
    public function isImplicit(): bool
137
    {
138
        return true;
139
    }
140
141
    /**
142
     * @param ServerRequestInterface $request
143
     * @throws OAuthException
144
     */
145
    public function verifyRequest(ServerRequestInterface $request): void
146
    {
147
        $scope = explode(' ', $request->getQueryParams()['scope'] ?? $request->getParsedBody()['scope'] ?? null);
148
        if (is_null($scope)) {
0 ignored issues
show
introduced by
The condition is_null($scope) can never be true.
Loading history...
149
            throw new OAuthException('invalid_request',
150
                'Missing a required parameter : scope',
151
                'http://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint'
152
            );
153
        }
154
        if (!in_array('openid', $scope)) {
155
            throw new OAuthException('invalid_request',
156
                'Invalid scope parameter : openid scope value must be present',
157
                'http://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint'
158
            );
159
        }
160
    }
161
162
    public function requireTLS(): bool
163
    {
164
        return true;
165
    }
166
167
    public function isMultiValuedResponseTypeSupported(): bool
168
    {
169
        return true;
170
    }
171
172
    public function getExtendedResponseTypes(): ?array {
173
        return ['code', 'token'];
174
    }
175
176
    public function isQueryResponseModeSupported(): bool
177
    {
178
        return false;
179
    }
180
}