Skip to content

Commit 542f640

Browse files
committed
Merge #15 Telekom bearer token: Additional secret V31
2 parents fd4d9df + 74bb1b4 commit 542f640

File tree

8 files changed

+578
-5
lines changed

8 files changed

+578
-5
lines changed

lib/Command/UpsertProvider.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ protected function configure() {
179179
->addOption('clientid', 'c', InputOption::VALUE_REQUIRED, 'OpenID client identifier')
180180
->addOption('clientsecret', 's', InputOption::VALUE_REQUIRED, 'OpenID client secret')
181181
->addOption('discoveryuri', 'd', InputOption::VALUE_REQUIRED, 'OpenID discovery endpoint uri')
182+
->addOption('bearersecret', 'bs', InputOption::VALUE_OPTIONAL, 'Telekom bearer token requires a different client secret for bearer tokens')
182183
->addOption('endsessionendpointuri', 'e', InputOption::VALUE_REQUIRED, 'OpenID end session endpoint uri')
183184
->addOption('postlogouturi', 'p', InputOption::VALUE_REQUIRED, 'Post logout URI')
184185
->addOption('scope', 'o', InputOption::VALUE_OPTIONAL, 'OpenID requested value scopes, if not set defaults to "openid email profile"');
@@ -206,10 +207,17 @@ protected function execute(InputInterface $input, OutputInterface $output) {
206207
return $this->listProviders($input, $output);
207208
}
208209

210+
// bearersecret is usually base64 encoded, but SAM delivers it non-encoded by default
211+
// so always encode/decode for this field
212+
$bearersecret = $input->getOption('bearersecret');
213+
if ($bearersecret !== null) {
214+
$bearersecret = $this->crypto->encrypt(\Base64Url\Base64Url::encode($bearersecret));
215+
}
216+
209217
// check if any option for updating is provided
210218
$updateOptions = array_filter($input->getOptions(), static function ($value, $option) {
211219
return in_array($option, [
212-
'identifier', 'clientid', 'clientsecret', 'discoveryuri', 'endsessionendpointuri', 'postlogouturi', 'scope',
220+
'identifier', 'clientid', 'clientsecret', 'discoveryuri', 'endsessionendpointuri', 'postlogouturi', 'scope', 'bearersecret',
213221
...array_keys(self::EXTRA_OPTIONS),
214222
]) && $value !== null;
215223
}, ARRAY_FILTER_USE_BOTH);
@@ -250,7 +258,7 @@ protected function execute(InputInterface $input, OutputInterface $output) {
250258
}
251259
try {
252260
$provider = $this->providerMapper->createOrUpdateProvider(
253-
$identifier, $clientid, $clientsecret, $discoveryuri, $scope, $endsessionendpointuri, $postLogoutUri
261+
$identifier, $clientid, $clientsecret, $discoveryuri, $scope, $endsessionendpointuri, $postLogoutUri, $bearersecret
254262
);
255263
// invalidate JWKS cache (even if it was just created)
256264
$this->providerService->setSetting($provider->getId(), ProviderService::SETTING_JWKS_CACHE, '');

lib/Controller/SettingsController.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,10 @@ public function isDiscoveryEndpointValid($url) {
7777
}
7878

7979
#[PasswordConfirmationRequired]
80-
public function createProvider(string $identifier, string $clientId, string $clientSecret, string $discoveryEndpoint,
80+
public function createProvider(string $identifier, string $clientId, string $clientSecret, string $discoveryEndpoint, string $bearerSecret,
8181
array $settings = [], string $scope = 'openid email profile', ?string $endSessionEndpoint = null,
8282
?string $postLogoutUri = null): JSONResponse {
83+
8384
if ($this->providerService->getProviderByIdentifier($identifier) !== null) {
8485
return new JSONResponse(['message' => 'Provider with the given identifier already exists'], Http::STATUS_CONFLICT);
8586
}
@@ -102,6 +103,8 @@ public function createProvider(string $identifier, string $clientId, string $cli
102103
$provider->setEndSessionEndpoint($endSessionEndpoint ?: null);
103104
$provider->setPostLogoutUri($postLogoutUri ?: null);
104105
$provider->setScope($scope);
106+
$encryptedBearerSecret = $this->crypto->encrypt(\Base64Url\Base64Url::encode($bearerSecret));
107+
$provider->setBearerSecret($encryptedBearerSecret);
105108
$provider = $this->providerMapper->insert($provider);
106109

107110
$providerSettings = $this->providerService->setSettings($provider->getId(), $settings);
@@ -110,7 +113,7 @@ public function createProvider(string $identifier, string $clientId, string $cli
110113
}
111114

112115
#[PasswordConfirmationRequired]
113-
public function updateProvider(int $providerId, string $identifier, string $clientId, string $discoveryEndpoint, ?string $clientSecret = null,
116+
public function updateProvider(int $providerId, string $identifier, string $clientId, string $discoveryEndpoint, ?string $clientSecret = null, ?string $bearerSecret = null,
114117
array $settings = [], string $scope = 'openid email profile', ?string $endSessionEndpoint = null,
115118
?string $postLogoutUri = null): JSONResponse {
116119
$provider = $this->providerMapper->getProvider($providerId);

lib/Db/Provider.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
* @method \void setEndSessionEndpoint(?string $endSessionEndpoint)
2424
* @method \string|\null getPostLogoutUri()
2525
* @method \void setPostLogoutUri(?string $postLogoutUri)
26+
* @method \string getScope()
2627
* @method \void setScope(string $scope)
28+
* @method \string getBearerSecret()
29+
* @method \void setBearerSecret(string $bearerSecret)
2730
*/
2831
class Provider extends Entity implements \JsonSerializable {
2932

@@ -33,6 +36,9 @@ class Provider extends Entity implements \JsonSerializable {
3336
protected $clientId;
3437
/** @var string */
3538
protected $clientSecret;
39+
/** @var string */
40+
protected $bearerSecret;
41+
3642
/** @var ?string */
3743
protected $discoveryEndpoint;
3844
/** @var ?string */

lib/Db/ProviderMapper.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public function getProviders() {
8080
* @param string $identifier
8181
* @param string|null $clientid
8282
* @param string|null $clientsecret
83+
* @param string|null $bearersecret
8384
* @param string|null $discoveryuri
8485
* @param string $scope
8586
* @param string|null $endsessionendpointuri
@@ -91,7 +92,7 @@ public function getProviders() {
9192
*/
9293
public function createOrUpdateProvider(string $identifier, ?string $clientid = null,
9394
?string $clientsecret = null, ?string $discoveryuri = null, string $scope = 'openid email profile',
94-
?string $endsessionendpointuri = null, ?string $postLogoutUri = null) {
95+
?string $endsessionendpointuri = null, ?string $postLogoutUri = null, ?string $bearersecret = null) {
9596
try {
9697
$provider = $this->findProviderByIdentifier($identifier);
9798
} catch (DoesNotExistException $eNotExist) {
@@ -106,6 +107,7 @@ public function createOrUpdateProvider(string $identifier, ?string $clientid = n
106107
$provider->setIdentifier($identifier);
107108
$provider->setClientId($clientid);
108109
$provider->setClientSecret($clientsecret);
110+
$provider->setBearerSecret($bearersecret ?? '');
109111
$provider->setDiscoveryEndpoint($discoveryuri);
110112
$provider->setEndSessionEndpoint($endsessionendpointuri);
111113
$provider->setPostLogoutUri($postLogoutUri);
@@ -118,6 +120,9 @@ public function createOrUpdateProvider(string $identifier, ?string $clientid = n
118120
if ($clientsecret !== null) {
119121
$provider->setClientSecret($clientsecret);
120122
}
123+
if ($bearersecret !== null) {
124+
$provider->setBearerSecret($bearersecret);
125+
}
121126
if ($discoveryuri !== null) {
122127
$provider->setDiscoveryEndpoint($discoveryuri);
123128
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OCA\UserOIDC\Migration;
6+
7+
use Closure;
8+
use OCP\DB\ISchemaWrapper;
9+
use OCP\Migration\IOutput;
10+
use OCP\Migration\SimpleMigrationStep;
11+
12+
class Version00008Date20211114183344 extends SimpleMigrationStep {
13+
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
14+
/** @var ISchemaWrapper $schema */
15+
$schema = $schemaClosure();
16+
17+
$table = $schema->getTable('user_oidc_providers');
18+
$table->addColumn('bearer_secret', 'string', [
19+
'notnull' => true,
20+
'length' => 64,
21+
]);
22+
23+
return $schema;
24+
}
25+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* @copyright Copyright 2023, Julien Veyssier <julien-nc@posteo.net>
7+
*
8+
* @author B. Rederlechner <bernd.rederlechner@t-systems.com>
9+
*
10+
* @license GNU AGPL version 3 or any later version
11+
*
12+
* This program is free software: you can redistribute it and/or modify
13+
* it under the terms of the GNU Affero General Public License as
14+
* published by the Free Software Foundation, either version 3 of the
15+
* License, or (at your option) any later version.
16+
*
17+
* This program is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Affero General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU Affero General Public License
23+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
24+
*
25+
*/
26+
namespace OCA\UserOIDC\Migration;
27+
28+
use Closure;
29+
use OCP\DB\ISchemaWrapper;
30+
use OCP\DB\QueryBuilder\IQueryBuilder;
31+
use OCP\IDBConnection;
32+
use OCP\Migration\IOutput;
33+
use OCP\Migration\SimpleMigrationStep;
34+
use OCP\Security\ICrypto;
35+
36+
class Version010304Date20230902125945 extends SimpleMigrationStep {
37+
38+
/**
39+
* @var IDBConnection
40+
*/
41+
private $connection;
42+
/**
43+
* @var ICrypto
44+
*/
45+
private $crypto;
46+
47+
public function __construct(
48+
IDBConnection $connection,
49+
ICrypto $crypto,
50+
) {
51+
$this->connection = $connection;
52+
$this->crypto = $crypto;
53+
}
54+
55+
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
56+
/** @var ISchemaWrapper $schema */
57+
$schema = $schemaClosure();
58+
$tableName = 'user_oidc_providers';
59+
60+
if ($schema->hasTable($tableName)) {
61+
$table = $schema->getTable($tableName);
62+
if ($table->hasColumn('bearer_secret')) {
63+
$column = $table->getColumn('bearer_secret');
64+
$column->setLength(512);
65+
return $schema;
66+
}
67+
}
68+
69+
return null;
70+
}
71+
72+
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
73+
$tableName = 'user_oidc_providers';
74+
75+
// update secrets in user_oidc_providers and user_oidc_id4me
76+
$qbUpdate = $this->connection->getQueryBuilder();
77+
$qbUpdate->update($tableName)
78+
->set('bearer_secret', $qbUpdate->createParameter('updateSecret'))
79+
->where(
80+
$qbUpdate->expr()->eq('id', $qbUpdate->createParameter('updateId'))
81+
);
82+
83+
$qbSelect = $this->connection->getQueryBuilder();
84+
$qbSelect->select('id', 'bearer_secret')
85+
->from($tableName);
86+
$req = $qbSelect->executeQuery();
87+
while ($row = $req->fetch()) {
88+
$id = $row['id'];
89+
$secret = $row['bearer_secret'];
90+
$encryptedSecret = $this->crypto->encrypt($secret);
91+
$qbUpdate->setParameter('updateSecret', $encryptedSecret, IQueryBuilder::PARAM_STR);
92+
$qbUpdate->setParameter('updateId', $id, IQueryBuilder::PARAM_INT);
93+
$qbUpdate->executeStatement();
94+
}
95+
$req->closeCursor();
96+
}
97+
}

src/components/SettingsForm.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@
3232
:required="!update"
3333
autocomplete="off">
3434
</p>
35+
<p>
36+
<label for="oidc-bearer-secret">{{ t('user_oidc', 'Bearer shared secret') }}</label>
37+
<input id="oidc-bearer-secret"
38+
v-model="localProvider.bearerSecret"
39+
:placeholder="update ? t('user_oidc', 'Leave empty to keep existing') : null"
40+
type="text"
41+
:required="!update"
42+
autocomplete="off">
43+
</p>
3544
<p class="settings-hint warning-hint">
3645
<AlertOutlineIcon :size="20" class="icon" />
3746
{{ t('user_oidc', 'Warning, if the protocol of the URLs in the discovery content is HTTP, the ID token will be delivered through an insecure connection.') }}

0 commit comments

Comments
 (0)