Can I use client certificates and private keys in HTTP Requests from a Canister

  • Context:
    I am developing a dApp on the Internet Computer and need to make HTTP requests to an external API (Revolut’s Open Banking API) which requires client certificates and private keys for mutual TLS authentication. Specifically, I need to use a transport.pem certificate and a private.key to authenticate my requests.

  • Details:
    I am using the http_request API from the IC management canister to make HTTP requests:

use ic_cdk::api::management_canister::http_request::{
    http_request, CanisterHttpRequestArgument, HttpHeader, HttpMethod,
};

let request_headers = vec![HttpHeader {
    name: "Content-Type".to_string(),
    value: "application/x-www-form-urlencoded".to_string(),
}];

let request_body = format!(
    "grant_type=client_credentials&scope=accounts&client_id={}",
    client_id
);

let request = CanisterHttpRequestArgument {
    url: format!("{}/token", api_url),
    method: HttpMethod::POST,
    body: Some(request_body.as_bytes().to_vec()),
    max_response_bytes: None,
    transform: None,
    headers: request_headers,
};

let cycles: u128 = 10_000_000_000;
match http_request(request, cycles).await {
    Ok((response,)) => {
        // handle response
    }
    Err((r, m)) => {
        // handle error
    }
}

For a curl request I would use:

$ curl -k --cert transport.pem --key private.key --location --request POST 'https://sandbox-oba-auth.revolut.com/token' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'grant_type=client_credentials' --data-urlencode 'scope=payments' --data-urlencode ${CLIENT_ID}

Challenges:

  1. Including Certificates in HTTP Requests
  • The http_request API does not directly support specifying client certificates and private keys for mutual TLS.
  • How can I include these certificates in my HTTP request?
  1. CEL Expressions and HTTP Certification
  • From the HTTP Gateway Protocol Specification and related resources (HTTP certification | Internet Computer), it seems like using CEL expressions and HTTP certification might be relevant.
  • Can CEL expressions be used to handle mutual TLS, or is there another recommended approach?
  1. Security and Best Practices:
  • What are the best practices for securely managing and using client certificates and private keys in an IC canister?
  • Are there any specific limitations or security considerations I should be aware of?

Any guidance or examples on how to achieve this would be greatly appreciated. Thank you!

Forget about the HTTP Gateway protocol. The HTTP Gateway protocol is used to serve HTTP from a canister, not to make HTTP requests. It’s an unfortunate name clash that both sending and receiving HTTP requests use functions named http_request. In your case it is irrelevant

That problem is not fully solved. Data in canisters is private by default, but a malicious node could still look at your canister’s state. Using any sort of secrets from a canister is therefore not fully safe and you should simply not put things there that are ‘too valuable’. I would personally be okay with storing secrets worth $XXXX in a canister, but it’s up to you to know how much you trust it. Maybe there is a way to rotate the secret regularly?

Thanks for the answer. Still, do you know if I can incorporate client certificates and private keys for mutual TLS or http_request does not support it?

curl -k --cert transport.pem --key private.key

I don’t think it’s supported. The spec is usually the source of truth for such matters. I don’t see any mention of client certs in there.

1 Like