Service Credentials
Securely retrieve credentials for external service integrations.
Get Service Credentials
Retrieves the authentication credentials for a specific external service.
Endpoint: GET /api/v1/services/{id}/credentials
Request
curl -X GET "https://dev.api.authsec.dev/exsvc/api/v1/services/svc_abc123/credentials" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json"
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Service ID |
Response
Status: 200 OK
{
"service_id": "svc_abc123",
"credentials": {
"api_key": "sk_live_51A...xyz",
"api_secret": "whsec_...abc",
"client_id": "ca_...123",
"environment": "production"
},
"metadata": {
"last_rotated": "2026-02-01T00:00:00Z",
"expires_at": "2027-02-01T00:00:00Z"
},
"created_at": "2026-02-10T10:30:00Z",
"updated_at": "2026-02-11T14:00:00Z"
}
Error Responses
404 Not Found - Service doesn't exist:
{
"error": {
"code": "SERVICE_NOT_FOUND",
"message": "Service with ID 'svc_abc123' not found"
}
}
404 Not Found - Credentials not configured:
{
"error": {
"code": "CREDENTIALS_NOT_FOUND",
"message": "No credentials found for service 'svc_abc123'"
}
}
403 Forbidden - Insufficient permissions:
{
"error": {
"code": "INSUFFICIENT_PERMISSIONS",
"message": "User does not have permission to view credentials"
}
}
Credential Object Structure
The credentials object structure varies by service type, but commonly includes:
| Field | Type | Description |
|---|---|---|
service_id | string | Associated service ID |
credentials | object | Credential data (varies by service) |
metadata | object | Additional metadata |
created_at | timestamp | Credential creation timestamp |
updated_at | timestamp | Last update timestamp |
Common Credential Fields
| Field | Type | Use Case |
|---|---|---|
api_key | string | API authentication key |
api_secret | string | Secret key for signing requests |
client_id | string | OAuth client identifier |
client_secret | string | OAuth client secret |
access_token | string | Access token for API calls |
refresh_token | string | Token for refreshing access |
webhook_secret | string | Secret for validating webhooks |
environment | string | Environment identifier (production, staging) |
Security Considerations
Best Practices
1. Secure Storage
- Never log credentials in application logs
- Encrypt credentials at rest in your application
- Use environment variables for credential storage
- Avoid hardcoding credentials in source code
2. Access Control
- Implement RBAC for credential access
- Audit credential retrieval for security monitoring
- Use time-limited tokens when possible
- Rotate credentials regularly
3. Transmission Security
- Always use HTTPS for API calls
- Validate SSL certificates on connections
- Use TLS 1.2 or higher for all communications
4. Application Security
# ❌ BAD: Logging credentials
logger.info(f"API Key: {credentials['api_key']}")
# ✅ GOOD: Masking sensitive data
logger.info("API Key retrieved successfully")
# ❌ BAD: Storing in plaintext
with open('config.txt', 'w') as f:
f.write(credentials['api_key'])
# ✅ GOOD: Using environment variables
import os
os.environ['STRIPE_API_KEY'] = credentials['api_key']
Code Examples
Python
import requests
import os
BASE_URL = "https://dev.api.authsec.dev/exsvc"
TOKEN = "your_jwt_token"
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json"
}
def get_service_credentials(service_id: str):
"""
Securely retrieve service credentials
"""
try:
response = requests.get(
f"{BASE_URL}/api/v1/services/{service_id}/credentials",
headers=headers
)
response.raise_for_status()
data = response.json()
credentials = data['credentials']
# Store in environment variables (never log!)
for key, value in credentials.items():
env_key = f"SERVICE_{service_id.upper()}_{key.upper()}"
os.environ[env_key] = str(value)
return credentials
except requests.exceptions.HTTPError as e:
if e.response.status_code == 404:
print(f"Service or credentials not found: {service_id}")
elif e.response.status_code == 403:
print(f"Insufficient permissions to access credentials")
else:
print(f"Error retrieving credentials: {e}")
return None
# Usage
service_id = "svc_abc123"
credentials = get_service_credentials(service_id)
if credentials:
# Use credentials (retrieved from environment)
api_key = os.environ.get(f"SERVICE_{service_id.upper()}_API_KEY")
# Make external API call with credentials
TypeScript
interface ServiceCredentials {
service_id: string;
credentials: Record<string, string>;
metadata: {
last_rotated?: string;
expires_at?: string;
};
created_at: string;
updated_at: string;
}
const BASE_URL = "https://dev.api.authsec.dev/exsvc";
const TOKEN = "your_jwt_token";
async function getServiceCredentials(
serviceId: string
): Promise<ServiceCredentials | null> {
try {
const response = await fetch(
`${BASE_URL}/api/v1/services/${serviceId}/credentials`,
{
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json"
}
}
);
if (!response.ok) {
if (response.status === 404) {
console.error(`Service or credentials not found: ${serviceId}`);
} else if (response.status === 403) {
console.error("Insufficient permissions to access credentials");
} else {
console.error(`Error: ${response.statusText}`);
}
return null;
}
const data: ServiceCredentials = await response.json();
// Store credentials securely (e.g., in-memory cache, not localStorage)
// Never log credentials
console.log("Credentials retrieved successfully");
return data;
} catch (error) {
console.error("Failed to retrieve credentials:", error);
return null;
}
}
// Usage
async function useServiceCredentials() {
const serviceId = "svc_abc123";
const credData = await getServiceCredentials(serviceId);
if (credData) {
const { api_key, api_secret } = credData.credentials;
// Use credentials for external service calls
// Make sure to handle them securely
}
}
Credential Rotation
When to Rotate
- Scheduled: Every 90 days as a best practice
- Compromised: Immediately if credentials are exposed
- Employee Offboarding: When team members leave
- Security Audit: After security reviews recommend rotation
Rotation Workflow
- Generate New Credentials in the external service
- Update Credentials in External Service API (via service update)
- Deploy Updated Configuration to your applications
- Verify Functionality with new credentials
- Revoke Old Credentials in the external service
Monitoring Expiration
from datetime import datetime, timedelta
def check_credential_expiration(service_id: str):
"""
Check if credentials are expiring soon
"""
cred_data = get_service_credentials(service_id)
if not cred_data or 'metadata' not in cred_data:
return
expires_at_str = cred_data['metadata'].get('expires_at')
if not expires_at_str:
return
expires_at = datetime.fromisoformat(expires_at_str.replace('Z', '+00:00'))
days_until_expiry = (expires_at - datetime.now()).days
if days_until_expiry < 30:
print(f"⚠️ Credentials expire in {days_until_expiry} days!")
print("Consider rotating credentials soon")
elif days_until_expiry < 7:
print(f"🚨 URGENT: Credentials expire in {days_until_expiry} days!")
print("Rotate credentials immediately")
Common Use Cases
1. Payment Gateway Integration
# Retrieve Stripe credentials
stripe_creds = get_service_credentials("stripe_production")
stripe.api_key = stripe_creds['credentials']['api_key']
# Create a payment
payment = stripe.PaymentIntent.create(
amount=2000,
currency="usd",
payment_method_types=["card"]
)
2. Email Service Integration
# Retrieve SendGrid credentials
sendgrid_creds = get_service_credentials("sendgrid_production")
api_key = sendgrid_creds['credentials']['api_key']
# Send email
import sendgrid
from sendgrid.helpers.mail import Mail
sg = sendgrid.SendGridAPIClient(api_key)
message = Mail(
from_email='[email protected]',
to_emails='[email protected]',
subject='Hello',
html_content='<strong>Message</strong>'
)
response = sg.send(message)
3. Cloud Storage Integration
# Retrieve AWS S3 credentials
s3_creds = get_service_credentials("aws_s3_production")
creds = s3_creds['credentials']
import boto3
s3_client = boto3.client(
's3',
aws_access_key_id=creds['access_key_id'],
aws_secret_access_key=creds['secret_access_key']
)
# Upload file
s3_client.upload_file('local_file.txt', 'bucket-name', 'file.txt')
Troubleshooting
Credentials Not Found
Problem: 404 CREDENTIALS_NOT_FOUND error
Solutions:
- Verify service exists:
GET /api/v1/services/{id} - Check if credentials were set for the service
- Confirm you have the correct service ID
Insufficient Permissions
Problem: 403 INSUFFICIENT_PERMISSIONS error
Solutions:
- Verify your JWT token has required scopes
- Check RBAC permissions for credential access
- Contact your administrator for elevated access
Expired Credentials
Problem: External service returns authentication errors
Solutions:
- Check credential expiration date in metadata
- Rotate credentials if expired
- Implement automatic expiration monitoring
Next Steps
- Service Management - Create and manage external services
- Debug Utilities - Troubleshoot authentication issues
- Security Best Practices - General security guidelines