Skip to content

Commit 83f4ec1

Browse files
feat: separate OIDC discovery from .well-known
Signed-off-by: The one with the braid <info@braid.business>
1 parent 590f349 commit 83f4ec1

File tree

2 files changed

+79
-57
lines changed

2 files changed

+79
-57
lines changed

lib/msc_extensions/msc_3861_native_oidc/msc2965_oidc_auth_metadata/msc2965_oidc_auth_metadata.dart

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,55 @@ import 'package:http/http.dart' hide Client;
55
import 'package:matrix/matrix.dart';
66

77
extension OidcProviderMetadataExtension on Client {
8+
/// High-level function to get the OIDC auth metadata for the homeserver
9+
///
10+
/// Performs checks on all three revisions of MSC2965 for OIDC discovery.
11+
///
12+
/// In case the homeserver supports OIDC, this will store the OIDC Auth
13+
/// Metadata provided by the homeserver.
14+
///
15+
/// This function might usually be called by [checkHomeserver]. Works similar
16+
/// to [getWellknown].
17+
Future<Map<String, Object?>?> getOidcDiscoveryInformation() async {
18+
Map<String, Object?>? oidcMetadata;
19+
20+
// MSC2965 no longer expects any information on whether OIDC is supported
21+
// to be present in .well-known - the only way to figure out is sadly
22+
// calling the /auth_metadata endpoint.
23+
24+
try {
25+
oidcMetadata = await getOidcAuthMetadata();
26+
} catch (e) {
27+
Logs().v(
28+
'[OIDC] auth_metadata endpoint not supported. '
29+
'Fallback on legacy .well-known discovery.',
30+
e,
31+
);
32+
}
33+
if (oidcMetadata == null) {
34+
try {
35+
// even though no longer required, a homeserver *might* still prefer
36+
// the fallback on .well-known discovery as per
37+
// https://openid.net/specs/openid-connect-discovery-1_0.html
38+
final issuer =
39+
// ignore: deprecated_member_use_from_same_package
40+
wellKnown?.authentication?.issuer ?? await oidcAuthIssuer();
41+
// ignore: deprecated_member_use_from_same_package
42+
oidcMetadata = await getOidcAuthWellKnown(issuer);
43+
} catch (e) {
44+
Logs().v('[OIDC] Homeserver does not support OIDC delegation.', e);
45+
}
46+
}
47+
if (oidcMetadata == null) {
48+
return null;
49+
}
50+
51+
Logs().v('[OIDC] Found auth metadata document.');
52+
53+
await database?.storeOidcAuthMetadata(oidcMetadata);
54+
return oidcMetadata;
55+
}
56+
857
/// Loads the Auth Metadata from the homeserver
958
///
1059
/// Even though homeservers might still use the previous proposed approaches

lib/src/client.dart

Lines changed: 30 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ class Client extends MatrixApi {
134134
/// the cached .well-known file updated using [getWellknown]
135135
DiscoveryInformation? get wellKnown => _wellKnown;
136136

137-
/// the cached OIDC auth metadata as per MSC 2965 updated using [getWellknown]
137+
/// the cached OIDC auth metadata as per MSC 2965 updated using
138+
/// [getOidcDiscoveryInformation]
138139
Map<String, Object?>? get oidcAuthMetadata => _oidcAuthMetadata;
139140

140141
/// the cached OIDC auth metadata as per MSC 2966
@@ -558,6 +559,7 @@ class Client extends MatrixApi {
558559
)> checkHomeserver(
559560
Uri homeserverUrl, {
560561
bool checkWellKnown = true,
562+
bool checkOidcDiscovery = true,
561563
Set<String>? overrideSupportedVersions,
562564
}) async {
563565
final supportedVersions =
@@ -575,15 +577,22 @@ class Client extends MatrixApi {
575577
Logs().v('Found no well known information', e);
576578
}
577579
}
580+
if (checkOidcDiscovery) {
581+
try {
582+
_oidcAuthMetadata = await getOidcDiscoveryInformation();
583+
} catch (e) {
584+
Logs().v('[OIDC] Error checking OIDC discovery', e);
585+
}
586+
}
578587

579588
// Check if server supports at least one supported version
580589
final versions = await getVersions();
581590
if (!versions.versions
582591
.any((version) => supportedVersions.contains(version))) {
583-
Logs().w(
584-
'Server supports the versions: ${versions.toString()} but this application is only compatible with ${supportedVersions.toString()}.',
592+
throw BadServerVersionsException(
593+
versions.versions.toSet(),
594+
supportedVersions,
585595
);
586-
assert(false);
587596
}
588597

589598
final loginTypes = await getLoginFlows() ?? [];
@@ -610,47 +619,16 @@ class Client extends MatrixApi {
610619
/// Note that this endpoint is not necessarily handled by the homeserver,
611620
/// but by another webserver, to be used for discovering the homeserver URL.
612621
///
613-
/// In case the homeserver supports OIDC, this will also request and store
614-
/// the OIDC Auth Metadata provided by the homeserver.
615-
///
616622
/// The result of this call is stored in [wellKnown] for later use at runtime.
617623
@override
618624
Future<DiscoveryInformation> getWellknown() async {
619-
DiscoveryInformation wellKnown;
620-
try {
621-
wellKnown = await super.getWellknown();
625+
final wellKnown = await super.getWellknown();
626+
627+
// do not reset the well known here, so super call
628+
super.homeserver = wellKnown.mHomeserver.baseUrl.stripTrailingSlash();
629+
_wellKnown = wellKnown;
630+
await database?.storeWellKnown(wellKnown);
622631

623-
// do not reset the well known here, so super call
624-
super.homeserver = wellKnown.mHomeserver.baseUrl.stripTrailingSlash();
625-
_wellKnown = wellKnown;
626-
await database?.storeWellKnown(wellKnown);
627-
} finally {
628-
// MSC2965 no longer expects any information on whether OIDC is supported
629-
// to be present in .well-known - the only way to figure out is sadly
630-
// calling the /auth_metadata endpoint.
631-
try {
632-
try {
633-
_oidcAuthMetadata = await getOidcAuthMetadata();
634-
} on http.ClientException {
635-
Logs().v(
636-
'[OIDC] auth_metadata endpoint not supported. '
637-
'Fallback on legacy .well-known discovery.',
638-
);
639-
// even though no longer required, a homeserver *might* still prefer
640-
// the fallback on .well-known discovery as per
641-
// https://openid.net/specs/openid-connect-discovery-1_0.html
642-
final issuer =
643-
// ignore: deprecated_member_use_from_same_package
644-
_wellKnown?.authentication?.issuer ?? await oidcAuthIssuer();
645-
// ignore: deprecated_member_use_from_same_package
646-
_oidcAuthMetadata = await getOidcAuthWellKnown(issuer);
647-
}
648-
await database?.storeOidcAuthMetadata(_oidcAuthMetadata);
649-
Logs().v('[OIDC] Found auth metadata document.');
650-
} on http.ClientException {
651-
Logs().v('[OIDC] Homeserver does not support OIDC delegation.');
652-
}
653-
}
654632
return wellKnown;
655633
}
656634

@@ -1704,22 +1682,7 @@ class Client extends MatrixApi {
17041682
return pushrules != null ? TryGetPushRule.tryFromJson(pushrules) : null;
17051683
}
17061684

1707-
static const Set<String> supportedVersions = {
1708-
'v1.1',
1709-
'v1.2',
1710-
'v1.3',
1711-
'v1.4',
1712-
'v1.5',
1713-
'v1.6',
1714-
'v1.7',
1715-
'v1.8',
1716-
'v1.9',
1717-
'v1.10',
1718-
'v1.11',
1719-
'v1.12',
1720-
'v1.13',
1721-
};
1722-
1685+
static const Set<String> supportedVersions = {'v1.1', 'v1.2'};
17231686
static const List<String> supportedDirectEncryptionAlgorithms = [
17241687
AlgorithmTypes.olmV1Curve25519AesSha2,
17251688
];
@@ -4091,6 +4054,16 @@ enum SyncStatus {
40914054
error,
40924055
}
40934056

4057+
class BadServerVersionsException implements Exception {
4058+
final Set<String> serverVersions, supportedVersions;
4059+
4060+
BadServerVersionsException(this.serverVersions, this.supportedVersions);
4061+
4062+
@override
4063+
String toString() =>
4064+
'Server supports the versions: ${serverVersions.toString()} but this application is only compatible with ${supportedVersions.toString()}.';
4065+
}
4066+
40944067
class BadServerLoginTypesException implements Exception {
40954068
final Set<String> serverLoginTypes, supportedLoginTypes;
40964069

0 commit comments

Comments
 (0)