feat: add Linux OAuth adapters

Add a bounded libcurl transport with verified TLS, no redirects or retries, sanitized failures, binary-safe requests, and resolved-address enforcement for cleartext loopback traffic.

Add shell-free xdg-open launching and a one-shot IPv4 loopback callback receiver with strict HTTP/query parsing, deadlines, fixed callback path, and RAII cleanup. Token parsing, Secret Service, and Graph remain follow-up phases.
This commit is contained in:
2026-07-18 11:33:06 +01:00
parent dd6e02cb55
commit 295acbc125
12 changed files with 2095 additions and 28 deletions

View File

@@ -0,0 +1,45 @@
#pragma once
#include "nocal/sync/http.hpp"
#include <cstddef>
#include <stdexcept>
#include <string>
namespace nocal::sync {
class CurlHttpError : public std::runtime_error {
public:
enum class Kind {
invalid_request,
initialization_failed,
transport_failed,
response_too_large,
};
CurlHttpError(Kind kind, std::string message);
[[nodiscard]] Kind kind() const noexcept;
private:
Kind kind_;
};
struct CurlHttpOptions {
long connect_timeout_milliseconds{10'000};
long total_timeout_milliseconds{30'000};
std::size_t maximum_response_bytes{8U * 1024U * 1024U};
std::string user_agent{"nocal/0.1"};
};
class CurlHttpTransport final : public HttpTransport {
public:
explicit CurlHttpTransport(CurlHttpOptions options = {});
[[nodiscard]] HttpResponse send(const HttpRequest& request) override;
private:
CurlHttpOptions options_;
};
} // namespace nocal::sync

View File

@@ -0,0 +1,40 @@
#pragma once
#include "nocal/sync/oauth.hpp"
#include <chrono>
#include <memory>
#include <string>
namespace nocal::sync {
class XdgBrowserLauncher final : public BrowserLauncher {
public:
explicit XdgBrowserLauncher(std::string executable = "xdg-open");
void open(const std::string& url) override;
private:
std::string executable_;
};
class LoopbackCallbackReceiver final : public AuthorizationCallbackReceiver {
public:
explicit LoopbackCallbackReceiver(
std::chrono::milliseconds timeout = std::chrono::minutes{5});
~LoopbackCallbackReceiver();
LoopbackCallbackReceiver(const LoopbackCallbackReceiver&) = delete;
LoopbackCallbackReceiver& operator=(const LoopbackCallbackReceiver&) = delete;
LoopbackCallbackReceiver(LoopbackCallbackReceiver&&) noexcept;
LoopbackCallbackReceiver& operator=(LoopbackCallbackReceiver&&) noexcept;
[[nodiscard]] std::string redirect_uri() const override;
AuthorizationCallback receive() override;
private:
struct Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace nocal::sync