Skip to content

Commit 53e9199

Browse files
committed
POC introspection endpoint RFC 7662
1 parent e12b077 commit 53e9199

File tree

4 files changed

+162
-0
lines changed

4 files changed

+162
-0
lines changed

Diff for: Controller/IntrospectionController.php

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the FOSOAuthServerBundle package.
7+
*
8+
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace FOS\OAuthServerBundle\Controller;
15+
16+
use FOS\OAuthServerBundle\Model\AccessTokenInterface;
17+
use FOS\OAuthServerBundle\Model\RefreshTokenInterface;
18+
use FOS\OAuthServerBundle\Model\TokenInterface;
19+
use FOS\OAuthServerBundle\Model\TokenManagerInterface;
20+
use Symfony\Component\HttpFoundation\JsonResponse;
21+
use Symfony\Component\HttpFoundation\Request;
22+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
23+
24+
class IntrospectionController
25+
{
26+
/**
27+
* @var TokenStorageInterface
28+
*/
29+
private $tokenStorage;
30+
31+
/**
32+
* @var TokenManagerInterface
33+
*/
34+
private $accessTokenManager;
35+
36+
/**
37+
* @var TokenManagerInterface
38+
*/
39+
private $refreshTokenManager;
40+
41+
public function __construct(
42+
TokenStorageInterface $tokenStorage,
43+
TokenManagerInterface $accessTokenManager,
44+
TokenManagerInterface $refreshTokenManager
45+
) {
46+
$this->tokenStorage = $tokenStorage;
47+
$this->accessTokenManager = $accessTokenManager;
48+
$this->refreshTokenManager = $refreshTokenManager;
49+
}
50+
51+
public function introspectAction(Request $request): JsonResponse
52+
{
53+
// $clientToken = $this->tokenStorage->getToken(); → use in security
54+
55+
// TODO security for this endpoint. Probably in the README documentation
56+
57+
$token = $this->getToken($request);
58+
59+
$isActive = $token && !$token->hasExpired();
60+
61+
if (!$isActive) {
62+
return new JsonResponse([
63+
'active' => false,
64+
]);
65+
}
66+
67+
return new JsonResponse([
68+
'active' => true,
69+
'scope' => $token->getScope(),
70+
'client_id' => $token->getClientId(),
71+
'username' => $this->getUsername($token),
72+
'token_type' => $this->getTokenType($token),
73+
'exp' => $token->getExpiresAt(),
74+
]);
75+
}
76+
77+
/**
78+
* @return TokenInterface|null
79+
*/
80+
private function getToken(Request $request)
81+
{
82+
$tokenTypeHint = $request->request->get('token_type_hint'); // TODO move in a form type ? can be `access_token`, `refresh_token` See https://tools.ietf.org/html/rfc7009#section-4.1.2
83+
$tokenString = $request->request->get('token'); // TODO move in a form type ?
84+
85+
$tokenManagerList = [];
86+
if (!$tokenTypeHint || 'access_token' === $tokenTypeHint) {
87+
$tokenManagerList[] = $this->accessTokenManager;
88+
}
89+
if (!$tokenTypeHint || 'refresh_token' === $tokenTypeHint) {
90+
$tokenManagerList[] = $this->refreshTokenManager;
91+
}
92+
93+
foreach ($tokenManagerList as $tokenManager) {
94+
$token = $tokenManager->findTokenByToken($tokenString);
95+
96+
if ($token) {
97+
return $token;
98+
}
99+
}
100+
}
101+
102+
/**
103+
* @return string|null
104+
*/
105+
private function getTokenType(TokenInterface $token)
106+
{
107+
if ($token instanceof AccessTokenInterface) {
108+
return 'access_token';
109+
} elseif ($token instanceof RefreshTokenInterface) {
110+
return 'refresh_token';
111+
}
112+
113+
return null;
114+
}
115+
116+
/**
117+
* @return string|null
118+
*/
119+
private function getUsername(TokenInterface $token)
120+
{
121+
$user = $token->getUser();
122+
if (!$user) {
123+
return null;
124+
}
125+
126+
return $user->getUserName();
127+
}
128+
}

Diff for: DependencyInjection/FOSOAuthServerExtension.php

+7
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ public function load(array $configs, ContainerBuilder $container)
101101
$authorizeFormDefinition = $container->getDefinition('fos_oauth_server.authorize.form');
102102
$authorizeFormDefinition->setFactory([new Reference('form.factory'), 'createNamed']);
103103
}
104+
105+
$this->loadIntrospection($loader);
104106
}
105107

106108
/**
@@ -142,6 +144,11 @@ protected function remapParametersNamespaces(array $config, ContainerBuilder $co
142144
}
143145
}
144146

147+
protected function loadIntrospection(XmlFileLoader $loader)
148+
{
149+
$loader->load('introspection.xml');
150+
}
151+
145152
protected function loadAuthorize(array $config, ContainerBuilder $container, XmlFileLoader $loader)
146153
{
147154
$loader->load('authorize.xml');

Diff for: Resources/config/introspection.xml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
6+
7+
<services>
8+
<service id="fos_oauth_server.controller.introspection" class="FOS\OAuthServerBundle\Controller\IntrospectionController" public="true">
9+
<argument type="service" id="security.token_storage" />
10+
<argument type="service" id="fos_oauth_server.access_token_manager" />
11+
<argument type="service" id="fos_oauth_server.refresh_token_manager" />
12+
</service>
13+
</services>
14+
15+
</container>

Diff for: Resources/config/routing/introspection.xml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<routes xmlns="http://symfony.com/schema/routing"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
6+
7+
<route id="fos_oauth_server_introspection" path="/oauth/v2/introspect" methods="POST">
8+
<default key="_controller">fos_oauth_server.controller.introspection:introspectAction</default>
9+
</route>
10+
11+
</routes>
12+

0 commit comments

Comments
 (0)