Working impl

This commit is contained in:
Henry Hiles 2025-06-19 13:39:52 -04:00
commit 386f7fffd6
No known key found for this signature in database
9 changed files with 64 additions and 55 deletions

View file

@ -25,7 +25,6 @@ class ApiHelper {
final scope = data["scope"];
final nonce = data["nonce"];
// Basic validation
if ([
username,
password,
@ -33,13 +32,16 @@ class ApiHelper {
clientId,
nonce,
scope,
].any((v) => v == null)) {
].any((f) => f == null)) {
return Response(400, body: "Missing required field(s)");
}
// Matrix login
if (!Uri.parse(redirectUri!).host.endsWith(settings.serviceDomain)) {
return Response(403, body: "Redirect URI not allowed");
}
final loginRes = await http.post(
Uri.https(settings.homeserver, "_matrix/client/v3/login"),
Uri.parse("${settings.homeserver}/_matrix/client/v3/login"),
headers: {"Content-Type": "application/json"},
body: json.encode({
"type": "m.login.password",
@ -56,11 +58,9 @@ class ApiHelper {
final userId = loginData["user_id"];
final accessToken = loginData["access_token"];
// Request OpenID token from Matrix
final openidRes = await http.post(
Uri.https(
settings.homeserver,
"_matrix/client/v3/user/${Uri.encodeComponent(userId)}/openid/request",
Uri.parse(
"${settings.homeserver}/_matrix/client/v3/user/${Uri.encodeComponent(userId)}/openid/request_token",
),
headers: {"Authorization": "Bearer $accessToken"},
);
@ -73,7 +73,6 @@ class ApiHelper {
final openidToken = json.decode(openidRes.body)["access_token"];
// Generate and store authorization code
final code = base64Url.encode(
List<int>.generate(16, (_) => DateTime.now().millisecond % 256),
);
@ -85,7 +84,6 @@ class ApiHelper {
MatrixUser(userId: userId, matrixToken: openidToken, nonce: nonce!),
);
// Redirect back to client
return Response.found("$redirectUri?code=$code&state=$state");
}
@ -93,34 +91,38 @@ class ApiHelper {
final settings = ref.read(SettingsController.provider)!;
final body = Uri.splitQueryString(await request.readAsString());
final code = body["code"];
final clientId = body["client_id"];
if (code == null || clientId == null) {
return Response(400, body: "Missing code or client_id");
}
final codes = ref.read(AuthCodeController.provider);
if (code == null || !codes.containsKey(code)) {
if (!codes.containsKey(code)) {
return Response(400, body: "Invalid code");
}
final user = codes[code]!;
ref.read(AuthCodeController.provider.notifier).remove(code);
final secret = await File.fromUri(
Uri.file(settings.jwtSecretFile),
).readAsString();
final jwt = JWT(
{
"nonce": user.nonce,
"exp":
DateTime.now().add(Duration(minutes: 10)).millisecondsSinceEpoch ~/
DateTime.now().add(Duration(days: 7)).millisecondsSinceEpoch ~/
1000,
"iat": DateTime.now().millisecondsSinceEpoch ~/ 1000,
},
subject: user.userId,
issuer: ref.read(SettingsController.provider)!.issuer,
audience: Audience([body["client_id"]!]),
issuer: settings.issuer,
audience: Audience([clientId]),
);
final token = jwt.sign(
SecretKey(
await File.fromUri(Uri.file(settings.jwtSecretFile)).readAsString(),
),
algorithm: JWTAlgorithm.HS256,
);
final token = jwt.sign(SecretKey(secret), algorithm: JWTAlgorithm.HS256);
return Response.ok(
json.encode({
@ -143,9 +145,8 @@ class ApiHelper {
final token = auth.substring(7);
final matrixResp = await http.get(
Uri.https(
ref.read(SettingsController.provider)!.homeserver,
"_matrix/federation/v1/openid/userinfo",
Uri.parse(
"${ref.read(SettingsController.provider)!.homeserver}/_matrix/federation/v1/openid/userinfo",
),
headers: {"Authorization": "Bearer $token"},
);