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', 'auth.token'], + ]); + $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['auth.token'] = 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,7 @@ // 'phone' => 'Information about your phone numbers', // 'address' => 'Information about your address', // 'login' => 'See your login information', + 'auth.token' => 'Kolab authentication token', ], ], @@ -30,6 +31,9 @@ // 'company_phone', // 'company_email', // ], + 'auth.token' => [ + 'auth.token', + ] ], /** diff --git a/src/resources/js/utils.js b/src/resources/js/utils.js --- a/src/resources/js/utils.js +++ b/src/resources/js/utils.js @@ -52,7 +52,7 @@ return result } -const loader = '