Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117896103
D4899.1775372443.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
7 KB
Referenced Files
None
Subscribers
None
D4899.1775372443.diff
View Options
diff --git a/config.demo/src/database/seeds/PassportSeeder.php b/config.demo/src/database/seeds/PassportSeeder.php
--- a/config.demo/src/database/seeds/PassportSeeder.php
+++ b/config.demo/src/database/seeds/PassportSeeder.php
@@ -31,6 +31,21 @@
$client->id = \config('auth.proxy.client_id');
$client->save();
+ // Create a client for Webmail SSO
+ $client = Passport::client()->forceFill([
+ 'user_id' => null,
+ 'name' => 'Webmail SSO client',
+ 'secret' => \config('auth.sso.client_secret'),
+ 'provider' => 'users',
+ 'redirect' => 'https://' . \config('app.website_domain') . '/roundcubemail/index.php/login/oauth',
+ 'personal_access_client' => 0,
+ 'password_client' => 0,
+ 'revoked' => false,
+ 'allowed_scopes' => ['email', 'otp'],
+ ]);
+ $client->id = \config('auth.sso.client_id');
+ $client->save();
+
// Create a client for synapse oauth
$client = Passport::client()->forceFill([
'user_id' => null,
diff --git a/src/app/Auth/IdentityEntity.php b/src/app/Auth/IdentityEntity.php
--- a/src/app/Auth/IdentityEntity.php
+++ b/src/app/Auth/IdentityEntity.php
@@ -35,8 +35,16 @@
// TODO: Other claims
// TODO: Should we use this in AuthController::oauthUserInfo() for some de-duplicaton?
- return [
+ $claims = [
'email' => $this->user->email,
];
+
+ // Short living password for IMAP/SMTP
+ // We use same TTL as for the OAuth tokens, so clients can get a new password on token refresh
+ // TODO: We should create the password only when the access token scope requests it
+ $ttl = config('auth.token_expiry_minutes') * 60;
+ $claims['otp'] = Utils::tokenCreate((string) $this->user->id, $ttl);
+
+ return $claims;
}
}
diff --git a/src/app/Auth/Utils.php b/src/app/Auth/Utils.php
--- a/src/app/Auth/Utils.php
+++ b/src/app/Auth/Utils.php
@@ -10,10 +10,11 @@
* Create a simple authentication token
*
* @param string $userid User identifier
+ * @param int $ttl Token's time to live (in seconds)
*
* @return string|null Encrypted token, Null on failure
*/
- public static function tokenCreate($userid): ?string
+ public static function tokenCreate($userid, $ttl = 10): ?string
{
// Note: Laravel's Crypt::encryptString() creates output that is too long
// We need output string to be max. 127 characters. For that reason
@@ -23,7 +24,7 @@
$key = config('app.key');
$iv = random_bytes(openssl_cipher_iv_length($cipher));
- $data = $userid . '!' . now()->addSeconds(10)->format('YmdHis');
+ $data = $userid . '!' . now()->addSeconds($ttl)->format('YmdHis');
$value = openssl_encrypt($data, $cipher, $key, 0, $iv, $tag);
diff --git a/src/app/Http/Controllers/API/AuthController.php b/src/app/Http/Controllers/API/AuthController.php
--- a/src/app/Http/Controllers/API/AuthController.php
+++ b/src/app/Http/Controllers/API/AuthController.php
@@ -111,7 +111,10 @@
}
try {
- // league/oauth2-server/src/Grant/ code expects GET parameters, but we're using POST here
+ // OpenID handler reads parameters from the request query string (GET)
+ $request->query->replace($request->input());
+
+ // OAuth2 server's code also expects GET parameters, but we're using POST here
$psrRequest = $psrRequest->withQueryParams($request->input());
$authRequest = $server->validateAuthorizationRequest($psrRequest);
diff --git a/src/config/auth.php b/src/config/auth.php
--- a/src/config/auth.php
+++ b/src/config/auth.php
@@ -140,6 +140,11 @@
'client_secret' => env('PASSPORT_SYNAPSE_OAUTH_CLIENT_SECRET'),
],
+ 'sso' => [
+ 'client_id' => env('PASSPORT_WEBMAIL_SSO_CLIENT_ID'),
+ 'client_secret' => env('PASSPORT_WEBMAIL_SSO_CLIENT_SECRET'),
+ ],
+
'token_expiry_minutes' => env('OAUTH_TOKEN_EXPIRY', 60),
'refresh_token_expiry_minutes' => env('OAUTH_REFRESH_TOKEN_EXPIRY', 30 * 24 * 60),
];
diff --git a/src/config/openid.php b/src/config/openid.php
--- a/src/config/openid.php
+++ b/src/config/openid.php
@@ -14,6 +14,8 @@
// 'phone' => 'Information about your phone numbers',
// 'address' => 'Information about your address',
// 'login' => 'See your login information',
+ // FIXME: Need a better label, it's not really a one-time pass.
+ 'otp' => 'Temporary access to the account',
],
],
@@ -30,6 +32,9 @@
// 'company_phone',
// 'company_email',
// ],
+ 'otp' => [
+ 'otp',
+ ]
],
/**
diff --git a/src/resources/lang/en/auth.php b/src/resources/lang/en/auth.php
--- a/src/resources/lang/en/auth.php
+++ b/src/resources/lang/en/auth.php
@@ -21,7 +21,7 @@
'error.password' => "Invalid password",
'error.invalidrequest' => "Invalid authorization request.",
'error.geolocation' => "Country code mismatch",
- 'error.nofound' => "User not found",
+ 'error.notfound' => "User not found",
'error.2fa' => "Second factor failure",
'error.2fa-generic' => "Second factor failure",
diff --git a/src/tests/Feature/Controller/AuthTest.php b/src/tests/Feature/Controller/AuthTest.php
--- a/src/tests/Feature/Controller/AuthTest.php
+++ b/src/tests/Feature/Controller/AuthTest.php
@@ -471,15 +471,15 @@
public function testOIDCAuthorizationCodeFlow(): void
{
$user = $this->getTestUser('john@kolab.org');
- $client = \App\Auth\PassportClient::find(\config('auth.synapse.client_id'));
+ $client = \App\Auth\PassportClient::find(\config('auth.sso.client_id'));
// Note: Invalid input cases were tested above, we omit them here
- // This is essentially the same as for OAuth2, but with extended scope
+ // This is essentially the same as for OAuth2, but with extended scopes
$post = [
'client_id' => $client->id,
'response_type' => 'code',
- 'scope' => 'openid email',
+ 'scope' => 'openid email otp',
'state' => 'state',
'nonce' => 'nonce',
];
@@ -522,8 +522,10 @@
$this->assertSame('JWT', $token['typ']);
$this->assertSame('RS256', $token['alg']);
+ $this->assertSame('nonce', $token['nonce']);
$this->assertSame(url('/'), $token['iss']);
$this->assertSame($user->email, $token['email']);
+ $this->assertSame((string) $user->id, \App\Auth\Utils::tokenValidate($token['otp']));
// TODO: Validate JWT token properly
diff --git a/src/tests/Feature/Controller/WellKnownTest.php b/src/tests/Feature/Controller/WellKnownTest.php
--- a/src/tests/Feature/Controller/WellKnownTest.php
+++ b/src/tests/Feature/Controller/WellKnownTest.php
@@ -11,7 +11,7 @@
*/
public function testOpenidConfiguration(): void
{
- $href = \App\Utils::serviceUrl("/");
+ $href = \App\Utils::serviceUrl('/');
$response = $this->get('.well-known/openid-configuration');
$response->assertStatus(200)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 5, 7:00 AM (20 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18826066
Default Alt Text
D4899.1775372443.diff (7 KB)
Attached To
Mode
D4899: Single-Sign-On for Webmail
Attached
Detach File
Event Timeline