[pve-devel] [PATCH proxmox_dart_api_client 1/1] fix #4281: dart_api_client: Added functions for login with Open ID.

Alexander Abraham a.abraham at proxmox.com
Tue Apr 29 17:07:55 CEST 2025


 This commit contains a module for the Dart API client for
 the PVE Flutter app focussed on logging in with Open ID.
 The module provides a function for obtaining an authorization
 URL from an Open ID provider and a function for obtaining 
 a ticket from the PVE API from the redirect URL an Open ID
 provider sends the user to once they have logged into their
 Open ID provider.

Signed-off-by: Alexander Abraham <a.abraham at proxmox.com>
---
 lib/src/client.dart |   4 +-
 lib/src/oidc.dart   | 148 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+), 2 deletions(-)
 create mode 100644 lib/src/oidc.dart

diff --git a/lib/src/client.dart b/lib/src/client.dart
index f597c28..fdf5395 100644
--- a/lib/src/client.dart
+++ b/lib/src/client.dart
@@ -675,10 +675,10 @@ class ProxmoxApiClient extends http.BaseClient {
 
   Future<List<PveAccessDomainModel>> getAccessDomainsList() async {
     final path = '/api2/json/access/domains';
-    final response = await _getWithValidation(path, null);
+    final response = await _getWithValidation(path, null); 
     var data = (json.decode(response.body)['data'] as List).map((f) {
       return serializers.deserializeWith(PveAccessDomainModel.serializer, f);
     });
     return data.whereType<PveAccessDomainModel>().toList();
-  }
+  } 
 }
diff --git a/lib/src/oidc.dart b/lib/src/oidc.dart
new file mode 100644
index 0000000..fb42f0b
--- /dev/null
+++ b/lib/src/oidc.dart
@@ -0,0 +1,148 @@
+import 'dart:io';
+import 'dart:convert';
+import 'package:http/io_client.dart';
+import 'package:http/http.dart' as http;
+
+/// Returns the fetched authentication
+/// or an empty string if the request
+/// fails for any reason.
+Future<String> fetchOIDCAuthUrl(
+  String realm,
+  String host,
+  String redirectUrl
+) async {
+  String result = "";
+  Map<String,String> params = {
+    "realm": realm,
+    "redirect-url":"https://$redirectUrl"
+  };
+  String urlPath = "https://$host/api2/json/access/openid/auth-url";
+  try {
+    http.Client client = IOClient(
+      HttpClient()
+        ..badCertificateCallback = (
+          (
+            X509Certificate cert, 
+            String host, 
+            int port
+          ){
+            return true;
+          }
+      )
+    );
+    http.Response resp = await client.post(
+      Uri.parse(urlPath),
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      body: jsonEncode(params)
+    );
+    if (resp.statusCode == 200) {
+      result = (jsonDecode(resp.body) as Map<String,dynamic>)["data"];
+    }
+    else {
+      result = resp.body;
+    }
+  }
+  catch(e) {
+    result = e.toString();
+  }
+  return result;
+}
+
+/// Attempts to fetch the login credentials
+/// for Open ID logins from the PVE API.
+Future<String> fetchCredsWithPort(
+  String host, 
+  String port,
+  String code,
+  String state,
+)async {
+  var result = "";
+  Map<String,String> params = {
+      "code": code,
+      "redirect-url":"https://$host:$port",
+      "state": state
+    };
+    String urlPath = "https://$host:$port/api2/json/access/openid/login";
+    http.Client client = IOClient(
+      HttpClient()
+        ..badCertificateCallback = (
+          (
+            X509Certificate cert, 
+            String host, 
+            int port
+          ){
+            return true;
+          }
+      )
+    );
+    http.Response resp = await client.post(
+      Uri.parse(urlPath),
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      body: jsonEncode(params)
+    );
+    if (resp.statusCode == 200) {
+      result = resp.body;
+    }
+    else {
+      result = resp.body;
+    }
+    return result;
+}
+
+/// Returns the fetched credentials
+/// inside a JSON string. An empty
+/// string is returned if the
+/// request fails for any reason.
+Future<String> fetchOIDCCredentials(
+  String code,
+  String state,
+  String redirectUrl
+) async {
+  String result = ""; 
+  try {
+    result = await fetchCredsWithPort(
+      redirectUrl, 
+      "8006", 
+      code, 
+      state
+    );
+  }
+  catch(e) {
+    try {
+      result = await fetchCredsWithPort(
+        redirectUrl, 
+        "443", 
+        code, 
+        state
+      );
+    }
+    catch(e){
+      result = e.toString();
+    }
+  }
+  return result;
+}
+
+/// Parses the URL an Open ID provider
+/// redirects to post-login and returns
+/// the parameters extracted from the URL
+/// for obtaining a ticket from the PVE
+/// API as key-value pairs.
+Map<String,String> parseUrl(String url){
+  Uri parsed = Uri.parse(url);
+  Map<String, String> params = parsed.queryParameters; 
+  String redirectUrl = parsed.host;
+  String stateCode = params["state"]!;
+  String statusCode = params["code"]!;
+  Map<String, String> result = Map();
+  result["state"] = stateCode;
+  result["code"] = statusCode;
+  result["host"] = redirectUrl;
+  return result;
+}
+
+
-- 
2.39.5





More information about the pve-devel mailing list