> ## Documentation Index
> Fetch the complete documentation index at: https://developers.stellar.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Auth

> Implement authentication and authorization.

The [auth example] demonstrates how to implement authentication and authorization using the Soroban Host-managed auth framework.

This example is an extension of the [storing data example].

[![Open in Codespaces](https://github.com/codespaces/badge.svg)][open-in-github-codespaces]

[![Open in Codeanywhere](https://codeanywhere.com/img/open-in-codeanywhere-btn.svg)][open-in-code-anywhere]

[open-in-github-codespaces]: https://github.com/codespaces/new?repo=stellar/soroban-examples&editor=web

[open-in-code-anywhere]: https://app.codeanywhere.com/#https://github.com/stellar/soroban-examples

[storing data example]: https://developers.stellar.org/docs/build/smart-contracts/getting-started/storing-data.md

[auth example]: https://github.com/stellar/soroban-examples/tree/v23.0.0/auth

## Run the Example

First go through the [Setup] process to get your development environment configured, then clone the `v23.0.0` tag of `soroban-examples` repository:

[setup]: https://developers.stellar.org/docs/build/smart-contracts/getting-started/setup.md

```
git clone -b v23.0.0 https://github.com/stellar/soroban-examples
```

Or, skip the development environment setup and open this example in [GitHub Codespaces][open-in-github-codespaces] or [Code Anywhere][open-in-code-anywhere].

To run the tests for the example, navigate to the `auth` directory, and use `cargo test`.

```
cd auth
cargo test
```

You should see the output:

```
running 1 test
test test::test ... ok
```

## Code

```rust title="auth/src/lib.rs" theme={"theme":{"light":"github-light","dark":"github-dark"}}
#[contracttype]
pub enum DataKey {
    Counter(Address),
}

#[contract]
pub struct IncrementContract;

#[contractimpl]
impl IncrementContract {
    /// Increment increments a counter for the user, and returns the value.
    pub fn increment(env: Env, user: Address, value: u32) -> u32 {
        // Requires `user` to have authorized call of the `increment` of this
        // contract with all the arguments passed to `increment`, i.e. `user`
        // and `value`. This will panic if auth fails for any reason.
        // When this is called, Soroban host performs the necessary
        // authentication, manages replay prevention and enforces the user's
        // authorization policies.
        // The contracts normally shouldn't worry about these details and just
        // write code in generic fashion using `Address` and `require_auth` (or
        // `require_auth_for_args`).
        user.require_auth();

        // This call is equilvalent to the above:
        // user.require_auth_for_args((&user, value).into_val(&env));

        // The following has less arguments but is equivalent in authorization
        // scope to the above calls (the user address doesn't have to be
        // included in args as it's guaranteed to be authenticated).
        // user.require_auth_for_args((value,).into_val(&env));

        // Construct a key for the data being stored. Use an enum to set the
        // contract up well for adding other types of data to be stored.
        let key = DataKey::Counter(user.clone());

        // Get the current count for the invoker.
        let mut count: u32 = env.storage().persistent().get(&key).unwrap_or_default();

        // Increment the count.
        count += value;

        // Save the count.
        env.storage().persistent().set(&key, &count);

        // Return the count to the caller.
        count
    }
}
```

Ref: [https://github.com/stellar/soroban-examples/tree/v23.0.0/auth](https://github.com/stellar/soroban-examples/tree/v23.0.0/auth)

## How it Works

The example contract stores a per-`Address` counter that can only be incremented by the owner of that `Address`.

Open the `auth/src/lib.rs` file or see the code above to follow along.

### `Address`

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
#[contracttype]
pub enum DataKey {
    Counter(Address),
}
```

`Address` is a universal Soroban identifier that may represent a Stellar account, a contract, or a contract account (a contract that defines a custom authentication scheme and authorization policies). Contracts don't need to distinguish between these internal representations though. `Address` can be used any time some network identity needs to be represented, like to distinguish between counters for different users in this example.

> [!TIP]
>
> **Enum keys like `DataKey` are useful for organizing contract storage.**
>
> Different enum values create different key 'namespaces'.
>
> In the example the counter for each address is stored against `DataKey::Counter(Address)`. If the contract needs to start storing other types of data, it can do so by adding additional variants to the enum.

### `require_auth`

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
impl IncrementContract {
    pub fn increment(env: Env, user: Address, value: u32) -> u32 {
        user.require_auth();
```

The `require_auth` method can be called for any `Address`. Semantically `user.require_auth()` here means 'require `user` to have authorized calling `increment` function of the current `IncrementContract` instance with the current call arguments, i.e. the current `user` and `value` argument values'. In simpler terms, this ensures that the `user` has allowed incrementing their counter value and nobody else can increment it.

When using `require_auth` the contract implementation doesn't need to worry about the signatures, authentication, and replay prevention. All these features are implemented by the Soroban host and happen automatically as long as the `Address` type is used.

`Address` has another method called `require_auth_for_args`. It works in the same fashion as `require_auth`, but allows customizing the arguments that need to be authorized. Note though, this should be used with care to ensure that there is a deterministic mapping between the contract invocation arguments and the `require_auth_for_args` arguments.

The following two calls are functionally equivalent to `user.require_auth`:

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
// Completely equivalent
user.require_auth_for_args((&user, value).into_val(&env));
// The following has less arguments but is equivalent in authorization
// scope to the above call (the user address doesn't have to be
// included in args as it's guaranteed to be authenticated).
user.require_auth_for_args((value,).into_val(&env));
```

### Tests

Open the [`auth/src/test.rs`] file to follow along.

[`auth/src/test.rs`]: https://github.com/stellar/soroban-examples/tree/v23.0.0/auth/src/test.rs

```rust title="auth/src/test.rs" theme={"theme":{"light":"github-light","dark":"github-dark"}}
#![cfg(test)]
extern crate std;

#[test]
fn test() {
    let env = Env::default();
    env.mock_all_auths();

    let contract_id = env.register(IncrementContract, {});
    let client = IncrementContractClient::new(&env, &contract_id);

    let user_1 = Address::generate(&env);
    let user_2 = Address::generate(&env);

    assert_eq!(client.increment(&user_1, &5), 5);
    // Verify that the user indeed had to authorize a call of `increment` with
    // the expected arguments:
    assert_eq!(
        env.auths(),
        std::vec![(
            // Address for which authorization check is performed
            user_1.clone(),
            // Invocation tree that needs to be authorized
            AuthorizedInvocation {
                // Function that is authorized. Can be a contract function or
                // a host function that requires authorization.
                function: AuthorizedFunction::Contract((
                    // Address of the called contract
                    contract_id.clone(),
                    // Name of the called function
                    symbol_short!("increment"),
                    // Arguments used to call `increment` (converted to the env-managed vector via `into_val`)
                    (user_1.clone(), 5_u32).into_val(&env),
                )),
                // The contract doesn't call any other contracts that require
                // authorization,
                sub_invocations: std::vec![]
            }
        )]
    );

    // Do more `increment` calls. It's not necessary to verify authorizations
    // for every one of them as we don't expect the auth logic to change from
    // call to call.
    assert_eq!(client.increment(&user_1, &2), 7);
    assert_eq!(client.increment(&user_2, &1), 1);
    assert_eq!(client.increment(&user_1, &3), 10);
    assert_eq!(client.increment(&user_2, &4), 5);
}
```

In any test the first thing that is always required is an `Env`, which is the Soroban environment that the contract will run in.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
let env = Env::default();
```

The test instructs the environment to mock all auths. All calls to `require_auth` or `require_auth_for_args` will succeed.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
env.mock_all_auths();
```

The contract is registered with the environment using the contract type.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
let contract_id = env.register(IncrementContract, {});
```

All public functions within an `impl` block that is annotated with the `#[contractimpl]` attribute have a corresponding function generated in a generated client type. The client type will be named the same as the contract type with `Client` appended. For example, in our contract the contract type is `IncrementContract`, and the client is named `IncrementContractClient`.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
let client = IncrementContractClient::new(&env, &contract_id);
```

Generate `Address`es for two users. Normally the exact value of the `Address` shouldn't matter for testing, so they're simply generated randomly.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
let user_1 = Address::random(&env);
let user_2 = Address::random(&env);
```

Invoke `increment` function for `user_1`.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
assert_eq!(client.increment(&user_1, &5), 5);
```

In order to verify that the `require_auth` call(s) have indeed happened, use `auths` function that returns a vector of tuples containing the authorizations from the most recent contract invocation.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
assert_eq!(
    env.auths(),
    std::vec![(
        // Address for which auth is performed
        user_1.clone(),
        // Identifier of the called contract
        contract_id.clone(),
        // Name of the called function
        symbol_short!("increment"),
        // Arguments used to call `increment` (converted to the env-managed vector via `into_val`)
        (user_1.clone(), 5_u32).into_val(&env)
    )]
);
```

Invoke the `increment` function several more times for both users. Notice, that the values are tracked separately for each users.

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
assert_eq!(client.increment(&user_1, &2), 7);
assert_eq!(client.increment(&user_2, &1), 1);
assert_eq!(client.increment(&user_1, &3), 10);
assert_eq!(client.increment(&user_2, &4), 5);
```

## Build the Contract

To build the contract into a `.wasm` file, use the `stellar contract build` command.

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract build
```

The `.wasm` file should be found in the `target` directory after building:

```
target/wasm32v1-none/release/soroban_auth_contract.wasm
```

## Run the Contract

If you have [`stellar-cli`] installed, you can deploy the contract and invoke its functions.

But since we are dealing with authorization and signatures, we need to set up some identities to use for testing and get their public keys:

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar keys generate acc1 --network testnet
stellar keys generate acc2 --network testnet
stellar keys address acc1
stellar keys address acc2
```

Example output with two public keys of identities:

```
GA6S566FD3EQDUNQ4IGSLXKW3TGVSTQW3TPHPGS7NWMCEIPBOKTNCSRU
GAJGHZ44IJXYFNOVRZGBCVKC2V62DB2KHZB7BEMYOWOLFQH4XP2TAM6B
```

### Deploy

**macOS/Linux**

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract deploy \
    --wasm target/wasm32v1-none/release/soroban_auth_contract.wasm \
    --alias auth_example \
    --source-account acc1 \
    --network testnet
```

**Windows (PowerShell)**

```powershell theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract deploy `
    --wasm target/wasm32v1-none/release/soroban_auth_contract.wasm `
    --alias auth_example `
    --source-account acc1 `
    --network testnet
```

### Invoke

Now the contract itself can be invoked. Notice the `--source-account` must be the identity name matching the address passed to the `--user` argument. This allows `Stellar CLI` to automatically sign the necessary payload for the invocation.

**macOS/Linux**

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke \
    --id auth_example \
    --source-account acc1 \
    --network testnet \
    -- \
    increment \
    --user GA6S566FD3EQDUNQ4IGSLXKW3TGVSTQW3TPHPGS7NWMCEIPBOKTNCSRU \
    --value 2
```

**Windows (PowerShell)**

```powershell theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke `
    --id auth_example `
    --source-account acc1 `
    --network testnet `
    -- `
    increment `
    --user GA6S566FD3EQDUNQ4IGSLXKW3TGVSTQW3TPHPGS7NWMCEIPBOKTNCSRU `
    --value 2
```

Run a few more increments for both accounts.

**macOS/Linux**

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke \
    --id auth_example \
    --source-account acc2 \
    --network testnet \
    -- \
    increment \
    --user GAJGHZ44IJXYFNOVRZGBCVKC2V62DB2KHZB7BEMYOWOLFQH4XP2TAM6B \
    --value 5
```

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke \
    --id auth_example \
    --source-account acc1 \
    --network testnet \
    -- \
    increment \
    --user GA6S566FD3EQDUNQ4IGSLXKW3TGVSTQW3TPHPGS7NWMCEIPBOKTNCSRU \
    --value 3
```

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke \
    --id auth_example \
    --source-account acc2 \
    --network testnet \
    -- \
    increment \
    --user GAJGHZ44IJXYFNOVRZGBCVKC2V62DB2KHZB7BEMYOWOLFQH4XP2TAM6B \
    --value 10
```

**Windows (PowerShell)**

```powershell theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke `
    --id auth_example `
    --source-account acc2 `
    --network testnet `
    -- `
    increment `
    --user GAJGHZ44IJXYFNOVRZGBCVKC2V62DB2KHZB7BEMYOWOLFQH4XP2TAM6B `
    --value 5
```

```powershell theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke `
    --id auth_example `
    --source-account acc1 `
    --network testnet `
    -- `
    increment `
    --user GA6S566FD3EQDUNQ4IGSLXKW3TGVSTQW3TPHPGS7NWMCEIPBOKTNCSRU `
    --value 3
```

```powershell theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke `
    --id auth_example `
    --source-account acc2 `
    --network testnet `
    -- `
    increment `
    --user GAJGHZ44IJXYFNOVRZGBCVKC2V62DB2KHZB7BEMYOWOLFQH4XP2TAM6B `
    --value 10
```

View the data that has been stored against each user with `stellar contract read`.

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract read --id auth_example --network testnet
```

```
"[""Counter"",""GA6S566FD3EQDUNQ4IGSLXKW3TGVSTQW3TPHPGS7NWMCEIPBOKTNCSRU""]",5
"[""Counter"",""GAJGHZ44IJXYFNOVRZGBCVKC2V62DB2KHZB7BEMYOWOLFQH4XP2TAM6B""]",15
```

It is also possible to preview the authorization payload that is being signed by providing `--auth` flag to the invocation:

**macOS/Linux**

```sh theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke \
    --id auth_example \
    --source-account acc2 \
    --network testnet \
    --auth \
    -- \
    increment \
    --user GAJGHZ44IJXYFNOVRZGBCVKC2V62DB2KHZB7BEMYOWOLFQH4XP2TAM6B \
    --value 123
```

**Windows (PowerShell)**

```powershell theme={"theme":{"light":"github-light","dark":"github-dark"}}
stellar contract invoke `
    --id auth_example `
    --source-account acc2 `
    --network testnet `
    --auth `
    -- `
    increment `
    --user GAJGHZ44IJXYFNOVRZGBCVKC2V62DB2KHZB7BEMYOWOLFQH4XP2TAM6B `
    --value 123
```

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
Contract auth: [{"address_with_nonce":null,"root_invocation":{"contract_id":"0000000000000000000000000000000000000000000000000000000000000001","function_name":"increment","args":[{"object":{"address":{"account":{"public_key_type_ed25519":"c7bab0288753d58d3e21cc3fa68cd2546b5f78ae6635a6f1b3fe07e03ee846e9"}}}},{"u32":123}],"sub_invocations":[]},"signature_args":[]}]
```

[`stellar-cli`]: ../getting-started/setup#install-the-stellar-cli

## Further reading

[Authorization documentation](https://developers.stellar.org/docs/learn/fundamentals/contract-development/authorization.md) provides more details on how Soroban auth framework works.

[Timelock](https://developers.stellar.org/docs/build/smart-contracts/example-contracts/timelock.md) and [Single Offer](https://developers.stellar.org/docs/build/smart-contracts/example-contracts/single-offer-sale.md) examples demonstrate authorizing token operations on behalf of the user, which can be extended to any nested contract invocations.

[Atomic Swap](https://developers.stellar.org/docs/build/smart-contracts/example-contracts/atomic-swap.md) example demonstrates multi-party authorization where multiple users sign their parts of the contract invocation.

[Simple Account](https://developers.stellar.org/docs/build/smart-contracts/example-contracts/simple-account.md) example demonstrates a minimal contract account implementation and how `__check_auth` works end-to-end.
