summaryrefslogtreecommitdiff
path: root/src/Controllers
diff options
context:
space:
mode:
authorDaniel Weipert <git@mail.dweipert.de>2025-08-20 14:58:10 +0200
committerDaniel Weipert <git@mail.dweipert.de>2025-08-20 14:58:10 +0200
commit6dc0447320272aaae51a98eb6606597019f986d3 (patch)
tree0acb527801a1d9eac943b5e0b0ccb33e610cd755 /src/Controllers
parentd08f4c83470c25d35d24594bd73e4effdac191a0 (diff)
login produces devices and tokens
Diffstat (limited to 'src/Controllers')
-rw-r--r--src/Controllers/KeyController.php34
-rw-r--r--src/Controllers/LoginController.php54
2 files changed, 77 insertions, 11 deletions
diff --git a/src/Controllers/KeyController.php b/src/Controllers/KeyController.php
index a999e40..5050d9b 100644
--- a/src/Controllers/KeyController.php
+++ b/src/Controllers/KeyController.php
@@ -2,6 +2,10 @@
namespace App\Controllers;
+use App\Errors\AppException;
+use App\Errors\ErrorCode;
+use App\Models\Tokens;
+use App\Support\RequestValidator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
@@ -29,4 +33,34 @@ class KeyController
public function query(string $serverName): Response
{}
+
+ /**
+ * POST /_matrix/client/v3/refresh
+ */
+ public function refresh(): Response
+ {
+ $request = Request::createFromGlobals();
+ RequestValidator::validateJson();
+ $body = json_decode($request->getContent(), true);
+
+ $tokens = Tokens::fetchWithRefreshToken($body["refresh_token"]);
+
+ if (empty($tokens)) {
+ throw new AppException(
+ ErrorCode::UNKNOWN_TOKEN,
+ "Soft logged out",
+ Response::HTTP_UNAUTHORIZED,
+ ["soft_logout" => true],
+ );
+ }
+
+ $newTokens = Tokens::new($tokens->getUserId(), $tokens->getDeviceId());
+ $newTokens->insert();
+
+ return new JsonResponse([
+ "access_token" => $newTokens->getAccessToken(),
+ "expires_in" => $newTokens->getExpiresIn(),
+ "refresh_token" => $newTokens->getRefreshToken(),
+ ]);
+ }
}
diff --git a/src/Controllers/LoginController.php b/src/Controllers/LoginController.php
index 1ff234c..fd48f25 100644
--- a/src/Controllers/LoginController.php
+++ b/src/Controllers/LoginController.php
@@ -7,7 +7,9 @@ use App\Errors\AppException;
use App\Errors\ErrorCode;
use App\Errors\UnknownError;
use App\Models\Device;
+use App\Models\Tokens;
use App\Models\User;
+use App\Support\RequestValidator;
use App\Types\LoginFlow;
use App\Types\LoginType;
use App\Types\UserRegistrationKind;
@@ -36,6 +38,7 @@ class LoginController
{
$request = Request::createFromGlobals();
$body = json_decode($request->getContent(), true);
+ RequestValidator::validateJson();
// validate login type
$loginType = null;
@@ -53,24 +56,43 @@ class LoginController
$user = User::fetchWithPassword($userId, $body["password"]);
if (! $user) {
- throw new AppException(ErrorCode::FORBIDDEN, "Invalid credentials.", Response::HTTP_FORBIDDEN);
+ throw new AppException(ErrorCode::FORBIDDEN, "Invalid credentials", Response::HTTP_FORBIDDEN);
}
$deviceId = $body["device_id"] ?? "";
- $device = $user->fetchDevice($deviceId);
- if (! $device) {
+ $device = null;
+ $tokens = null;
+
+ // create new device with tokens
+ if (empty($deviceId)) {
$device = Device::new(
$user->getId(),
initialDisplayName: $body["initial_device_display_name"] ?? "",
);
+ $device->insert();
+
+ $tokens = Tokens::new($userId, $device->getId());
+ $tokens->insert();
+ } else { // fetch existing device and tokens
+ $device = $user->fetchDevice($deviceId);
+ $tokens = Tokens::fetch($userId, $device->getId());
+
+ if (empty($tokens)) {
+ throw new AppException(
+ ErrorCode::UNKNOWN_TOKEN,
+ "Soft logged out",
+ Response::HTTP_UNAUTHORIZED,
+ ["soft_logout" => true],
+ );
+ }
}
return new JsonResponse([
- "access_token" => $device->getAccessToken(),
+ "access_token" => $tokens->getAccessToken(),
"device_id" => $device->getId(),
- "expires_in_ms" => 60000,
- "refresh_token" => $device->getRefreshToken(),
+ "expires_in_ms" => $tokens->getExpiresIn(),
+ "refresh_token" => $tokens->getRefreshToken(),
"user_id" => $user->getId(),
#"well_known" => [],
]);
@@ -83,8 +105,15 @@ class LoginController
{
$request = Request::createFromGlobals();
$body = json_decode($request->getContent(), true);
+ RequestValidator::validateJson();
- $kind = UserRegistrationKind::from($request->query->get("kind") ?? "user");
+ // validate kind
+ $kind = null;
+ try {
+ $kind = UserRegistrationKind::from($request->query->get("kind") ?? "user");
+ } catch (\ValueError $error) {
+ throw new UnknownError("Bad registration kind.", Response::HTTP_BAD_REQUEST);
+ }
$username = $body["username"];
$userId = "@$username:$_ENV[DOMAIN]";
@@ -95,16 +124,19 @@ class LoginController
]);
$device_id = $body["device_id"] ?? "";
- $initialDeviceDisplayName = $body["initialDeviceDisplayName"] ?? "";
+ $initialDeviceDisplayName = $body["initial_device_display_name"] ?? "";
$device = Device::new($userId, $device_id, $initialDeviceDisplayName);
$device->insert();
+ $tokens = Tokens::new($userId, $device->getId());
+ $tokens->insert();
+
return new JsonResponse([
- "access_token" => $device->getAccessToken(),
+ "access_token" => $tokens->getAccessToken(),
"device_id" => $device->getId(),
- "expires_in_ms" => 60000,
- "refresh_token" => $device->getRefreshToken(),
+ "expires_in_ms" => $tokens->getExpiresIn(),
+ "refresh_token" => $tokens->getRefreshToken(),
"user_id" => $userId,
]);
}