❌ FAQ - Authentication
🚫 Why does /auth/token return HTTP 501 in Local Server mode?
This is expected behavior. JWT authentication is not implemented in local server mode. When you make a request to /auth/token in local server mode, you will receive HTTP 501 Not Implemented.
Single API Consistency
While this breaks the "single API" consistency between local and cloud modes, JWT authentication for local server mode is planned for a future release.
🔐 What is JWT authentication and how does it work?
JWT (JSON Web Token) authentication is the primary authentication mechanism for the SMSGate API. It provides a secure, scalable way to authenticate API requests without transmitting credentials with each request.
🔄 How do I migrate from Basic Auth to JWT?
Migrating from Basic Authentication to JWT provides enhanced security, better performance, and fine-grained access control. Here's how to migrate:
Step 1: Update Your Code
Replace Basic Auth with JWT Bearer tokens:
response = requests.post(
"https://api.sms-gate.app/3rdparty/v1/messages",
auth=("username", "password"),
json={"phoneNumbers": ["+1234567890"], "textMessage": {"text": "Hello world!"}}
)
# First, get a token
token_response = requests.post(
"https://api.sms-gate.app/3rdparty/v1/auth/token",
auth=("username", "password"),
json={"ttl": 3600, "scopes": ["messages:send"]}
)
if token_response.status_code == 201:
token_data = token_response.json()
access_token = token_data["access_token"]
# Then use the token
response = requests.post(
"https://api.sms-gate.app/3rdparty/v1/messages",
headers={
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
},
json={"phoneNumbers": ["+1234567890"], "textMessage": {"text": "Hello world!"}}
)
Step 2: Implement Token Management
- Token Refresh: Implement automatic token refresh before expiration
- Error Handling: Handle 401/403 errors gracefully
- Secure Storage: Store tokens securely on the server side
🔑 What are JWT scopes and how do I use them?
JWT scopes define the permissions associated with a token, implementing the principle of least privilege. All scopes follow the pattern: resource:action
All available scopes are listed in the Authentication section.
Using Scopes
When requesting a JWT token, specify which scopes you need:
Scope Best Practices
- Request only the scopes you need
- Create multiple tokens with different scopes for different components
- Use short TTLs for tokens with sensitive scopes
- Avoid using
all:anyunless absolutely necessary
⏰ How long do JWT tokens last and how do I refresh them?
JWT tokens have a configurable time-to-live (TTL). The default TTL is 24 hours (86400 seconds), but you can specify a custom duration when generating a token.
Token Expiration
{
"id": "w8pxz0a4Fwa4xgzyCvSeC",
"token_type": "Bearer",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_at": "2025-11-22T08:45:00Z"
}
Token Refresh Strategy
Since JWT tokens cannot be refreshed (they must be reissued), implement a proactive refresh strategy:
import requests
from datetime import datetime, timedelta
class SMSGatewayClient:
def __init__(self, gateway_url, username, password):
self.gateway_url = gateway_url
self.username = username
self.password = password
self.access_token = None
self.token_expires_at = None
def get_token(self, scopes, ttl=3600):
"""Get a new JWT token"""
response = requests.post(
f"{self.gateway_url}/3rdparty/v1/auth/token",
auth=(self.username, self.password),
headers={"Content-Type": "application/json"},
json={"ttl": ttl, "scopes": scopes}
)
if response.status_code == 201:
token_data = response.json()
self.access_token = token_data["access_token"]
self.token_expires_at = datetime.fromisoformat(
token_data["expires_at"].replace("Z", "+00:00")
)
return self.access_token
else:
raise Exception(f"Failed to get token: {response.status_code}")
def ensure_valid_token(self, scopes):
"""Ensure we have a valid token, refresh if needed"""
if (self.access_token is None or
self.token_expires_at is None or
datetime.now() + timedelta(minutes=5) >= self.token_expires_at):
return self.get_token(scopes)
return self.access_token
Token Management Best Practices
- Refresh tokens 5-10 minutes before expiration
- Implement exponential backoff for failed refresh attempts
- Store tokens securely (not in client-side code)
🛡️ How do I revoke a JWT token?
JWT tokens can be revoked before they expire using the token revocation endpoint. This is useful when a token is compromised or no longer needed.
Revoking a Token
curl -X DELETE "https://api.sms-gate.app/3rdparty/v1/auth/token/{jti}" \
-H "Authorization: Basic username:password"
Where {jti} is the token ID from the token response.
🔐 "Invalid token" JWT Error
The "invalid token" error occurs when the JWT token is malformed, has an incorrect signature, or cannot be validated by the server.
Common Causes
- Malformed Token: The token structure is incorrect or corrupted
- Invalid Signature: The token signature doesn't match the server's secret
- Algorithm Mismatch: The token was signed with a different algorithm than expected
- Encoding Issues: The token contains invalid characters or formatting
Troubleshooting Steps
-
Check Token Format: Ensure the token has three parts separated by dots (
.) -
Verify Token Copy: Make sure you copied the entire token without extra spaces or line breaks
-
Validate Token Structure: Use an online JWT decoder to verify the token structure
⏰ "Token expired" JWT Error
The "token expired" error occurs when the JWT token has passed its expiration time. This is a normal part of the JWT lifecycle and requires token refresh.
Common Causes
- Token TTL Expired: The token has reached its expiration time
- Clock Skew: Time differences between client and server clocks
- Long-running Operations: Operations that take longer than the token TTL
Troubleshooting Steps
-
Check Expiration Time: Parse the token to see when it expires
import jwt import datetime token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." try: decoded = jwt.decode(token, options={"verify_signature": False}) exp_time = datetime.datetime.fromtimestamp(decoded['exp']) print(f"Token expires at: {exp_time}") except Exception as e: print(f"Error decoding token: {e}") -
Implement Token Refresh: Refresh tokens before they expire
-
Adjust Token TTL: Use a longer TTL for long-running operations
Best Practices
- Implement automatic token refresh
- Use appropriate TTL values for your use case
- Handle token expiration gracefully in your code
- Consider clock skew in your expiration logic
🚫 "Token revoked" JWT Error
The "token revoked" error occurs when a JWT token has been manually revoked before its natural expiration time.
Common Causes
- Manual Revocation: Token was explicitly revoked by an administrator
- Security Incident: Token was revoked due to a security concern
Troubleshooting Steps
-
Request New Token: Generate a new token with the same scopes
-
Investigate Revocation Reason: Contact support to understand why the token was revoked
🙅 "Scope required" JWT Error
The "scope required" error occurs when the JWT token doesn't have the necessary scope to access a specific resource or perform a specific action.
Common Causes
- Missing Scope: The token doesn't include the required scope
- Incorrect Scope: The token has the wrong scope for the requested action
- Scope Typos: The scope name is misspelled or incorrectly formatted
- Resource Changes: The required scope for a resource has changed
Troubleshooting Steps
-
Check Token Scopes: Verify what scopes your token contains
-
Verify Required Scope: Check the API documentation for the required scope
-
Request New Token: Generate a new token with the correct scopes
Scope Best Practices
- Request only the scopes you need
- Use the exact scope names from the documentation
- Create multiple tokens for different purposes
- Regularly review and update your scope requirements
🔄 "Migration from Basic Auth to JWT" Issues
When migrating from Basic Authentication to JWT, you may encounter various issues. Here are common problems and their solutions.
Common Issues
- Token Generation Errors: Unable to generate JWT tokens
- Permission Errors: JWT tokens don't have the same permissions as Basic Auth
- Code Compatibility: Existing code doesn't work with JWT authentication
Troubleshooting Steps
-
Verify Token Generation: Ensure you can generate JWT tokens successfully
-
Update Code Gradually: Migrate code incrementally rather than all at once
# Hybrid approach during migration def make_request(endpoint, data=None, use_jwt=True): if use_jwt and jwt_token: headers = {"Authorization": f"Bearer {jwt_token}"} else: # Fall back to Basic Auth headers = {} auth = (username, password) return requests.post(endpoint, headers=headers, auth=auth, json=data) -
Test in Staging: Test JWT authentication in a staging environment before production
Migration Best Practices
- Keep Basic Auth as a fallback during transition
- Monitor authentication errors during migration
🛡️ JWT Security Issues
JWT tokens are generally secure, but improper implementation can lead to security vulnerabilities.
Common Security Issues
- Long TTLs: Using excessively long token expiration times
- Token Leakage: Tokens being exposed in logs, browser storage, or network traffic
- Insufficient Scopes: Using overly broad scopes like
all:any
Troubleshooting Steps
-
Review Token TTL: Ensure your token TTL is appropriate for your use case
-
Implement Secure Storage: Ensure tokens are stored securely
Security Best Practices
- Use the shortest practical TTL for your use case
- Store tokens securely on the server side
- Implement proper token revocation