I want a function on a canister to be callable only by another canister on the IC, and not by an API call or any other canister

I have a secure canister which calls a function in a different canister by importing that canister.

For security reasons, I want this function canister to ONLY be able to be called from the secure canister, and reject all other requests. In particular, this function should not be callable from an API call and not callable from any other canister on the IC other than that specific canister.

How can I achieve this?

Thanks in advance,


1 Like

Here’s an example in Rust, I believe there’s something similar in Motoko

pub fn my_guard() -> Result<(), String> {
    if caller() != "your secure canister" {
        return Err(String::from("Access denied"));


#[update(guard = my_guard)]
pub async fn my_secure_function(){

Thanks! A couple of followups:
(1) I presume the string “your secure canister” refers to the canister name in dfx.json?
(2) For Motoko, I assume the analogy to your answer is here: Principals and caller identification :: Internet Computer and uses (msg)? (i.e msg.caller)

1 - it should be your canister principal not the name.
2 - yes true

Are you sure it is the principal ID? It would not make sense to hard-code the principal ID in, especially since if you consider that, if the canisters are being deployed together (dfx deploy), you cannot know the principal ID before deploying.

You can know the principal of the canister before deploying if you install it first, which assign an id on the mainnet before actually installing the code.

dfx canister create --all // -> this will create the canisters id in canister_ids.sjosn
dfx build
dfx canister install --all

Okay, thank you! Best Wishes!

Somewhat related… is there a way to make a canister be callable only by a frontend client?

The catch is that client could represent any number of logged-in users. I could put some application ID in both the frontend code and the backend canister code, and verify the application ID on every request… but someone could read the JS and extract the application ID.

Basically, I want to prevent malicious users from calling the backend canister directly… but maybe that’s an impossible goal?