Moose supports two authentication mechanisms for securing your API endpoints:
Choose the method that fits your use case, or use both together with custom configuration.
API keys are the simplest way to secure your Moose endpoints. They're ideal for:
API keys use PBKDF2 HMAC SHA256 hashing for secure storage. You generate a token pair (plain-text and hashed) using the Moose CLI, store the hashed version in environment variables, and send the plain-text version in your request headers.
Generate tokens and hashed keys using the Moose CLI:
moose generate hash-tokenOutput:
Authorization headers)Use the hashed key for environment variables and moose.config.toml. Use the plain-text token in your Authorization: Bearer token headers.
Set environment variables with the hashed API keys you generated:
# For ingest endpoints
export MOOSE_INGEST_API_KEY='your_pbkdf2_hmac_sha256_hashed_key'
# For analytics endpoints
export MOOSE_CONSUMPTION_API_KEY='your_pbkdf2_hmac_sha256_hashed_key'
# For admin endpoints
export MOOSE_ADMIN_TOKEN='your_plain_text_token'Or set the admin API key in moose.config.toml:
[authentication]admin_api_key = "your_pbkdf2_hmac_sha256_hashed_key"Storing the admin_api_key (which is a PBKDF2 HMAC SHA256 hash) in your moose.config.toml file is an acceptable practice, even if the file is version-controlled. This is because the actual plain-text Bearer token (the secret) is not stored. The hash is computationally expensive to reverse, ensuring that your secret is not exposed in the codebase.
All authenticated requests require the Authorization header with the plain-text token:
# Using curl
curl -H "Authorization: Bearer your_plain_text_token_here" \
https://your-moose-instance.com/ingest/YourDataModel
# Using JavaScript
fetch('https://your-moose-instance.com/api/endpoint', {
headers: {
'Authorization': 'Bearer your_plain_text_token_here'
}
})JWT authentication integrates with existing identity providers and follows standard token-based authentication patterns. Use JWTs when:
Moose validates JWT tokens using RS256 algorithm with your identity provider's public key. You configure the expected issuer and audience, and Moose handles token verification automatically.
[jwt]# Your JWT public key (PEM-formatted RSA public key)secret = """-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy...-----END PUBLIC KEY-----"""# Expected JWT issuerissuer = "https://my-auth-server.com/"# Expected JWT audience audience = "my-moose-app"The secret field should contain your JWT public key used to verify signatures using RS256 algorithm.
You can also set these values as environment variables:
MOOSE_JWT__SECRET=your_jwt_public_key # PEM-formatted RSA public key (overrides `secret` in `moose.config.toml`)
MOOSE_JWT__ISSUER=your_jwt_issuer # Expected JWT issuer (overrides `issuer` in `moose.config.toml`)
MOOSE_JWT__AUDIENCE=your_jwt_audience # Expected JWT audience (overrides `audience` in `moose.config.toml`)Send requests with the JWT token in the Authorization header:
# Using curl
curl -H "Authorization: Bearer your_jwt_token_here" \
https://your-moose-instance.com/ingest/YourDataModel
# Using JavaScript
fetch('https://your-moose-instance.com/api/endpoint', {
headers: {
'Authorization': 'Bearer your_jwt_token_here'
}
})You can configure both JWT and API Key authentication simultaneously. When both are configured, Moose's authentication behavior depends on the enforce_on_all_* flags.
By default, when both JWT and API Keys are configured, Moose tries JWT validation first, then falls back to API Key validation:
[jwt]# JWT configurationsecret = "..."issuer = "https://my-auth-server.com/"audience = "my-moose-app"# enforce flags default to false# API Key configuration
MOOSE_INGEST_API_KEY='your_pbkdf2_hmac_sha256_hashed_key'
MOOSE_CONSUMPTION_API_KEY='your_pbkdf2_hmac_sha256_hashed_key'For Ingest Endpoints (/ingest/*):
For Analytics Endpoints (/api/*):
This allows you to use either authentication method for your clients.
If you want to only accept JWT tokens (no API key fallback), set the enforcement flags:
[jwt]secret = "..."issuer = "https://my-auth-server.com/"audience = "my-moose-app"# Only accept JWT, no API key fallbackenforce_on_all_ingest_apis = trueenforce_on_all_consumptions_apis = trueResult: When enforcement is enabled, API Key authentication is disabled even if the environment variables are set. Only valid JWT tokens will be accepted.
Configure JWT for user-facing analytics endpoints, API keys for internal ingestion:
[jwt]secret = "..."issuer = "https://my-auth-server.com/"audience = "my-moose-app"enforce_on_all_consumptions_apis = true # JWT only for /api/*enforce_on_all_ingest_apis = false # Allow fallback for /ingest/*MOOSE_INGEST_API_KEY='hashed_key_for_internal_services'Start with both configured, no enforcement. Gradually migrate clients to JWT. Once complete, enable enforcement:
[jwt]secret = "..."issuer = "https://my-auth-server.com/"audience = "my-moose-app"# Start with both allowed during migrationenforce_on_all_ingest_apis = falseenforce_on_all_consumptions_apis = false# Later, enable to complete migration# enforce_on_all_ingest_apis = true# enforce_on_all_consumptions_apis = trueAdmin endpoints use API key authentication exclusively (configured separately from ingest/analytics endpoints).
Configuration precedence (highest to lowest):
--token CLI parameter (plain-text token)MOOSE_ADMIN_TOKEN environment variable (plain-text token)admin_api_key in moose.config.toml (hashed token)Example:
# Option 1: CLI parameter
moose remote plan --token your_plain_text_token
# Option 2: Environment variable
export MOOSE_ADMIN_TOKEN='your_plain_text_token'
moose remote plan
# Option 3: Config file
# In moose.config.toml:
# [authentication]
# admin_api_key = "your_pbkdf2_hmac_sha256_hashed_key"moose.config.toml is safe to version control, but the plain-text token should only exist in secure environment variables or secret management systemsNever commit plain-text tokens to version control. Use hashed keys in configuration files and environment variables for production.