diff --git a/.vscode/launch.json b/.vscode/launch.json index 380f43f..1c64f63 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "name": "matrix-oauth2oidc", + "name": "matrixoidc", "program": "bin/matrixoidc.dart", "args": [ "--homeserver", @@ -13,7 +13,7 @@ "--jwtSecretFile", "secret", "--issuer", - "http://localhost:8080/", + "http://localhost:8080", "--authorizeEndpoint", "http://localhost:4321/login", "--serviceDomain", diff --git a/JUSTFILE b/JUSTFILE index c2af145..0a86649 100644 --- a/JUSTFILE +++ b/JUSTFILE @@ -5,4 +5,4 @@ build: dart run build_runner build test: - oauth2c http://localhost:8080 --client-id yourclientid --redirect-url http://localhost/callback --scopes openid --grant-type authorization_code --auth-method none --response-mode query \ No newline at end of file + oauth2c http://localhost:8080 --client-id yourclientid --scopes openid --grant-type authorization_code --auth-method none --response-mode query \ No newline at end of file diff --git a/bin/matrixoidc.dart b/bin/matrixoidc.dart index e405b09..1484caf 100644 --- a/bin/matrixoidc.dart +++ b/bin/matrixoidc.dart @@ -1,5 +1,5 @@ import "dart:io"; -import "package:args/args.dart"; +import "package:cli_tools/config.dart"; import "package:matrixoidc/controllers/settings_controller.dart"; import "package:matrixoidc/helpers/api_helper.dart"; import "package:riverpod/riverpod.dart"; @@ -8,18 +8,17 @@ import "package:shelf/shelf_io.dart"; import "package:shelf_router/shelf_router.dart"; void main(List argsRaw) async { - final parser = ArgParser() + final parser = ConfigParser() ..addOption("socket", abbr: "s") - ..addOption("serviceDomain", abbr: "d") ..addOption("port", abbr: "p", defaultsTo: "8080") ..addOption("address", abbr: "a", defaultsTo: "127.0.0.1") ..addOption("issuer", abbr: "i", mandatory: true) - ..addOption("homeserver", abbr: "h", mandatory: true) + ..addOption("homeserver", abbr: "u", mandatory: true) + ..addOption("serviceDomain", abbr: "d", mandatory: true) ..addOption("jwtSecretFile", abbr: "j", mandatory: true) ..addOption("authorizeEndpoint", abbr: "e", mandatory: true); final container = ProviderContainer(); - container .read(SettingsController.provider.notifier) .set(parser.parse(argsRaw)); @@ -35,8 +34,9 @@ void main(List argsRaw) async { apiHelper.openidConfiguration, ) ..get("/userinfo", apiHelper.userinfoHandler) - ..get("/jwks.json", apiHelper.jwks) - ..post("/login", apiHelper.handleLogin) + ..get("/bridge", apiHelper.bridgeHandler) + ..post("/login", apiHelper.loginHandler) + ..post("/logout", apiHelper.logoutHandler) ..post("/token", apiHelper.tokenHandler)) .call, ); diff --git a/flake.nix b/flake.nix index ae04dfa..76a116a 100644 --- a/flake.nix +++ b/flake.nix @@ -4,24 +4,40 @@ nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; }; - outputs = { - flake-parts, - nixpkgs, - self, - ... - } @ inputs: - flake-parts.lib.mkFlake {inherit inputs;} { + outputs = inputs: + inputs.flake-parts.lib.mkFlake {inherit inputs;} { systems = ["x86_64-linux" "aarch64-linux"]; perSystem = { + lib, pkgs, system, ... }: { - _module.args.pkgs = import nixpkgs {inherit system;}; + _module.args.pkgs = import inputs.nixpkgs {inherit system;}; devShells.default = pkgs.mkShell { buildInputs = with pkgs; [just dart oauth2c watchexec]; }; + + packages.default = pkgs.buildDartApplication { + pname = "matrixoidc"; + version = "1.0.0"; + src = ./.; + + dartConfigHook = "packageRun build_runner build"; + pubspecLock = lib.importJSON ./pubspec.lock.json; + + preInstall = "set -x"; + + meta = { + homepage = "https://git.federated.nexus/Henry-Hiles/matrixoidc"; + description = "An attempt to make an OIDC provider that authenticates with matrix OAuth."; + mainProgram = "matrixoidc"; + license = lib.licenses.gpl3Plus; + maintainers = [lib.maintainers.quadradical]; + }; + }; }; + flake.nixosModules.default = import ./module.nix inputs.self; }; } diff --git a/lib/controllers/key_controller.dart b/lib/controllers/key_controller.dart new file mode 100644 index 0000000..f11bdee --- /dev/null +++ b/lib/controllers/key_controller.dart @@ -0,0 +1,18 @@ +import "dart:io"; + +import "package:dart_jsonwebtoken/dart_jsonwebtoken.dart"; +import "package:matrixoidc/controllers/settings_controller.dart"; +import "package:riverpod/riverpod.dart"; + +class KeyController extends AsyncNotifier { + @override + Future build() async => SecretKey( + (await File.fromUri( + Uri.file(ref.read(SettingsController.provider)!.jwtSecretFile), + ).readAsString()).trim(), + ); + + static final provider = AsyncNotifierProvider( + KeyController.new, + ); +} diff --git a/lib/helpers/api_helper.dart b/lib/helpers/api_helper.dart index 6b55c18..fe0dad2 100644 --- a/lib/helpers/api_helper.dart +++ b/lib/helpers/api_helper.dart @@ -1,7 +1,7 @@ -import "dart:io"; import "dart:convert"; import "package:dart_jsonwebtoken/dart_jsonwebtoken.dart"; import "package:matrixoidc/controllers/auth_code_controller.dart"; +import "package:matrixoidc/controllers/key_controller.dart"; import "package:matrixoidc/controllers/settings_controller.dart"; import "package:shelf/shelf.dart"; import "package:http/http.dart" as http; @@ -12,7 +12,7 @@ class ApiHelper { final Ref ref; ApiHelper(this.ref); - Future handleLogin(Request request) async { + Future loginHandler(Request request) async { final body = await request.readAsString(); final data = Uri.splitQueryString(body); @@ -22,7 +22,7 @@ class ApiHelper { final state = data["state"] ?? ""; if (userId == null || accessToken == null || redirectUri == null) { - return Response(400, body: "Missing parameters"); + return Response(400, body: json.encode({"error": "Missing parameters"})); } final settings = ref.read(SettingsController.provider)!; @@ -32,7 +32,9 @@ class ApiHelper { ); if (whoamiRes.statusCode != 200) { - return Response.forbidden("Access token validation failed"); + return Response.forbidden( + json.encode({"error": "Access token validation failed"}), + ); } final code = base64Url.encode( @@ -41,9 +43,60 @@ class ApiHelper { ref .read(AuthCodeController.provider.notifier) - .set(code, MatrixUser(userId: userId, matrixToken: accessToken)); + .set( + code, + MatrixUser( + userId: userId, + matrixToken: accessToken, + nonce: data["nonce"], + ), + ); - return Response.found("$redirectUri?code=$code&state=$state"); + final uri = Uri.parse(redirectUri); + + return Response.found( + uri.replace( + queryParameters: { + ...uri.queryParameters, + "code": code, + "state": state, + "nonce": data["nonce"], + }, + ), + ); + } + + Future bridgeHandler(Request request) async { + final query = request.url.queryParameters; + final code = query["code"]; + final redirectUri = query["redirect_uri"]; + + if (code == null || redirectUri == null) { + return Response( + 400, + body: json.encode({"error": "Missing code or redirect_uri"}), + ); + } + + final tokenRes = await tokenHandler( + Request( + "POST", + Uri.base, + body: utf8.encode("code=$code&client_id=proxy"), + ), + ); + + if (tokenRes.statusCode != 200) { + return Response(400, body: json.encode({"error": "Token post failed"})); + } + + return Response.found( + redirectUri, + headers: { + "set-cookie": + "id_token=${json.decode(await tokenRes.readAsString())["id_token"]}; Path=/; Secure; HttpOnly; SameSite=Lax; Domain=.${ref.watch(SettingsController.provider)!.serviceDomain}; Max-Age=604800", + }, + ); } Future tokenHandler(Request request) async { @@ -53,26 +106,26 @@ class ApiHelper { final clientId = body["client_id"]; if (code == null || clientId == null) { - return Response(400, body: "Missing code or client_id"); + return Response( + 400, + body: json.encode({"error": "Missing code or client_id"}), + ); } final codes = ref.read(AuthCodeController.provider); if (!codes.containsKey(code)) { - return Response(400, body: "Invalid code"); + return Response(400, body: json.encode({"error": "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( { "exp": DateTime.now().add(Duration(days: 7)).millisecondsSinceEpoch ~/ 1000, + "nonce": user.nonce, "iat": DateTime.now().millisecondsSinceEpoch ~/ 1000, }, subject: user.userId, @@ -80,13 +133,16 @@ class ApiHelper { audience: Audience([clientId]), ); - final token = jwt.sign(SecretKey(secret), algorithm: JWTAlgorithm.HS256); + final token = jwt.sign( + await ref.read(KeyController.provider.future), + algorithm: JWTAlgorithm.HS256, + ); return Response.ok( json.encode({ "id_token": token, + "access_token": token, "token_type": "Bearer", - "expires_in": 600, }), headers: {"Content-Type": "application/json"}, ); @@ -102,14 +158,33 @@ class ApiHelper { final token = auth.substring(7); final jwt = JWT.verify( token, - SecretKey( - await File.fromUri( - Uri.file(ref.read(SettingsController.provider)!.jwtSecretFile), - ).readAsString(), + await ref.read(KeyController.provider.future), + ); + + final settings = ref.read(SettingsController.provider)!; + final profile = await http.get( + Uri.parse( + "${settings.homeserver}/_matrix/client/v3/profile/${jwt.subject}", ), ); + + if (profile.statusCode != 200) { + return Response.forbidden( + json.encode({"error": "Access token validation failed"}), + ); + } + + final fullName = (json.decode(profile.body)["displayname"] as String); + final name = fullName.length <= 20 ? fullName : fullName.substring(0, 20); + return Response.ok( - jsonEncode({"sub": jwt.subject}), + jsonEncode({ + "sub": jwt.subject, + "name": name, + "first_name": name, + "last_name": "", + "nickname": name, + }), headers: {"Content-Type": "application/json"}, ); } catch (e) { @@ -117,10 +192,29 @@ class ApiHelper { } } - Response jwks(_) => Response.ok( - json.encode({"keys": []}), - headers: {"content-type": "application/json"}, - ); + Future introspectionHandler(Request request) async { + final token = Uri.splitQueryString(await request.readAsString())["token"]; + if (token == null) { + return Response(400, body: json.encode({"error": "Missing token"})); + } + + try { + JWT.verify(token, await ref.read(KeyController.provider.future)); + + return Response.ok( + json.encode({"active": true}), + headers: {"content-type": "application/json"}, + ); + } catch (_) { + return Response.ok( + json.encode({"active": false}), + headers: {"content-type": "application/json"}, + ); + } + } + + Future logoutHandler(Request request) async => + Response.ok(json.encode("Log out is not currently implemented")); Response openidConfiguration(_) { final settings = ref.read(SettingsController.provider)!; @@ -130,7 +224,8 @@ class ApiHelper { "authorization_endpoint": settings.authorizeEndpoint, "token_endpoint": "${settings.issuer}/token", "userinfo_endpoint": "${settings.issuer}/userinfo", - "jwks_uri": "${settings.issuer}/jwks.json", + "introspection_endpoint": "${settings.issuer}/introspect", + "end_session_endpoint": "#", "response_types_supported": ["code"], "subject_types_supported": ["public"], "id_token_signing_alg_values_supported": ["HS256"], diff --git a/lib/models/matrix_user.dart b/lib/models/matrix_user.dart index 805fb3f..d763865 100644 --- a/lib/models/matrix_user.dart +++ b/lib/models/matrix_user.dart @@ -8,6 +8,7 @@ abstract class MatrixUser with _$MatrixUser { const factory MatrixUser({ required String userId, required String matrixToken, + required String? nonce, }) = _MatrixUser; factory MatrixUser.fromJson(Map json) => diff --git a/lib/models/matrix_user.freezed.dart b/lib/models/matrix_user.freezed.dart index 94504e8..e9eaf24 100644 --- a/lib/models/matrix_user.freezed.dart +++ b/lib/models/matrix_user.freezed.dart @@ -4,7 +4,7 @@ // ignore_for_file: type=lint // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark -part of "matrix_user.dart"; +part of 'matrix_user.dart'; // ************************************************************************** // FreezedGenerator @@ -16,11 +16,11 @@ T _$identity(T value) => value; /// @nodoc mixin _$MatrixUser { - String get userId; String get matrixToken; + String get userId; String get matrixToken; String? get nonce; /// Create a copy of MatrixUser /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) -@pragma("vm:prefer-inline") +@pragma('vm:prefer-inline') $MatrixUserCopyWith get copyWith => _$MatrixUserCopyWithImpl(this as MatrixUser, _$identity); /// Serializes this MatrixUser to a JSON map. @@ -29,16 +29,16 @@ $MatrixUserCopyWith get copyWith => _$MatrixUserCopyWithImpl Object.hash(runtimeType,userId,matrixToken); +int get hashCode => Object.hash(runtimeType,userId,matrixToken,nonce); @override String toString() { - return "MatrixUser(userId: $userId, matrixToken: $matrixToken)"; + return 'MatrixUser(userId: $userId, matrixToken: $matrixToken, nonce: $nonce)'; } @@ -49,7 +49,7 @@ abstract mixin class $MatrixUserCopyWith<$Res> { factory $MatrixUserCopyWith(MatrixUser value, $Res Function(MatrixUser) _then) = _$MatrixUserCopyWithImpl; @useResult $Res call({ - String userId, String matrixToken + String userId, String matrixToken, String? nonce }); @@ -66,11 +66,12 @@ class _$MatrixUserCopyWithImpl<$Res> /// Create a copy of MatrixUser /// with the given fields replaced by the non-null parameter values. -@pragma("vm:prefer-inline") @override $Res call({Object? userId = null,Object? matrixToken = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? userId = null,Object? matrixToken = null,Object? nonce = freezed,}) { return _then(_self.copyWith( userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable as String,matrixToken: null == matrixToken ? _self.matrixToken : matrixToken // ignore: cast_nullable_to_non_nullable -as String, +as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable +as String?, )); } @@ -81,16 +82,17 @@ as String, @JsonSerializable() class _MatrixUser implements MatrixUser { - const _MatrixUser({required this.userId, required this.matrixToken}); + const _MatrixUser({required this.userId, required this.matrixToken, required this.nonce}); factory _MatrixUser.fromJson(Map json) => _$MatrixUserFromJson(json); @override final String userId; @override final String matrixToken; +@override final String? nonce; /// Create a copy of MatrixUser /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) -@pragma("vm:prefer-inline") +@pragma('vm:prefer-inline') _$MatrixUserCopyWith<_MatrixUser> get copyWith => __$MatrixUserCopyWithImpl<_MatrixUser>(this, _$identity); @override @@ -100,16 +102,16 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _MatrixUser&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.matrixToken, matrixToken) || other.matrixToken == matrixToken)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _MatrixUser&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.matrixToken, matrixToken) || other.matrixToken == matrixToken)&&(identical(other.nonce, nonce) || other.nonce == nonce)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,userId,matrixToken); +int get hashCode => Object.hash(runtimeType,userId,matrixToken,nonce); @override String toString() { - return "MatrixUser(userId: $userId, matrixToken: $matrixToken)"; + return 'MatrixUser(userId: $userId, matrixToken: $matrixToken, nonce: $nonce)'; } @@ -120,7 +122,7 @@ abstract mixin class _$MatrixUserCopyWith<$Res> implements $MatrixUserCopyWith<$ factory _$MatrixUserCopyWith(_MatrixUser value, $Res Function(_MatrixUser) _then) = __$MatrixUserCopyWithImpl; @override @useResult $Res call({ - String userId, String matrixToken + String userId, String matrixToken, String? nonce }); @@ -137,11 +139,12 @@ class __$MatrixUserCopyWithImpl<$Res> /// Create a copy of MatrixUser /// with the given fields replaced by the non-null parameter values. -@override @pragma("vm:prefer-inline") $Res call({Object? userId = null,Object? matrixToken = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? userId = null,Object? matrixToken = null,Object? nonce = freezed,}) { return _then(_MatrixUser( userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable as String,matrixToken: null == matrixToken ? _self.matrixToken : matrixToken // ignore: cast_nullable_to_non_nullable -as String, +as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable +as String?, )); } diff --git a/lib/models/matrix_user.g.dart b/lib/models/matrix_user.g.dart index 95e855f..d9f38c8 100644 --- a/lib/models/matrix_user.g.dart +++ b/lib/models/matrix_user.g.dart @@ -1,18 +1,20 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of "matrix_user.dart"; +part of 'matrix_user.dart'; // ************************************************************************** // JsonSerializableGenerator // ************************************************************************** _MatrixUser _$MatrixUserFromJson(Map json) => _MatrixUser( - userId: json["userId"] as String, - matrixToken: json["matrixToken"] as String, + userId: json['userId'] as String, + matrixToken: json['matrixToken'] as String, + nonce: json['nonce'] as String?, ); Map _$MatrixUserToJson(_MatrixUser instance) => { - "userId": instance.userId, - "matrixToken": instance.matrixToken, + 'userId': instance.userId, + 'matrixToken': instance.matrixToken, + 'nonce': instance.nonce, }; diff --git a/lib/models/settings.dart b/lib/models/settings.dart index 6d7a895..87af5e9 100644 --- a/lib/models/settings.dart +++ b/lib/models/settings.dart @@ -7,11 +7,11 @@ part "settings.g.dart"; abstract class Settings with _$Settings { const factory Settings({ required String? socket, + required String serviceDomain, required String address, required String port, required String homeserver, required String issuer, - required String serviceDomain, required String jwtSecretFile, required String authorizeEndpoint, }) = _Settings; diff --git a/lib/models/settings.freezed.dart b/lib/models/settings.freezed.dart index 8376cab..a88af64 100644 --- a/lib/models/settings.freezed.dart +++ b/lib/models/settings.freezed.dart @@ -16,7 +16,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$Settings { - String? get socket; String get address; String get port; String get homeserver; String get issuer; String get serviceDomain; String get jwtSecretFile; String get authorizeEndpoint; + String? get socket; String get serviceDomain; String get address; String get port; String get homeserver; String get issuer; String get jwtSecretFile; String get authorizeEndpoint; /// Create a copy of Settings /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -29,16 +29,16 @@ $SettingsCopyWith get copyWith => _$SettingsCopyWithImpl(thi @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is Settings&&(identical(other.socket, socket) || other.socket == socket)&&(identical(other.address, address) || other.address == address)&&(identical(other.port, port) || other.port == port)&&(identical(other.homeserver, homeserver) || other.homeserver == homeserver)&&(identical(other.issuer, issuer) || other.issuer == issuer)&&(identical(other.serviceDomain, serviceDomain) || other.serviceDomain == serviceDomain)&&(identical(other.jwtSecretFile, jwtSecretFile) || other.jwtSecretFile == jwtSecretFile)&&(identical(other.authorizeEndpoint, authorizeEndpoint) || other.authorizeEndpoint == authorizeEndpoint)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is Settings&&(identical(other.socket, socket) || other.socket == socket)&&(identical(other.serviceDomain, serviceDomain) || other.serviceDomain == serviceDomain)&&(identical(other.address, address) || other.address == address)&&(identical(other.port, port) || other.port == port)&&(identical(other.homeserver, homeserver) || other.homeserver == homeserver)&&(identical(other.issuer, issuer) || other.issuer == issuer)&&(identical(other.jwtSecretFile, jwtSecretFile) || other.jwtSecretFile == jwtSecretFile)&&(identical(other.authorizeEndpoint, authorizeEndpoint) || other.authorizeEndpoint == authorizeEndpoint)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,socket,address,port,homeserver,issuer,serviceDomain,jwtSecretFile,authorizeEndpoint); +int get hashCode => Object.hash(runtimeType,socket,serviceDomain,address,port,homeserver,issuer,jwtSecretFile,authorizeEndpoint); @override String toString() { - return "Settings(socket: $socket, address: $address, port: $port, homeserver: $homeserver, issuer: $issuer, serviceDomain: $serviceDomain, jwtSecretFile: $jwtSecretFile, authorizeEndpoint: $authorizeEndpoint)"; + return "Settings(socket: $socket, serviceDomain: $serviceDomain, address: $address, port: $port, homeserver: $homeserver, issuer: $issuer, jwtSecretFile: $jwtSecretFile, authorizeEndpoint: $authorizeEndpoint)"; } @@ -49,7 +49,7 @@ abstract mixin class $SettingsCopyWith<$Res> { factory $SettingsCopyWith(Settings value, $Res Function(Settings) _then) = _$SettingsCopyWithImpl; @useResult $Res call({ - String? socket, String address, String port, String homeserver, String issuer, String serviceDomain, String jwtSecretFile, String authorizeEndpoint + String? socket, String serviceDomain, String address, String port, String homeserver, String issuer, String jwtSecretFile, String authorizeEndpoint }); @@ -66,14 +66,14 @@ class _$SettingsCopyWithImpl<$Res> /// Create a copy of Settings /// with the given fields replaced by the non-null parameter values. -@pragma("vm:prefer-inline") @override $Res call({Object? socket = freezed,Object? address = null,Object? port = null,Object? homeserver = null,Object? issuer = null,Object? serviceDomain = null,Object? jwtSecretFile = null,Object? authorizeEndpoint = null,}) { +@pragma("vm:prefer-inline") @override $Res call({Object? socket = freezed,Object? serviceDomain = null,Object? address = null,Object? port = null,Object? homeserver = null,Object? issuer = null,Object? jwtSecretFile = null,Object? authorizeEndpoint = null,}) { return _then(_self.copyWith( socket: freezed == socket ? _self.socket : socket // ignore: cast_nullable_to_non_nullable -as String?,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable +as String?,serviceDomain: null == serviceDomain ? _self.serviceDomain : serviceDomain // ignore: cast_nullable_to_non_nullable +as String,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable as String,port: null == port ? _self.port : port // ignore: cast_nullable_to_non_nullable as String,homeserver: null == homeserver ? _self.homeserver : homeserver // ignore: cast_nullable_to_non_nullable as String,issuer: null == issuer ? _self.issuer : issuer // ignore: cast_nullable_to_non_nullable -as String,serviceDomain: null == serviceDomain ? _self.serviceDomain : serviceDomain // ignore: cast_nullable_to_non_nullable as String,jwtSecretFile: null == jwtSecretFile ? _self.jwtSecretFile : jwtSecretFile // ignore: cast_nullable_to_non_nullable as String,authorizeEndpoint: null == authorizeEndpoint ? _self.authorizeEndpoint : authorizeEndpoint // ignore: cast_nullable_to_non_nullable as String, @@ -87,15 +87,15 @@ as String, @JsonSerializable() class _Settings implements Settings { - const _Settings({required this.socket, required this.address, required this.port, required this.homeserver, required this.issuer, required this.serviceDomain, required this.jwtSecretFile, required this.authorizeEndpoint}); + const _Settings({required this.socket, required this.serviceDomain, required this.address, required this.port, required this.homeserver, required this.issuer, required this.jwtSecretFile, required this.authorizeEndpoint}); factory _Settings.fromJson(Map json) => _$SettingsFromJson(json); @override final String? socket; +@override final String serviceDomain; @override final String address; @override final String port; @override final String homeserver; @override final String issuer; -@override final String serviceDomain; @override final String jwtSecretFile; @override final String authorizeEndpoint; @@ -112,16 +112,16 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _Settings&&(identical(other.socket, socket) || other.socket == socket)&&(identical(other.address, address) || other.address == address)&&(identical(other.port, port) || other.port == port)&&(identical(other.homeserver, homeserver) || other.homeserver == homeserver)&&(identical(other.issuer, issuer) || other.issuer == issuer)&&(identical(other.serviceDomain, serviceDomain) || other.serviceDomain == serviceDomain)&&(identical(other.jwtSecretFile, jwtSecretFile) || other.jwtSecretFile == jwtSecretFile)&&(identical(other.authorizeEndpoint, authorizeEndpoint) || other.authorizeEndpoint == authorizeEndpoint)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _Settings&&(identical(other.socket, socket) || other.socket == socket)&&(identical(other.serviceDomain, serviceDomain) || other.serviceDomain == serviceDomain)&&(identical(other.address, address) || other.address == address)&&(identical(other.port, port) || other.port == port)&&(identical(other.homeserver, homeserver) || other.homeserver == homeserver)&&(identical(other.issuer, issuer) || other.issuer == issuer)&&(identical(other.jwtSecretFile, jwtSecretFile) || other.jwtSecretFile == jwtSecretFile)&&(identical(other.authorizeEndpoint, authorizeEndpoint) || other.authorizeEndpoint == authorizeEndpoint)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,socket,address,port,homeserver,issuer,serviceDomain,jwtSecretFile,authorizeEndpoint); +int get hashCode => Object.hash(runtimeType,socket,serviceDomain,address,port,homeserver,issuer,jwtSecretFile,authorizeEndpoint); @override String toString() { - return "Settings(socket: $socket, address: $address, port: $port, homeserver: $homeserver, issuer: $issuer, serviceDomain: $serviceDomain, jwtSecretFile: $jwtSecretFile, authorizeEndpoint: $authorizeEndpoint)"; + return "Settings(socket: $socket, serviceDomain: $serviceDomain, address: $address, port: $port, homeserver: $homeserver, issuer: $issuer, jwtSecretFile: $jwtSecretFile, authorizeEndpoint: $authorizeEndpoint)"; } @@ -132,7 +132,7 @@ abstract mixin class _$SettingsCopyWith<$Res> implements $SettingsCopyWith<$Res> factory _$SettingsCopyWith(_Settings value, $Res Function(_Settings) _then) = __$SettingsCopyWithImpl; @override @useResult $Res call({ - String? socket, String address, String port, String homeserver, String issuer, String serviceDomain, String jwtSecretFile, String authorizeEndpoint + String? socket, String serviceDomain, String address, String port, String homeserver, String issuer, String jwtSecretFile, String authorizeEndpoint }); @@ -149,14 +149,14 @@ class __$SettingsCopyWithImpl<$Res> /// Create a copy of Settings /// with the given fields replaced by the non-null parameter values. -@override @pragma("vm:prefer-inline") $Res call({Object? socket = freezed,Object? address = null,Object? port = null,Object? homeserver = null,Object? issuer = null,Object? serviceDomain = null,Object? jwtSecretFile = null,Object? authorizeEndpoint = null,}) { +@override @pragma("vm:prefer-inline") $Res call({Object? socket = freezed,Object? serviceDomain = null,Object? address = null,Object? port = null,Object? homeserver = null,Object? issuer = null,Object? jwtSecretFile = null,Object? authorizeEndpoint = null,}) { return _then(_Settings( socket: freezed == socket ? _self.socket : socket // ignore: cast_nullable_to_non_nullable -as String?,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable +as String?,serviceDomain: null == serviceDomain ? _self.serviceDomain : serviceDomain // ignore: cast_nullable_to_non_nullable +as String,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable as String,port: null == port ? _self.port : port // ignore: cast_nullable_to_non_nullable as String,homeserver: null == homeserver ? _self.homeserver : homeserver // ignore: cast_nullable_to_non_nullable as String,issuer: null == issuer ? _self.issuer : issuer // ignore: cast_nullable_to_non_nullable -as String,serviceDomain: null == serviceDomain ? _self.serviceDomain : serviceDomain // ignore: cast_nullable_to_non_nullable as String,jwtSecretFile: null == jwtSecretFile ? _self.jwtSecretFile : jwtSecretFile // ignore: cast_nullable_to_non_nullable as String,authorizeEndpoint: null == authorizeEndpoint ? _self.authorizeEndpoint : authorizeEndpoint // ignore: cast_nullable_to_non_nullable as String, diff --git a/lib/models/settings.g.dart b/lib/models/settings.g.dart index 11a29e1..ed4b6ed 100644 --- a/lib/models/settings.g.dart +++ b/lib/models/settings.g.dart @@ -8,22 +8,22 @@ part of "settings.dart"; _Settings _$SettingsFromJson(Map json) => _Settings( socket: json["socket"] as String?, + serviceDomain: json["serviceDomain"] as String, address: json["address"] as String, port: json["port"] as String, homeserver: json["homeserver"] as String, issuer: json["issuer"] as String, - serviceDomain: json["serviceDomain"] as String, jwtSecretFile: json["jwtSecretFile"] as String, authorizeEndpoint: json["authorizeEndpoint"] as String, ); Map _$SettingsToJson(_Settings instance) => { "socket": instance.socket, + "serviceDomain": instance.serviceDomain, "address": instance.address, "port": instance.port, "homeserver": instance.homeserver, "issuer": instance.issuer, - "serviceDomain": instance.serviceDomain, "jwtSecretFile": instance.jwtSecretFile, "authorizeEndpoint": instance.authorizeEndpoint, }; diff --git a/module.nix b/module.nix new file mode 100644 index 0000000..dd3d9de --- /dev/null +++ b/module.nix @@ -0,0 +1,80 @@ +self: { + config, + lib, + pkgs, + utils, + ... +}: let + cfg = config.services.matrixoidc; +in { + meta.maintainers = with lib.maintainers; [quadradical]; + options.services.matrixoidc = { + enable = lib.mkEnableOption "the matrixoidc server"; + package = lib.mkPackageOption self.packages.${pkgs.system} "default" {}; + + jwtSecretFile = lib.mkOption { + type = lib.types.path; + }; + + group = lib.mkOption { + type = lib.types.str; + default = "matrixoidc"; + }; + + args = lib.mkOption { + type = with lib.types; listOf str; + default = []; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.matrixoidc = { + description = "matrixoidc server"; + documentation = ["https://git.federated.nexus/Henry-Hiles/matrixoidc"]; + wantedBy = ["multi-user.target"]; + wants = ["network-online.target"]; + after = ["network-online.target"]; + + serviceConfig = { + LoadCredential = ["matrixoidc-secrets:${cfg.jwtSecretFile}"]; + ExecStart = utils.escapeSystemdExecArgs ([ + (lib.getExe cfg.package) + "--jwtSecretFile=/run/credentials/matrixoidc.service/matrixoidc-secrets" + ] + ++ cfg.args); + DynamicUser = true; + LockPersonality = true; + MemoryDenyWriteExecute = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + PrivateDevices = true; + PrivateMounts = true; + RestrictAddressFamilies = [ + "AF_UNIX" + "AF_INET" + "AF_INET6" + ]; + RestrictNamespaces = true; + RestrictRealtime = true; + ProtectHome = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~@privileged" + "~@resources" + ]; + Restart = "aslways"; + RestartSec = 5; + UMask = 007; + + RuntimeDirectory = "matrixoidc"; + RuntimeDirectoryMode = 0770; + Group = cfg.group; + }; + }; + }; +} diff --git a/pubspec.lock b/pubspec.lock index 84ee519..b066feb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -121,6 +121,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.4" + ci: + dependency: transitive + description: + name: ci + sha256: "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13" + url: "https://pub.dev" + source: hosted + version: "0.1.0" + cli_tools: + dependency: "direct main" + description: + name: cli_tools + sha256: ed6d1cef6e34ff3d68e7c798c3d18f497a311ac8082533340a4a914b12344717 + url: "https://pub.dev" + source: hosted + version: "0.6.0" clock: dependency: transitive description: @@ -169,6 +185,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.2.0" + dart_mappable: + dependency: transitive + description: + name: dart_mappable + sha256: "2255b2c00e328a65fef5a8df2dabfc0dc9c2e518c33a50051a4519b1c7a28c48" + url: "https://pub.dev" + source: hosted + version: "4.5.0" dart_style: dependency: transitive description: @@ -353,6 +377,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + oauth2: + dependency: transitive + description: + name: oauth2 + sha256: c84470642cbb2bec450ccab2f8520c079cd1ca546a76ffd5c40589e07f4e8bf4 + url: "https://pub.dev" + source: hosted + version: "2.0.3" package_config: dependency: transitive description: @@ -385,6 +417,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + pub_api_client: + dependency: transitive + description: + name: pub_api_client + sha256: b9c0184ce4a562d8cf2ebd7be235a25aa158b7c01bdef863cccadc5894644e26 + url: "https://pub.dev" + source: hosted + version: "3.1.1" pub_semver: dependency: transitive description: @@ -401,6 +441,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.0" + rfc_6901: + dependency: transitive + description: + name: rfc_6901 + sha256: df1bbfa3d023009598f19636d6114c6ac1e0b7bb7bf6a260f0e6e6ce91416820 + url: "https://pub.dev" + source: hosted + version: "0.2.0" riverpod: dependency: "direct main" description: @@ -497,6 +545,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + super_string: + dependency: transitive + description: + name: super_string + sha256: ba41acf9fbb318b3fc0d57c9235779100394d85d83f45ab533615df1f3146ea7 + url: "https://pub.dev" + source: hosted + version: "1.0.3" term_glyph: dependency: transitive description: @@ -521,6 +577,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" + type_plus: + dependency: transitive + description: + name: type_plus + sha256: d5d1019471f0d38b91603adb9b5fd4ce7ab903c879d2fbf1a3f80a630a03fcc9 + url: "https://pub.dev" + source: hosted + version: "2.1.1" typed_data: dependency: transitive description: diff --git a/pubspec.lock.json b/pubspec.lock.json new file mode 100644 index 0000000..1037dc6 --- /dev/null +++ b/pubspec.lock.json @@ -0,0 +1,797 @@ +{ + "packages": { + "_fe_analyzer_shared": { + "dependency": "transitive", + "description": { + "name": "_fe_analyzer_shared", + "sha256": "e55636ed79578b9abca5fecf9437947798f5ef7456308b5cb85720b793eac92f", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "82.0.0" + }, + "adaptive_number": { + "dependency": "transitive", + "description": { + "name": "adaptive_number", + "sha256": "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.0.0" + }, + "analyzer": { + "dependency": "transitive", + "description": { + "name": "analyzer", + "sha256": "904ae5bb474d32c38fb9482e2d925d5454cda04ddd0e55d2e6826bc72f6ba8c0", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "7.4.5" + }, + "args": { + "dependency": "transitive", + "description": { + "name": "args", + "sha256": "d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.7.0" + }, + "async": { + "dependency": "transitive", + "description": { + "name": "async", + "sha256": "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.13.0" + }, + "boolean_selector": { + "dependency": "transitive", + "description": { + "name": "boolean_selector", + "sha256": "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.1.2" + }, + "build": { + "dependency": "transitive", + "description": { + "name": "build", + "sha256": "486337d40a48d75049f2a01efceefc1412e3a6d6342d39624753e7d5a4e70016", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.5.1" + }, + "build_config": { + "dependency": "transitive", + "description": { + "name": "build_config", + "sha256": "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.1.2" + }, + "build_daemon": { + "dependency": "transitive", + "description": { + "name": "build_daemon", + "sha256": "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "4.0.4" + }, + "build_resolvers": { + "dependency": "transitive", + "description": { + "name": "build_resolvers", + "sha256": "abe6e4b5b36ce2bf01aec8f2a59424d1ecfc3cb340e7145a64359adc7233a0d1", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.5.1" + }, + "build_runner": { + "dependency": "direct dev", + "description": { + "name": "build_runner", + "sha256": "398ec7898b9b60be126067835a8202240b26dc54aa34d91d0198a539dcd5942e", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.5.1" + }, + "build_runner_core": { + "dependency": "transitive", + "description": { + "name": "build_runner_core", + "sha256": "9821dbf604ed74a6dabeaba0c33ac58190332ea238862a62cdf25fc8eba226b8", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "9.0.1" + }, + "built_collection": { + "dependency": "transitive", + "description": { + "name": "built_collection", + "sha256": "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "5.1.1" + }, + "built_value": { + "dependency": "transitive", + "description": { + "name": "built_value", + "sha256": "082001b5c3dc495d4a42f1d5789990505df20d8547d42507c29050af6933ee27", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "8.10.1" + }, + "checked_yaml": { + "dependency": "transitive", + "description": { + "name": "checked_yaml", + "sha256": "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.0.4" + }, + "ci": { + "dependency": "transitive", + "description": { + "name": "ci", + "sha256": "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "0.1.0" + }, + "cli_tools": { + "dependency": "direct main", + "description": { + "name": "cli_tools", + "sha256": "ed6d1cef6e34ff3d68e7c798c3d18f497a311ac8082533340a4a914b12344717", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "0.6.0" + }, + "clock": { + "dependency": "transitive", + "description": { + "name": "clock", + "sha256": "fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.1.2" + }, + "code_builder": { + "dependency": "transitive", + "description": { + "name": "code_builder", + "sha256": "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "4.10.1" + }, + "collection": { + "dependency": "transitive", + "description": { + "name": "collection", + "sha256": "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.19.1" + }, + "convert": { + "dependency": "transitive", + "description": { + "name": "convert", + "sha256": "b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "3.1.2" + }, + "crypto": { + "dependency": "transitive", + "description": { + "name": "crypto", + "sha256": "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "3.0.6" + }, + "dart_jsonwebtoken": { + "dependency": "direct main", + "description": { + "name": "dart_jsonwebtoken", + "sha256": "21ce9f8a8712f741e8d6876a9c82c0f8a257fe928c4378a91d8527b92a3fd413", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "3.2.0" + }, + "dart_mappable": { + "dependency": "transitive", + "description": { + "name": "dart_mappable", + "sha256": "2255b2c00e328a65fef5a8df2dabfc0dc9c2e518c33a50051a4519b1c7a28c48", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "4.5.0" + }, + "dart_style": { + "dependency": "transitive", + "description": { + "name": "dart_style", + "sha256": "5b236382b47ee411741447c1f1e111459c941ea1b3f2b540dde54c210a3662af", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "3.1.0" + }, + "ed25519_edwards": { + "dependency": "transitive", + "description": { + "name": "ed25519_edwards", + "sha256": "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "0.3.1" + }, + "fast_immutable_collections": { + "dependency": "direct main", + "description": { + "name": "fast_immutable_collections", + "sha256": "d1aa3d7788fab06cce7f303f4969c7a16a10c865e1bd2478291a8ebcbee084e5", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "11.0.4" + }, + "file": { + "dependency": "transitive", + "description": { + "name": "file", + "sha256": "a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "7.0.1" + }, + "fixnum": { + "dependency": "transitive", + "description": { + "name": "fixnum", + "sha256": "b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.1.1" + }, + "freezed": { + "dependency": "direct dev", + "description": { + "name": "freezed", + "sha256": "6022db4c7bfa626841b2a10f34dd1e1b68e8f8f9650db6112dcdeeca45ca793c", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "3.0.6" + }, + "freezed_annotation": { + "dependency": "direct main", + "description": { + "name": "freezed_annotation", + "sha256": "c87ff004c8aa6af2d531668b46a4ea379f7191dc6dfa066acd53d506da6e044b", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "3.0.0" + }, + "frontend_server_client": { + "dependency": "transitive", + "description": { + "name": "frontend_server_client", + "sha256": "f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "4.0.0" + }, + "glob": { + "dependency": "transitive", + "description": { + "name": "glob", + "sha256": "c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.1.3" + }, + "graphs": { + "dependency": "transitive", + "description": { + "name": "graphs", + "sha256": "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.3.2" + }, + "http": { + "dependency": "direct main", + "description": { + "name": "http", + "sha256": "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.4.0" + }, + "http_methods": { + "dependency": "transitive", + "description": { + "name": "http_methods", + "sha256": "6bccce8f1ec7b5d701e7921dca35e202d425b57e317ba1a37f2638590e29e566", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.1.1" + }, + "http_multi_server": { + "dependency": "transitive", + "description": { + "name": "http_multi_server", + "sha256": "aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "3.2.2" + }, + "http_parser": { + "dependency": "transitive", + "description": { + "name": "http_parser", + "sha256": "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "4.1.2" + }, + "io": { + "dependency": "transitive", + "description": { + "name": "io", + "sha256": "dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.0.5" + }, + "js": { + "dependency": "transitive", + "description": { + "name": "js", + "sha256": "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "0.7.2" + }, + "json_annotation": { + "dependency": "direct main", + "description": { + "name": "json_annotation", + "sha256": "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "4.9.0" + }, + "json_serializable": { + "dependency": "direct dev", + "description": { + "name": "json_serializable", + "sha256": "c50ef5fc083d5b5e12eef489503ba3bf5ccc899e487d691584699b4bdefeea8c", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "6.9.5" + }, + "lints": { + "dependency": "direct dev", + "description": { + "name": "lints", + "sha256": "a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "6.0.0" + }, + "logging": { + "dependency": "transitive", + "description": { + "name": "logging", + "sha256": "c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.3.0" + }, + "matcher": { + "dependency": "transitive", + "description": { + "name": "matcher", + "sha256": "dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "0.12.17" + }, + "meta": { + "dependency": "transitive", + "description": { + "name": "meta", + "sha256": "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.17.0" + }, + "mime": { + "dependency": "transitive", + "description": { + "name": "mime", + "sha256": "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.0.0" + }, + "oauth2": { + "dependency": "transitive", + "description": { + "name": "oauth2", + "sha256": "c84470642cbb2bec450ccab2f8520c079cd1ca546a76ffd5c40589e07f4e8bf4", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.0.3" + }, + "package_config": { + "dependency": "transitive", + "description": { + "name": "package_config", + "sha256": "f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.2.0" + }, + "path": { + "dependency": "transitive", + "description": { + "name": "path", + "sha256": "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.9.1" + }, + "pointycastle": { + "dependency": "transitive", + "description": { + "name": "pointycastle", + "sha256": "92aa3841d083cc4b0f4709b5c74fd6409a3e6ba833ffc7dc6a8fee096366acf5", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "4.0.0" + }, + "pool": { + "dependency": "transitive", + "description": { + "name": "pool", + "sha256": "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.5.1" + }, + "pub_api_client": { + "dependency": "transitive", + "description": { + "name": "pub_api_client", + "sha256": "b9c0184ce4a562d8cf2ebd7be235a25aa158b7c01bdef863cccadc5894644e26", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "3.1.1" + }, + "pub_semver": { + "dependency": "transitive", + "description": { + "name": "pub_semver", + "sha256": "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.2.0" + }, + "pubspec_parse": { + "dependency": "transitive", + "description": { + "name": "pubspec_parse", + "sha256": "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.5.0" + }, + "rfc_6901": { + "dependency": "transitive", + "description": { + "name": "rfc_6901", + "sha256": "df1bbfa3d023009598f19636d6114c6ac1e0b7bb7bf6a260f0e6e6ce91416820", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "0.2.0" + }, + "riverpod": { + "dependency": "direct main", + "description": { + "name": "riverpod", + "sha256": "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.6.1" + }, + "shelf": { + "dependency": "direct main", + "description": { + "name": "shelf", + "sha256": "e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.4.2" + }, + "shelf_router": { + "dependency": "direct main", + "description": { + "name": "shelf_router", + "sha256": "f5e5d492440a7fb165fe1e2e1a623f31f734d3370900070b2b1e0d0428d59864", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.1.4" + }, + "shelf_web_socket": { + "dependency": "transitive", + "description": { + "name": "shelf_web_socket", + "sha256": "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "3.0.0" + }, + "source_gen": { + "dependency": "transitive", + "description": { + "name": "source_gen", + "sha256": "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.0.0" + }, + "source_helper": { + "dependency": "transitive", + "description": { + "name": "source_helper", + "sha256": "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.3.5" + }, + "source_span": { + "dependency": "transitive", + "description": { + "name": "source_span", + "sha256": "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.10.1" + }, + "stack_trace": { + "dependency": "transitive", + "description": { + "name": "stack_trace", + "sha256": "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.12.1" + }, + "state_notifier": { + "dependency": "transitive", + "description": { + "name": "state_notifier", + "sha256": "b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.0.0" + }, + "stream_channel": { + "dependency": "transitive", + "description": { + "name": "stream_channel", + "sha256": "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.1.4" + }, + "stream_transform": { + "dependency": "transitive", + "description": { + "name": "stream_transform", + "sha256": "ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.1.1" + }, + "string_scanner": { + "dependency": "transitive", + "description": { + "name": "string_scanner", + "sha256": "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.4.1" + }, + "super_string": { + "dependency": "transitive", + "description": { + "name": "super_string", + "sha256": "ba41acf9fbb318b3fc0d57c9235779100394d85d83f45ab533615df1f3146ea7", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.0.3" + }, + "term_glyph": { + "dependency": "transitive", + "description": { + "name": "term_glyph", + "sha256": "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.2.2" + }, + "test_api": { + "dependency": "transitive", + "description": { + "name": "test_api", + "sha256": "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "0.7.6" + }, + "timing": { + "dependency": "transitive", + "description": { + "name": "timing", + "sha256": "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.0.2" + }, + "type_plus": { + "dependency": "transitive", + "description": { + "name": "type_plus", + "sha256": "d5d1019471f0d38b91603adb9b5fd4ce7ab903c879d2fbf1a3f80a630a03fcc9", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "2.1.1" + }, + "typed_data": { + "dependency": "transitive", + "description": { + "name": "typed_data", + "sha256": "f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.4.0" + }, + "watcher": { + "dependency": "transitive", + "description": { + "name": "watcher", + "sha256": "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.1.2" + }, + "web": { + "dependency": "transitive", + "description": { + "name": "web", + "sha256": "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.1.1" + }, + "web_socket": { + "dependency": "transitive", + "description": { + "name": "web_socket", + "sha256": "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "1.0.1" + }, + "web_socket_channel": { + "dependency": "transitive", + "description": { + "name": "web_socket_channel", + "sha256": "d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "3.0.3" + }, + "yaml": { + "dependency": "transitive", + "description": { + "name": "yaml", + "sha256": "b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce", + "url": "https://pub.dev" + }, + "source": "hosted", + "version": "3.1.3" + } + }, + "sdks": { + "dart": ">=3.8.0 <4.0.0" + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 1daf022..8867bc5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,6 +2,8 @@ name: matrixoidc description: A minimal OpenID Connect provider backed by Matrix. version: 1.0.0 publish_to: none +executables: + matrixoidc: environment: sdk: ^3.8.0 @@ -14,8 +16,9 @@ dependencies: freezed_annotation: ^3.0.0 json_annotation: ^4.9.0 shelf_router: ^1.1.4 - args: ^2.7.0 fast_immutable_collections: ^11.0.4 + cli_tools: ^0.6.0 + args: ^2.7.0 dev_dependencies: build_runner: ^2.4.6