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

# Authentication

> Learn how to authenticate with the Aries API using OAuth2 and manage access tokens

## Overview

The Aries API uses **OAuth2 with Bearer tokens** (JWT format) for authentication. All API requests require a valid access token in the Authorization header.

## Authentication Flow

### 1. OAuth2 Client Credentials

First, obtain your OAuth2 credentials from the Aries platform:

* **Client ID**: Your application identifier
* **Client Secret**: Your application secret key

### 2. Initialize the SDK

```python theme={null}
from aries_exchange import AriesClient

client = AriesClient(
    client_id="your_client_id",
    client_secret="your_client_secret"
)

# The SDK handles token management automatically
```

## OAuth2 Authorization Flow

### Authorization Code Flow

For applications that need user authorization:

```python theme={null}
# Step 1: Initiate authorization
auth_url = client.oauth2.get_authorization_url(
    redirect_uri="https://yourapp.com/callback",
    scope=["read", "trade"],
    state="random_state_string"
)
print(f"Redirect user to: {auth_url}")

# Step 2: Handle the callback with authorization code
authorization_code = "code_from_callback"

# Step 3: Exchange code for tokens
tokens = client.oauth2.exchange_code(
    code=authorization_code,
    redirect_uri="https://yourapp.com/callback"
)

print(f"Access Token: {tokens.access_token}")
print(f"Refresh Token: {tokens.refresh_token}")
print(f"Expires In: {tokens.expires_in} seconds")
```

### PKCE Support

For enhanced security in public clients (mobile apps, SPAs):

```python theme={null}
import secrets
import hashlib
import base64

# Generate code verifier
code_verifier = base64.urlsafe_b64encode(secrets.token_bytes(32)).decode('utf-8').rstrip('=')

# Generate code challenge
code_challenge = base64.urlsafe_b64encode(
    hashlib.sha256(code_verifier.encode('utf-8')).digest()
).decode('utf-8').rstrip('=')

# Step 1: Authorization with PKCE
auth_url = client.oauth2.get_authorization_url(
    redirect_uri="https://yourapp.com/callback",
    code_challenge=code_challenge,
    code_challenge_method="S256"
)

# Step 2: Exchange code with verifier
tokens = client.oauth2.exchange_code(
    code=authorization_code,
    redirect_uri="https://yourapp.com/callback",
    code_verifier=code_verifier
)
```

### MFA Verification

If MFA is enabled:

```python theme={null}
# After initial authorization, verify MFA
mfa_result = client.oauth2.verify_mfa(
    code="123456",  # 6-digit MFA code
    session_token=auth_response.session_token
)

# Then exchange for tokens
tokens = client.oauth2.exchange_code(
    code=mfa_result.authorization_code,
    redirect_uri="https://yourapp.com/callback"
)
```

## Token Management

### Refreshing Access Tokens

Access tokens expire after a set period. Use refresh tokens to obtain new access tokens:

```python theme={null}
# Refresh the access token
new_tokens = client.oauth2.refresh_token(
    refresh_token=tokens.refresh_token
)

print(f"New Access Token: {new_tokens.access_token}")
print(f"Expires In: {new_tokens.expires_in} seconds")
```

### Automatic Token Refresh

The SDK automatically refreshes tokens when they expire:

```python theme={null}
# Configure automatic refresh
client = AriesClient(
    client_id="your_client_id",
    client_secret="your_client_secret",
    refresh_token="your_refresh_token",
    auto_refresh=True  # Enable automatic token refresh
)

# Make API calls without worrying about token expiration
accounts = client.users.get_user_accounts()
```

## Using Bearer Tokens Directly

If you already have an access token:

```python theme={null}
from aries_exchange import AriesClient

client = AriesClient(
    bearer_token="your_access_token"
)

# Make authenticated requests
profile = client.users.get_user_profile()
```

## Security Best Practices

### 1. Store Credentials Securely

Never hardcode credentials in your source code:

```python theme={null}
import os

client = AriesClient(
    client_id=os.getenv("ARIES_CLIENT_ID"),
    client_secret=os.getenv("ARIES_CLIENT_SECRET")
)
```

### 2. Use Environment Variables

Create a `.env` file (add to `.gitignore`):

```bash theme={null}
ARIES_CLIENT_ID=your_client_id
ARIES_CLIENT_SECRET=your_client_secret
ARIES_REFRESH_TOKEN=your_refresh_token
```

Load in your application:

```python theme={null}
from dotenv import load_dotenv
import os

load_dotenv()

client = AriesClient(
    client_id=os.getenv("ARIES_CLIENT_ID"),
    client_secret=os.getenv("ARIES_CLIENT_SECRET")
)
```

### 3. Handle Token Expiration

```python theme={null}
from aries_exchange import AriesAPIError

try:
    profile = client.users.get_user_profile()
except AriesAPIError as e:
    if e.status_code == 401:
        # Token expired, refresh it
        tokens = client.oauth2.refresh_token(refresh_token)
        client.bearer_token = tokens.access_token
        # Retry the request
        profile = client.users.get_user_profile()
```

### 4. Scope Limitations

Request only the scopes you need:

```python theme={null}
# Minimal scopes for read-only access
auth_url = client.oauth2.get_authorization_url(
    redirect_uri="https://yourapp.com/callback",
    scope=["read"]  # Only read access
)

# Full trading access
auth_url = client.oauth2.get_authorization_url(
    redirect_uri="https://yourapp.com/callback",
    scope=["read", "trade", "withdraw"]  # All permissions
)
```

## OAuth2 Scopes

Available scopes:

* `read` - Read account data, positions, and orders
* `trade` - Place and cancel orders
* `withdraw` - Withdraw funds from account
* `admin` - Administrative operations

## Error Handling

```python theme={null}
from aries_exchange import AriesAPIError

try:
    client = AriesClient(
        client_id="invalid_client_id",
        client_secret="invalid_secret"
    )
    profile = client.users.get_user_profile()
except AriesAPIError as e:
    if e.status_code == 401:
        print("Authentication failed: Invalid credentials")
    elif e.status_code == 403:
        print("Forbidden: Insufficient permissions")
    else:
        print(f"Error: {e.message}")
```

## Rate Limiting

The Aries API enforces rate limits. If you exceed the limit:

```python theme={null}
try:
    # Make API request
    result = client.orders.place_order(...)
except AriesAPIError as e:
    if e.status_code == 429:
        retry_after = e.headers.get('Retry-After')
        print(f"Rate limit exceeded. Retry after {retry_after} seconds")
        # Implement exponential backoff
```

## Complete Example

```python theme={null}
import os
from aries_exchange import AriesClient, AriesAPIError

def main():
    # Initialize client
    client = AriesClient(
        client_id=os.getenv("ARIES_CLIENT_ID"),
        client_secret=os.getenv("ARIES_CLIENT_SECRET"),
        auto_refresh=True
    )

    try:
        # Get user profile
        profile = client.users.get_user_profile()
        print(f"Authenticated as: {profile.email}")

        # Get user accounts
        accounts = client.users.get_user_accounts()
        print(f"Found {len(accounts)} accounts")

    except AriesAPIError as e:
        if e.status_code == 401:
            print("Authentication failed")
        elif e.status_code == 403:
            print("Access forbidden")
        else:
            print(f"API Error: {e.message}")

if __name__ == "__main__":
    main()
```

## Next Steps

* [Quick Start Guide](/sdks/python/quick-start) - Get started with basic operations
* [Users API](/sdks/python/users) - Manage user accounts and profiles
* [Orders API](/sdks/python/orders) - Place and manage trades

## Related Resources

* OAuth2 Specification: [RFC 6749](https://tools.ietf.org/html/rfc6749)
* PKCE Extension: [RFC 7636](https://tools.ietf.org/html/rfc7636)
* JWT Tokens: [RFC 7519](https://tools.ietf.org/html/rfc7519)
