Skip to main content

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

package main

import (
    "log"
    aries "github.com/aries-exchange/go-sdk"
)

func main() {
    client := aries.NewClient(
        aries.WithClientID("your_client_id"),
        aries.WithClientSecret("your_client_secret"),
    )

    // The SDK handles token management automatically
}

OAuth2 Authorization Flow

Authorization Code Flow

For applications that need user authorization:
package main

import (
    "fmt"
    "log"
    aries "github.com/aries-exchange/go-sdk"
)

func main() {
    client := aries.NewClient(
        aries.WithClientID("your_client_id"),
        aries.WithClientSecret("your_client_secret"),
    )

    // Step 1: Get authorization URL
    authURL, err := client.OAuth2.GetAuthorizationURL(&aries.AuthURLParams{
        RedirectURI: "https://yourapp.com/callback",
        Scope:       []string{"read", "trade"},
        State:       "random_state_string",
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Redirect user to: %s\n", authURL)

    // Step 2: Exchange code for tokens
    authCode := "code_from_callback"
    tokens, err := client.OAuth2.ExchangeCode(&aries.TokenExchangeParams{
        Code:        authCode,
        RedirectURI: "https://yourapp.com/callback",
    })
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Access Token: %s\n", tokens.AccessToken)
    fmt.Printf("Refresh Token: %s\n", tokens.RefreshToken)
    fmt.Printf("Expires In: %d seconds\n", tokens.ExpiresIn)
}

PKCE Support

For enhanced security in public clients:
import (
    "crypto/rand"
    "crypto/sha256"
    "encoding/base64"
)

func generatePKCE() (verifier, challenge string, err error) {
    // Generate code verifier
    b := make([]byte, 32)
    if _, err := rand.Read(b); err != nil {
        return "", "", err
    }
    verifier = base64.RawURLEncoding.EncodeToString(b)

    // Generate code challenge
    h := sha256.New()
    h.Write([]byte(verifier))
    challenge = base64.RawURLEncoding.EncodeToString(h.Sum(nil))

    return verifier, challenge, nil
}

func main() {
    client := aries.NewClient(
        aries.WithClientID("your_client_id"),
        aries.WithClientSecret("your_client_secret"),
    )

    // Generate PKCE parameters
    verifier, challenge, err := generatePKCE()
    if err != nil {
        log.Fatal(err)
    }

    // Step 1: Authorization with PKCE
    authURL, err := client.OAuth2.GetAuthorizationURL(&aries.AuthURLParams{
        RedirectURI:         "https://yourapp.com/callback",
        CodeChallenge:       challenge,
        CodeChallengeMethod: "S256",
    })
    if err != nil {
        log.Fatal(err)
    }

    // Step 2: Exchange code with verifier
    tokens, err := client.OAuth2.ExchangeCode(&aries.TokenExchangeParams{
        Code:         authCode,
        RedirectURI:  "https://yourapp.com/callback",
        CodeVerifier: verifier,
    })
    if err != nil {
        log.Fatal(err)
    }
}

MFA Verification

If MFA is enabled:
// Verify MFA
mfaResult, err := client.OAuth2.VerifyMFA(&aries.MFAVerifyParams{
    Code:         "123456",  // 6-digit MFA code
    SessionToken: authResponse.SessionToken,
})
if err != nil {
    log.Fatal(err)
}

// Exchange for tokens
tokens, err := client.OAuth2.ExchangeCode(&aries.TokenExchangeParams{
    Code:        mfaResult.AuthorizationCode,
    RedirectURI: "https://yourapp.com/callback",
})
if err != nil {
    log.Fatal(err)
}

Token Management

Refreshing Access Tokens

// Refresh the access token
newTokens, err := client.OAuth2.RefreshToken(tokens.RefreshToken)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("New Access Token: %s\n", newTokens.AccessToken)
fmt.Printf("Expires In: %d seconds\n", newTokens.ExpiresIn)

Automatic Token Refresh

// Configure automatic refresh
client := aries.NewClient(
    aries.WithClientID("your_client_id"),
    aries.WithClientSecret("your_client_secret"),
    aries.WithRefreshToken("your_refresh_token"),
    aries.WithAutoRefresh(true),  // Enable automatic token refresh
)

// Make API calls without worrying about token expiration
accounts, err := client.Users.GetUserAccounts()
if err != nil {
    log.Fatal(err)
}

Using Bearer Tokens Directly

If you already have an access token:
client := aries.NewClient(
    aries.WithBearerToken("your_access_token"),
)

// Make authenticated requests
user, err := client.Users.GetCurrentUser()
if err != nil {
    log.Fatal(err)
}

Security Best Practices

1. Store Credentials Securely

Never hardcode credentials:
import "os"

client := aries.NewClient(
    aries.WithClientID(os.Getenv("ARIES_CLIENT_ID")),
    aries.WithClientSecret(os.Getenv("ARIES_CLIENT_SECRET")),
)

2. Use Environment Variables

Set environment variables:
export ARIES_CLIENT_ID=your_client_id
export ARIES_CLIENT_SECRET=your_client_secret
export ARIES_REFRESH_TOKEN=your_refresh_token

3. Handle Token Expiration

import "errors"

user, err := client.Users.GetCurrentUser()
if err != nil {
    var apiErr *aries.APIError
    if errors.As(err, &apiErr) && apiErr.StatusCode == 401 {
        // Token expired, refresh it
        tokens, err := client.OAuth2.RefreshToken(refreshToken)
        if err != nil {
            log.Fatal(err)
        }

        // Update client with new token
        client = aries.NewClient(
            aries.WithBearerToken(tokens.AccessToken),
        )

        // Retry the request
        user, err = client.Users.GetCurrentUser()
        if err != nil {
            log.Fatal(err)
        }
    }
}

4. Context Support

Use context for cancellation and timeouts:
import (
    "context"
    "time"
)

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

user, err := client.Users.GetCurrentUserWithContext(ctx)
if err != nil {
    log.Fatal(err)
}

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

import (
    "errors"
    "log"
    aries "github.com/aries-exchange/go-sdk"
)

user, err := client.Users.GetCurrentUser()
if err != nil {
    var apiErr *aries.APIError
    if errors.As(err, &apiErr) {
        switch apiErr.StatusCode {
        case 401:
            log.Println("Authentication failed: Invalid credentials")
        case 403:
            log.Println("Forbidden: Insufficient permissions")
        case 429:
            log.Printf("Rate limit exceeded. Retry after %s", apiErr.Headers.Get("Retry-After"))
        default:
            log.Printf("API Error: %s", apiErr.Message)
        }
    } else {
        log.Fatal(err)
    }
}

Complete Example

package main

import (
    "fmt"
    "log"
    "os"
    aries "github.com/aries-exchange/go-sdk"
)

func main() {
    // Initialize client
    client := aries.NewClient(
        aries.WithClientID(os.Getenv("ARIES_CLIENT_ID")),
        aries.WithClientSecret(os.Getenv("ARIES_CLIENT_SECRET")),
        aries.WithAutoRefresh(true),
    )

    // Get current user
    user, err := client.Users.GetCurrentUser()
    if err != nil {
        log.Fatalf("Failed to get user: %v", err)
    }
    fmt.Printf("Authenticated as: %s\n", user.Email)

    // Get user accounts
    accounts, err := client.Users.GetUserAccounts()
    if err != nil {
        log.Fatalf("Failed to get accounts: %v", err)
    }
    fmt.Printf("Found %d accounts\n", len(accounts))
}

Next Steps