working a bit
This commit is contained in:
parent
217621daac
commit
93b6f180f6
7 changed files with 61 additions and 23 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
.dart_tool/
|
.dart_tool/
|
||||||
.direnv
|
.direnv
|
||||||
|
secret
|
9
.vscode/launch.json
vendored
9
.vscode/launch.json
vendored
|
@ -9,13 +9,14 @@
|
||||||
"program": "bin/matrixgate.dart",
|
"program": "bin/matrixgate.dart",
|
||||||
"args": [
|
"args": [
|
||||||
"--homeserver",
|
"--homeserver",
|
||||||
"foo",
|
"https://matrix.federated.nexus",
|
||||||
"--jwtSecretFile",
|
"--jwtSecretFile",
|
||||||
"foo",
|
"secret",
|
||||||
"--issuer",
|
"--issuer",
|
||||||
"http://localhost:8080",
|
"http://localhost:8080/",
|
||||||
"--authorizeEndpoint",
|
"--authorizeEndpoint",
|
||||||
"https://federated.nexus/login"
|
"http://localhost:4321/login"
|
||||||
|
// "https://federated.nexus/login"
|
||||||
],
|
],
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "dart"
|
"type": "dart"
|
||||||
|
|
|
@ -33,7 +33,7 @@ void main(List<String> argsRaw) async {
|
||||||
"/.well-known/openid-configuration",
|
"/.well-known/openid-configuration",
|
||||||
apiHelper.openidConfiguration,
|
apiHelper.openidConfiguration,
|
||||||
)
|
)
|
||||||
..get("/userInfo", apiHelper.userinfoHandler)
|
..get("/userinfo", apiHelper.userinfoHandler)
|
||||||
..get("/jwks.json", apiHelper.jwks)
|
..get("/jwks.json", apiHelper.jwks)
|
||||||
..post("/login", apiHelper.handleLogin)
|
..post("/login", apiHelper.handleLogin)
|
||||||
..post("/token", apiHelper.tokenHandler))
|
..post("/token", apiHelper.tokenHandler))
|
||||||
|
|
|
@ -21,9 +21,26 @@ class ApiHelper {
|
||||||
final password = data["password"];
|
final password = data["password"];
|
||||||
final redirectUri = data["redirect_uri"];
|
final redirectUri = data["redirect_uri"];
|
||||||
final state = data["state"] ?? "";
|
final state = data["state"] ?? "";
|
||||||
|
final clientId = data["client_id"];
|
||||||
|
final scope = data["scope"];
|
||||||
|
final nonce = data["nonce"];
|
||||||
|
|
||||||
|
// Basic validation
|
||||||
|
if ([
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
redirectUri,
|
||||||
|
clientId,
|
||||||
|
nonce,
|
||||||
|
scope,
|
||||||
|
].any((v) => v == null)) {
|
||||||
|
return Response(400, body: "Missing required field(s)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matrix login
|
||||||
final loginRes = await http.post(
|
final loginRes = await http.post(
|
||||||
Uri.https(settings.homeserver, "_matrix/client/v3/login"),
|
Uri.https(settings.homeserver, "_matrix/client/v3/login"),
|
||||||
|
headers: {"Content-Type": "application/json"},
|
||||||
body: json.encode({
|
body: json.encode({
|
||||||
"type": "m.login.password",
|
"type": "m.login.password",
|
||||||
"identifier": {"type": "m.id.user", "user": username},
|
"identifier": {"type": "m.id.user", "user": username},
|
||||||
|
@ -39,10 +56,11 @@ class ApiHelper {
|
||||||
final userId = loginData["user_id"];
|
final userId = loginData["user_id"];
|
||||||
final accessToken = loginData["access_token"];
|
final accessToken = loginData["access_token"];
|
||||||
|
|
||||||
|
// Request OpenID token from Matrix
|
||||||
final openidRes = await http.post(
|
final openidRes = await http.post(
|
||||||
Uri.https(
|
Uri.https(
|
||||||
settings.homeserver,
|
settings.homeserver,
|
||||||
"_matrix/client/v3/user/$userId/openid/request",
|
"_matrix/client/v3/user/${Uri.encodeComponent(userId)}/openid/request",
|
||||||
),
|
),
|
||||||
headers: {"Authorization": "Bearer $accessToken"},
|
headers: {"Authorization": "Bearer $accessToken"},
|
||||||
);
|
);
|
||||||
|
@ -55,13 +73,19 @@ class ApiHelper {
|
||||||
|
|
||||||
final openidToken = json.decode(openidRes.body)["access_token"];
|
final openidToken = json.decode(openidRes.body)["access_token"];
|
||||||
|
|
||||||
|
// Generate and store authorization code
|
||||||
final code = base64Url.encode(
|
final code = base64Url.encode(
|
||||||
List<int>.generate(16, (_) => DateTime.now().millisecond % 256),
|
List<int>.generate(16, (_) => DateTime.now().millisecond % 256),
|
||||||
);
|
);
|
||||||
|
|
||||||
ref
|
ref
|
||||||
.read(AuthCodeController.provider.notifier)
|
.read(AuthCodeController.provider.notifier)
|
||||||
.set(code, MatrixUser(userId: userId, matrixToken: openidToken));
|
.set(
|
||||||
|
code,
|
||||||
|
MatrixUser(userId: userId, matrixToken: openidToken, nonce: nonce!),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Redirect back to client
|
||||||
return Response.found("$redirectUri?code=$code&state=$state");
|
return Response.found("$redirectUri?code=$code&state=$state");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,10 +157,16 @@ class ApiHelper {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response.ok(matrixResp.body);
|
return Response.ok(
|
||||||
|
matrixResp.body,
|
||||||
|
headers: {"content-type": "application/json"},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Response jwks(_) => Response.ok(json.encode({"keys": []}));
|
Response jwks(_) => Response.ok(
|
||||||
|
json.encode({"keys": []}),
|
||||||
|
headers: {"content-type": "application/json"},
|
||||||
|
);
|
||||||
|
|
||||||
Response openidConfiguration(_) {
|
Response openidConfiguration(_) {
|
||||||
final settings = ref.read(SettingsController.provider)!;
|
final settings = ref.read(SettingsController.provider)!;
|
||||||
|
@ -145,7 +175,7 @@ class ApiHelper {
|
||||||
"issuer": settings.issuer,
|
"issuer": settings.issuer,
|
||||||
"authorization_endpoint": settings.authorizeEndpoint,
|
"authorization_endpoint": settings.authorizeEndpoint,
|
||||||
"token_endpoint": "${settings.issuer}/token",
|
"token_endpoint": "${settings.issuer}/token",
|
||||||
"userinfo_endpoint": "${settings.issuer}/userInfo",
|
"userinfo_endpoint": "${settings.issuer}/userinfo",
|
||||||
"jwks_uri": "${settings.issuer}/jwks.json",
|
"jwks_uri": "${settings.issuer}/jwks.json",
|
||||||
"response_types_supported": ["code"],
|
"response_types_supported": ["code"],
|
||||||
"subject_types_supported": ["public"],
|
"subject_types_supported": ["public"],
|
||||||
|
|
|
@ -8,6 +8,7 @@ abstract class MatrixUser with _$MatrixUser {
|
||||||
const factory MatrixUser({
|
const factory MatrixUser({
|
||||||
required String userId,
|
required String userId,
|
||||||
required String matrixToken,
|
required String matrixToken,
|
||||||
|
required String nonce,
|
||||||
}) = _MatrixUser;
|
}) = _MatrixUser;
|
||||||
|
|
||||||
factory MatrixUser.fromJson(Map<String, dynamic> json) =>
|
factory MatrixUser.fromJson(Map<String, dynamic> json) =>
|
||||||
|
|
|
@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$MatrixUser {
|
mixin _$MatrixUser {
|
||||||
|
|
||||||
String get userId; String get matrixToken;
|
String get userId; String get matrixToken; String get nonce;
|
||||||
/// Create a copy of MatrixUser
|
/// Create a copy of MatrixUser
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@ -29,16 +29,16 @@ $MatrixUserCopyWith<MatrixUser> get copyWith => _$MatrixUserCopyWithImpl<MatrixU
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
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)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,userId,matrixToken);
|
int get hashCode => Object.hash(runtimeType,userId,matrixToken,nonce);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
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;
|
factory $MatrixUserCopyWith(MatrixUser value, $Res Function(MatrixUser) _then) = _$MatrixUserCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String userId, String matrixToken
|
String userId, String matrixToken, String nonce
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,10 +66,11 @@ class _$MatrixUserCopyWithImpl<$Res>
|
||||||
|
|
||||||
/// Create a copy of MatrixUser
|
/// Create a copy of MatrixUser
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// 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 = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable
|
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,matrixToken: null == matrixToken ? _self.matrixToken : matrixToken // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,nonce: null == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
||||||
as String,
|
as String,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -81,11 +82,12 @@ as String,
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _MatrixUser implements MatrixUser {
|
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<String, dynamic> json) => _$MatrixUserFromJson(json);
|
factory _MatrixUser.fromJson(Map<String, dynamic> json) => _$MatrixUserFromJson(json);
|
||||||
|
|
||||||
@override final String userId;
|
@override final String userId;
|
||||||
@override final String matrixToken;
|
@override final String matrixToken;
|
||||||
|
@override final String nonce;
|
||||||
|
|
||||||
/// Create a copy of MatrixUser
|
/// Create a copy of MatrixUser
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@ -100,16 +102,16 @@ Map<String, dynamic> toJson() {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
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)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,userId,matrixToken);
|
int get hashCode => Object.hash(runtimeType,userId,matrixToken,nonce);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
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;
|
factory _$MatrixUserCopyWith(_MatrixUser value, $Res Function(_MatrixUser) _then) = __$MatrixUserCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String userId, String matrixToken
|
String userId, String matrixToken, String nonce
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,10 +139,11 @@ class __$MatrixUserCopyWithImpl<$Res>
|
||||||
|
|
||||||
/// Create a copy of MatrixUser
|
/// Create a copy of MatrixUser
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// 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 = null,}) {
|
||||||
return _then(_MatrixUser(
|
return _then(_MatrixUser(
|
||||||
userId: null == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable
|
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,matrixToken: null == matrixToken ? _self.matrixToken : matrixToken // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,nonce: null == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
||||||
as String,
|
as String,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,12 @@ part of 'matrix_user.dart';
|
||||||
_MatrixUser _$MatrixUserFromJson(Map<String, dynamic> json) => _MatrixUser(
|
_MatrixUser _$MatrixUserFromJson(Map<String, dynamic> json) => _MatrixUser(
|
||||||
userId: json['userId'] as String,
|
userId: json['userId'] as String,
|
||||||
matrixToken: json['matrixToken'] as String,
|
matrixToken: json['matrixToken'] as String,
|
||||||
|
nonce: json['nonce'] as String,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$MatrixUserToJson(_MatrixUser instance) =>
|
Map<String, dynamic> _$MatrixUserToJson(_MatrixUser instance) =>
|
||||||
<String, dynamic>{
|
<String, dynamic>{
|
||||||
'userId': instance.userId,
|
'userId': instance.userId,
|
||||||
'matrixToken': instance.matrixToken,
|
'matrixToken': instance.matrixToken,
|
||||||
|
'nonce': instance.nonce,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue