Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:ClickHouse ClickHouse Poco OAuth10Credentials

From Leeroopedia
Revision as of 14:38, 16 February 2026 by Admin (talk | contribs) (Auto-imported from implementations/ClickHouse_ClickHouse_Poco_OAuth10Credentials.md)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)


base/poco/Net/src/OAuth10Credentials.cpp:1-365 ClickHouse_ClickHouse ClickHouse_ClickHouse_HTTP_Authentication

Purpose

Implements the `Poco::Net::OAuth10Credentials` class, which provides OAuth 1.0 (RFC 5849) authentication for HTTP requests. The class supports both PLAINTEXT and HMAC-SHA1 signature methods, can sign outgoing requests and verify incoming ones, and constructs the `Authorization` header with proper OAuth parameter encoding.

Code Reference

HMAC-SHA1 Signature Creation

The `createSignature` method builds the signature base string and computes the HMAC-SHA1 digest:

std::string OAuth10Credentials::createSignature(
    const HTTPRequest& request, const std::string& uri,
    const HTMLForm& params, const std::string& nonce,
    const std::string& timestamp) const
{
    std::map<std::string, std::string> paramsMap;
    paramsMap["oauth_version"]          = "1.0";
    paramsMap["oauth_consumer_key"]     = percentEncode(_consumerKey);
    paramsMap["oauth_nonce"]            = percentEncode(nonce);
    paramsMap["oauth_signature_method"] = "HMAC-SHA1";
    paramsMap["oauth_timestamp"]        = timestamp;
    if (!_token.empty())
        paramsMap["oauth_token"] = percentEncode(_token);
    if (!_callback.empty())
        paramsMap["oauth_callback"] = percentEncode(_callback);
    for (auto it = params.begin(); it != params.end(); ++it)
        paramsMap[percentEncode(it->first)] = percentEncode(it->second);

    // Build sorted parameter string: key=value&key=value&...
    std::string paramsString;
    for (auto it = paramsMap.begin(); it != paramsMap.end(); ++it)
    {
        if (it != paramsMap.begin()) paramsString += '&';
        paramsString += it->first;
        paramsString += "=";
        paramsString += it->second;
    }

    // Signature base = METHOD&percentEncode(URI)&percentEncode(params)
    std::string signatureBase = request.getMethod();
    signatureBase += '&';
    signatureBase += percentEncode(uri);
    signatureBase += '&';
    signatureBase += percentEncode(paramsString);

    // Signing key = percentEncode(consumerSecret)&percentEncode(tokenSecret)
    std::string signingKey;
    signingKey += percentEncode(_consumerSecret);
    signingKey += '&';
    signingKey += percentEncode(_tokenSecret);

    Poco::HMACEngine<Poco::SHA1Engine> hmacEngine(signingKey);
    hmacEngine.update(signatureBase);
    Poco::DigestEngine::Digest digest = hmacEngine.digest();
    // Base64-encode the digest
    std::ostringstream digestBase64;
    Poco::Base64Encoder base64Encoder(digestBase64);
    base64Encoder.write(reinterpret_cast<char*>(&digest[0]), digest.size());
    base64Encoder.close();
    return digestBase64.str();
}

PLAINTEXT Signing

void OAuth10Credentials::signPlaintext(HTTPRequest& request) const
{
    std::string signature(percentEncode(_consumerSecret));
    signature += '&';
    signature += percentEncode(_tokenSecret);

    std::string authorization(SCHEME);
    // Append realm, consumer_key, signature, token, callback, version
    request.set(HTTPRequest::AUTHORIZATION, authorization);
}

Request Verification

bool OAuth10Credentials::verify(const HTTPRequest& request,
    const URI& uri, const HTMLForm& params)
{
    // Extract OAuth parameters from Authorization header
    // Recompute signature using extracted nonce and timestamp
    // Compare computed signature with provided signature
    return refSignature == signature;
}

Nonce Generation

std::string OAuth10Credentials::createNonce() const
{
    std::ostringstream base64Nonce;
    Poco::Base64Encoder base64Encoder(base64Nonce);
    Poco::RandomInputStream randomStream;
    for (int i = 0; i < 32; i++)
    {
        base64Encoder.put(randomStream.get());
    }
    base64Encoder.close();
    std::string nonce = base64Nonce.str();
    return Poco::translate(nonce, "+/=", "");
}

Credential Extraction from Request

OAuth10Credentials::OAuth10Credentials(const HTTPRequest& request)
{
    if (request.hasCredentials())
    {
        std::string authScheme;
        std::string authParams;
        request.getCredentials(authScheme, authParams);
        if (icompare(authScheme, SCHEME) == 0)
        {
            HTTPAuthenticationParams params(authParams);
            std::string consumerKey = params.get("oauth_consumer_key", "");
            URI::decode(consumerKey, _consumerKey);
            std::string token = params.get("oauth_token", "");
            URI::decode(token, _token);
            std::string callback = params.get("oauth_callback", "");
            URI::decode(callback, _callback);
        }
        else throw NotAuthenticatedException("No OAuth credentials in Authorization header");
    }
    else throw NotAuthenticatedException("No Authorization header found");
}

I/O Contract

Input Output Side Effects
Consumer key + secret, token + secret `OAuth10Credentials` object None
`HTTPRequest&` + `URI` via `authenticate` (HMAC-SHA1) None Sets `Authorization` header with OAuth params and HMAC-SHA1 signature
`HTTPRequest&` via `authenticate` (PLAINTEXT) None Sets `Authorization` header with plaintext signature
`HTTPRequest&` + `URI` via `verify` `bool` (signature valid) Extracts and decodes OAuth params from request; populates `_consumerKey`, `_token`, `_callback`
`HTTPRequest&` (constructor) `OAuth10Credentials` with extracted key/token/callback Throws `NotAuthenticatedException` if no OAuth credentials found
`createNonce` Random 32-byte Base64 string (without `+/=` characters) Reads from `Poco::RandomInputStream`

Usage Examples

// Signing a request with HMAC-SHA1
Poco::Net::OAuth10Credentials creds("consumerKey", "consumerSecret",
                                     "accessToken", "tokenSecret");
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, "/resource");
Poco::URI uri("https://api.example.com/resource");
creds.authenticate(request, uri, Poco::Net::OAuth10Credentials::SIGN_HMACSHA1);
// request now has Authorization header with OAuth signature

// Verifying an incoming request
Poco::Net::OAuth10Credentials serverCreds;
serverCreds.setConsumerSecret("consumerSecret");
serverCreds.setTokenSecret("tokenSecret");
bool valid = serverCreds.verify(incomingRequest, requestUri);

// Using PLAINTEXT signature
creds.authenticate(request, uri, Poco::Net::OAuth10Credentials::SIGN_PLAINTEXT);

Internal Details

  • The `percentEncode` method delegates to `Poco::URI::encode` with a custom set of reserved characters: `!?#/'\",;:$&()[]*+=@`.
  • Parameters are sorted lexicographically via `std::map` before building the signature base string, as required by the OAuth 1.0 specification.
  • The `authenticate` method strips the query and fragment from the URI before signing, as the OAuth spec requires a base string URI without query components.
  • The `nonceAndTimestampForTesting` method allows injection of fixed nonce and timestamp values for deterministic testing.
  • The `verify` method supports both PLAINTEXT and HMAC-SHA1 methods. It recomputes the signature using the provided nonce and timestamp and compares it against the signature from the `Authorization` header.
  • Nonces are generated from 32 bytes of `Poco::RandomInputStream` data, Base64-encoded, with `+`, `/`, and `=` characters stripped to produce URL-safe values.
  • The class reads/writes the `Authorization` header using the `OAuth` scheme prefix, with parameters formatted as `key="value"` pairs separated by commas.
  • Version is always set to `"1.0"`.

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment