-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver_resource.php
More file actions
117 lines (95 loc) · 3.51 KB
/
Copy pathserver_resource.php
File metadata and controls
117 lines (95 loc) · 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?php
/**
* Server side implementation for validate the token
*/
use Parroauth2\Client\ClientConfig;
use Parroauth2\Client\EndPoint\Introspection\IntrospectionResponse;
use Parroauth2\Client\Extension\JwtAccessToken\JwtAccessToken;
use Parroauth2\Client\Extension\RequiredScopeValidator;
use Parroauth2\Client\Provider\ProviderConfigPool;
use Parroauth2\Client\Provider\ProviderLoader;
use Psr\SimpleCache\CacheInterface;
require_once __DIR__.'/../vendor/autoload.php';
class Authenticator
{
private const PROVIDER_URL = 'http://192.168.0.139/~vquatrevieux/sso/s2pweb/oidc';
private const CLIENT_ID = 'server_resource_test';
private const CLIENT_SECRET = 'my_secret';
/**
* @var \Parroauth2\Client\ClientInterface
*/
private $client;
/**
* @var IntrospectionResponse
*/
private $token;
public function __construct(CacheInterface $cache)
{
// Load the provider and provide a cache for the config to ensure that
// keys and config are stored locally, and the server will not perform any request to check the token
$loader = new ProviderLoader(null, null, null, null, new ProviderConfigPool($cache));
// Create the client
$this->client = $loader->discover(self::PROVIDER_URL)->client(
(new ClientConfig(self::CLIENT_ID))->setSecret(self::CLIENT_SECRET)
);
// Enable local introspection using JWT access token
$this->client->register(new JwtAccessToken());
// Resource owner should check for some required scopes.
// Enable this extension to assert the given scope are provided in the access token.
$this->client->register(new RequiredScopeValidator(['profile']));
}
/**
* Validate the access token passed as "Authorization: Bearer" header
*
* Perform a local introspection if possible (a key has been configured, and the access token is effectively a JWT)
*
* @return bool true if the access token is valid
*
* @throws \Http\Client\Exception
* @throws \Parroauth2\Client\Exception\Parroauth2Exception
* @throws \Parroauth2\Client\Exception\UnsupportedServerOperation
*
* @psalm-assert-if-true !null $this->token()
* @psalm-assert-if-fale null $this->token()
*/
public function authenticate(): bool
{
// Check the Authorization header
if (empty($_SERVER['HTTP_AUTHORIZATION'])) {
return false;
}
$header = explode(' ', trim($_SERVER['HTTP_AUTHORIZATION']));
if (count($header) !== 2 || strcasecmp($header[0], 'bearer') !== 0) {
return false;
}
// Perform introspection on the token
// No HTTP request should be performed here because local introspection is enabled
$response = $this->client->endPoints()->introspection()
->accessToken($header[1])
->call()
;
// The token is expired or invalid
if (!$response->active()) {
return false;
}
$this->token = $response;
return true;
}
/**
* Get the parsed token
*
* @return IntrospectionResponse|null
*/
public function token(): ?IntrospectionResponse
{
return $this->token;
}
}
$authenticator = new Authenticator(new MyCacheImplementation());
if (!$authenticator->authenticate()) {
http_response_code(401);
exit('Invalid access token');
}
// Get the user id from the token
$userId = $authenticator->token()->subject();
echo json_encode(loadFromUserId($userId));