Authentication Guide
Introduction to API Authentication
Authentication is the process of verifying the identity of a client or user attempting to access the API. It ensures that only authorized parties can access your resources and perform operations. MyAppAPI supports multiple authentication methods to accommodate different security requirements and use cases.
Authentication vs. Authorization
Authentication verifies who you are, while authorization determines what you can do. This guide focuses on authentication. For information on roles, permissions, and access control, see our Authorization Guide.
Choosing the Right Authentication Method
MyAppAPI offers several authentication methods, each with its own advantages and use cases:
Method | Best For | Security Level | Complexity |
---|---|---|---|
API Keys | Server-to-server, scripts, backend services | Medium | Low |
OAuth 2.0 | User-context operations, third-party integrations | High | High |
JWT | Stateless authentication, microservices | High | Medium |
Session Tokens | Web applications, frontend clients | Medium | Low |
The following sections provide detailed information about each authentication method, with implementation examples for various programming languages and frameworks.
API Keys
API keys are simple, long-lived tokens that identify your application or project when making API requests. They are the simplest authentication method and are ideal for server-to-server communications and backend services.
Getting Your API Key
To get an API key:
- Log in to the MyAppAPI Dashboard
- Navigate to Settings → API Keys
- Click Create New API Key
- Name your key and set appropriate permissions
- Copy and securely store your API key
Important
Your API key is displayed only once when created. If you lose it, you'll need to generate a new one. Store it securely and never expose it in client-side code or public repositories.
Using API Keys
There are two ways to include your API key in requests:
1. HTTP Header (Recommended)
Include your API key in the X-API-Key
header:
curl -X GET "https://api.myappapi.com/v1/users" \
-H "X-API-Key: your_api_key_here"
// Using Fetch API
fetch('https://api.myappapi.com/v1/users', {
headers: {
'X-API-Key': 'your_api_key_here'
}
})
.then(response => response.json())
.then(data => console.log(data));
// Using Axios
const axios = require('axios');
axios.get('https://api.myappapi.com/v1/users', {
headers: {
'X-API-Key': 'your_api_key_here'
}
})
.then(response => console.log(response.data));
import requests
headers = {
'X-API-Key': 'your_api_key_here'
}
response = requests.get('https://api.myappapi.com/v1/users', headers=headers)
data = response.json()
print(data)
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.myappapi.com/v1/users');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: your_api_key_here'
]);
$response = curl_exec($ch);
$data = json_decode($response, true);
curl_close($ch);
?>
2. Query Parameter (Less Secure)
You can also include your API key as a query parameter, though this is less secure because API keys in URLs may be logged:
GET https://api.myappapi.com/v1/users?api_key=your_api_key_here
Security Note
Query parameter authentication should only be used for development or when HTTP headers aren't available. Never use this method for production applications.
API Key Management
Best practices for managing API keys:
- Create multiple keys for different environments (development, staging, production)
- Name keys descriptively to track their usage (e.g., "Production Backend Service")
- Rotate keys periodically to limit the impact of potential breaches
- Revoke unused keys to reduce your attack surface
- Store keys securely using environment variables or secrets management tools
- Monitor key usage to detect unauthorized access
For additional security, you can restrict API keys to specific IP addresses or referrer domains in the API key settings.
OAuth 2.0 Authentication
OAuth 2.0 is an industry-standard protocol for authorization that enables secure, delegated access to APIs. It's ideal for applications that need to access resources on behalf of users without handling their credentials directly.
OAuth 2.0 Flow Types
MyAppAPI supports the following OAuth 2.0 flows:
Flow | Best For | Description |
---|---|---|
Authorization Code | Web applications | Server-side flow with callback URL, most secure option |
Authorization Code with PKCE | Mobile/native apps | Enhanced security for public clients without client secrets |
Implicit | Single-page applications | Frontend-only flow that returns tokens directly (less secure) |
Client Credentials | Server-to-server | Machine-to-machine authentication without user context |
Setting Up OAuth
To implement OAuth 2.0 authentication:
- Register your application in the MyAppAPI Dashboard
- Configure redirect URLs and select the required scopes
- Receive your Client ID and Client Secret
- Implement the appropriate OAuth flow in your application
OAuth Endpoints
Endpoint | URL | Purpose |
---|---|---|
Authorization | https://auth.myappapi.com/oauth/authorize |
Initiates user authentication and consent |
Token | https://auth.myappapi.com/oauth/token |
Exchanges authorization codes for tokens |
Revocation | https://auth.myappapi.com/oauth/revoke |
Revokes active tokens |
User Info | https://auth.myappapi.com/oauth/userinfo |
Retrieves authenticated user information |
Authorization Code Flow Example
This is the most common and secure OAuth flow for web applications:
Step 1: Redirect to Authorization Page
// Construct the authorization URL
const authorizationUrl = new URL('https://auth.myappapi.com/oauth/authorize');
authorizationUrl.searchParams.append('client_id', 'YOUR_CLIENT_ID');
authorizationUrl.searchParams.append('redirect_uri', 'https://yourapp.com/callback');
authorizationUrl.searchParams.append('response_type', 'code');
authorizationUrl.searchParams.append('scope', 'read:users write:users');
authorizationUrl.searchParams.append('state', generateRandomState()); // Security measure
// Redirect the user
window.location.href = authorizationUrl.toString();
<?php
// Construct the authorization URL
$params = [
'client_id' => 'YOUR_CLIENT_ID',
'redirect_uri' => 'https://yourapp.com/callback',
'response_type' => 'code',
'scope' => 'read:users write:users',
'state' => bin2hex(random_bytes(16)) // Security measure
];
// Store state in session for verification
$_SESSION['oauth_state'] = $params['state'];
// Redirect the user
$authUrl = 'https://auth.myappapi.com/oauth/authorize?' . http_build_query($params);
header('Location: ' . $authUrl);
exit;
?>
Step 2: Handle the Callback
// Using Express.js as an example
app.get('/callback', async (req, res) => {
// Verify state to prevent CSRF
if (req.query.state !== storedState) {
return res.status(400).send('State mismatch error');
}
// Exchange code for tokens
try {
const tokenResponse = await fetch('https://auth.myappapi.com/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
grant_type: 'authorization_code',
code: req.query.code,
redirect_uri: 'https://yourapp.com/callback'
})
});
const tokens = await tokenResponse.json();
// Store tokens securely (e.g., in encrypted session/database)
req.session.accessToken = tokens.access_token;
req.session.refreshToken = tokens.refresh_token;
// Redirect to app home
res.redirect('/dashboard');
} catch (error) {
console.error('Error exchanging code for tokens:', error);
res.status(500).send('Authentication failed');
}
});
<?php
// Callback handler
session_start();
// Verify state to prevent CSRF
if ($_GET['state'] !== $_SESSION['oauth_state']) {
die('State mismatch error');
}
// Exchange code for tokens
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://auth.myappapi.com/oauth/token');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'client_id' => 'YOUR_CLIENT_ID',
'client_secret' => 'YOUR_CLIENT_SECRET',
'grant_type' => 'authorization_code',
'code' => $_GET['code'],
'redirect_uri' => 'https://yourapp.com/callback'
]));
$response = curl_exec($ch);
$tokens = json_decode($response, true);
curl_close($ch);
if (isset($tokens['access_token'])) {
// Store tokens securely
$_SESSION['access_token'] = $tokens['access_token'];
$_SESSION['refresh_token'] = $tokens['refresh_token'];
// Redirect to app home
header('Location: /dashboard');
exit;
} else {
// Handle error
die('Authentication failed');
}
?>
Step 3: Use the Access Token
// Making authenticated API requests
async function getUserProfile() {
try {
const response = await fetch('https://api.myappapi.com/v1/users/me', {
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
return await response.json();
} catch (error) {
console.error('API request failed:', error);
// Handle token expiration and refresh if needed
if (error.status === 401) {
await refreshAccessToken();
return getUserProfile();
}
throw error;
}
}
<?php
// Making authenticated API requests
function getUserProfile() {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.myappapi.com/v1/users/me');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $_SESSION['access_token']
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Handle token expiration
if ($httpCode === 401) {
refreshAccessToken();
return getUserProfile();
}
return json_decode($response, true);
}
?>
Token Refresh Flow
OAuth access tokens expire after a set time (typically 1 hour). Use refresh tokens to get a new access token without user interaction:
async function refreshAccessToken() {
try {
const tokenResponse = await fetch('https://auth.myappapi.com/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
grant_type: 'refresh_token',
refresh_token: refreshToken
})
});
const tokens = await tokenResponse.json();
// Update stored tokens
accessToken = tokens.access_token;
// Refresh token might also be updated
if (tokens.refresh_token) {
refreshToken = tokens.refresh_token;
}
return tokens;
} catch (error) {
console.error('Error refreshing token:', error);
// If refresh fails, redirect to login
window.location.href = '/login';
throw error;
}
}
import requests
def refresh_access_token(refresh_token):
token_url = 'https://auth.myappapi.com/oauth/token'
payload = {
'client_id': 'YOUR_CLIENT_ID',
'client_secret': 'YOUR_CLIENT_SECRET',
'grant_type': 'refresh_token',
'refresh_token': refresh_token
}
response = requests.post(token_url, data=payload)
if response.status_code == 200:
tokens = response.json()
# Update stored tokens
access_token = tokens['access_token']
# Refresh token might also be updated
if 'refresh_token' in tokens:
refresh_token = tokens['refresh_token']
return tokens
else:
# If refresh fails, redirect to login
print('Token refresh failed, user must log in again')
return None
OAuth Libraries
Consider using established OAuth libraries for your platform to simplify implementation and avoid security pitfalls:
- JavaScript: Passport OAuth2, Auth0 SPA SDK
- Python: Requests-OAuthlib, Python Social Auth
- PHP: PHP League OAuth 2.0 Client
- Java: Spring Security OAuth
- .NET: Microsoft.Identity.Client
JWT Authentication
JSON Web Tokens (JWT) provide a compact, self-contained way for securely transmitting information between parties. This makes them ideal for stateless authentication in distributed systems.
JWT Structure
A JWT consists of three parts separated by dots (.):
- Header: Contains token type and signing algorithm
- Payload: Contains claims (user data and metadata)
- Signature: Verifies the token's integrity
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzEyMyIsIm5hbWUiOiJKb2huIERvZSIsImlhdCI6MTUxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Obtaining JWT Tokens
There are two ways to obtain JWT tokens with MyAppAPI:
1. Via OAuth 2.0
When using OAuth flows, you can request JWT format tokens by adding token_format=jwt
to your token request:
POST https://auth.myappapi.com/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=AuthorizationCodeFromCallback&
client_id=YourClientId&
client_secret=YourClientSecret&
redirect_uri=https://yourapp.com/callback&
token_format=jwt
2. Via Direct Authentication
For server-side applications, you can obtain a JWT by authenticating directly:
async function getJwtToken() {
const response = await fetch('https://auth.myappapi.com/v1/auth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
audience: 'https://api.myappapi.com',
grant_type: 'client_credentials'
})
});
const data = await response.json();
return data.access_token; // This is a JWT
}
import requests
def get_jwt_token():
url = 'https://auth.myappapi.com/v1/auth/token'
payload = {
'client_id': 'YOUR_CLIENT_ID',
'client_secret': 'YOUR_CLIENT_SECRET',
'audience': 'https://api.myappapi.com',
'grant_type': 'client_credentials'
}
response = requests.post(url, json=payload)
data = response.json()
return data['access_token'] # This is a JWT
Using JWT Tokens
Include the JWT in the Authorization header with the Bearer scheme:
curl -X GET "https://api.myappapi.com/v1/users" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
fetch('https://api.myappapi.com/v1/users', {
headers: {
'Authorization': `Bearer ${jwtToken}`
}
})
.then(response => response.json())
.then(data => console.log(data));
import requests
headers = {
'Authorization': f'Bearer {jwt_token}'
}
response = requests.get('https://api.myappapi.com/v1/users', headers=headers)
data = response.json()
print(data)
JWT Validation
JWTs should be validated on the client side to ensure they are not expired or tampered with:
// Using jose library
const { jwtVerify } = require('jose');
async function validateToken(token) {
try {
// Fetch public key (or use pre-shared secret)
const JWKS = jose.createRemoteJWKSet(
new URL('https://auth.myappapi.com/.well-known/jwks.json')
);
// Verify token
const { payload } = await jwtVerify(token, JWKS, {
issuer: 'https://auth.myappapi.com/',
audience: 'https://api.myappapi.com'
});
// Check if token is expired
const now = Math.floor(Date.now() / 1000);
if (payload.exp < now) {
throw new Error('Token expired');
}
return payload;
} catch (error) {
console.error('Token validation failed:', error);
throw error;
}
}
import jwt
import requests
from jwt.algorithms import RSAAlgorithm
import time
def validate_token(token):
try:
# Fetch public key
jwks_url = 'https://auth.myappapi.com/.well-known/jwks.json'
jwks_response = requests.get(jwks_url)
jwks = jwks_response.json()
# Extract key information from token header
header = jwt.get_unverified_header(token)
key = None
for jwk in jwks['keys']:
if jwk['kid'] == header['kid']:
key = RSAAlgorithm.from_jwk(jwk)
break
if key is None:
raise ValueError("Public key not found")
# Verify token
payload = jwt.decode(
token,
key,
algorithms=['RS256'],
options={"verify_signature": True},
audience='https://api.myappapi.com',
issuer='https://auth.myappapi.com/'
)
# Check if token is expired
now = int(time.time())
if payload['exp'] < now:
raise jwt.ExpiredSignatureError("Token expired")
return payload
except Exception as e:
print(f"Token validation failed: {e}")
raise
JWT Security Considerations
When working with JWTs:
- Always validate tokens on the server side
- Use short expiration times for tokens (1 hour or less)
- Implement token revocation for logout or security breaches
- Never store sensitive information in JWT payloads
- Use HTTPS to prevent token interception
Session Tokens
Session tokens provide a simpler authentication mechanism for web applications. They are typically used for frontend clients and browser-based applications.
Obtaining Session Tokens
To obtain a session token, users must authenticate through the login endpoint:
async function login(email, password) {
const response = await fetch('https://auth.myappapi.com/v1/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: email,
password: password
})
});
const data = await response.json();
if (response.ok) {
// Store the session token
localStorage.setItem('sessionToken', data.session_token);
return data;
} else {
throw new Error(data.message || 'Authentication failed');
}
}
import requests
def login(email, password):
url = 'https://auth.myappapi.com/v1/auth/login'
payload = {
'email': email,
'password': password
}
response = requests.post(url, json=payload)
data = response.json()
if response.status_code == 200:
# Store the session token
session_token = data['session_token']
return data
else:
raise Exception(data.get('message', 'Authentication failed'))
Using Session Tokens
Include the session token in the X-Session-Token
header:
async function fetchUserProfile() {
const sessionToken = localStorage.getItem('sessionToken');
if (!sessionToken) {
throw new Error('Not authenticated');
}
const response = await fetch('https://api.myappapi.com/v1/users/me', {
headers: {
'X-Session-Token': sessionToken
}
});
if (response.status === 401) {
// Token expired or invalid
localStorage.removeItem('sessionToken');
// Redirect to login
window.location.href = '/login';
return;
}
return await response.json();
}
import requests
def fetch_user_profile(session_token):
if not session_token:
raise Exception('Not authenticated')
headers = {
'X-Session-Token': session_token
}
response = requests.get('https://api.myappapi.com/v1/users/me', headers=headers)
if response.status_code == 401:
# Token expired or invalid
print('Session expired, please log in again')
return None
return response.json()
Session Token Lifecycle
Session tokens typically have the following lifecycle:
- Creation: Generated when the user successfully logs in
- Expiration: Automatically expires after a set time (default: 24 hours)
- Renewal: Can be refreshed using the renewal endpoint
- Revocation: Explicitly invalidated when the user logs out
Renewing Session Tokens
async function renewSessionToken() {
const currentToken = localStorage.getItem('sessionToken');
if (!currentToken) {
throw new Error('No session token to renew');
}
try {
const response = await fetch('https://auth.myappapi.com/v1/auth/renew', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Session-Token': currentToken
}
});
const data = await response.json();
if (response.ok) {
// Update the session token
localStorage.setItem('sessionToken', data.session_token);
return data;
} else {
// Token couldn't be renewed
localStorage.removeItem('sessionToken');
throw new Error(data.message || 'Session renewal failed');
}
} catch (error) {
console.error('Error renewing session:', error);
// Redirect to login
window.location.href = '/login';
throw error;
}
}
Logging Out (Revoking Session Tokens)
async function logout() {
const sessionToken = localStorage.getItem('sessionToken');
if (sessionToken) {
try {
// Revoke the token on the server
await fetch('https://auth.myappapi.com/v1/auth/logout', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Session-Token': sessionToken
}
});
} catch (error) {
console.error('Error during logout:', error);
}
// Always clear local storage even if server request fails
localStorage.removeItem('sessionToken');
}
// Redirect to login
window.location.href = '/login';
}
Session Security Tips
To ensure secure handling of session tokens:
- Always use HTTPS to prevent token interception
- Store tokens in secure, HTTP-only cookies when possible
- Implement CSRF protection for cookie-based sessions
- Use shorter expiration times for sensitive operations
- Provide a "Remember Me" option to control session duration based on user preference
Security Best Practices
Implementing proper authentication is just the first step. Follow these security best practices to ensure your API integrations remain secure:
General Security Recommendations
- Use HTTPS for all API requests to prevent man-in-the-middle attacks and data exposure
- Implement proper error handling to avoid leaking sensitive information in error messages
- Keep authentication credentials secure — never expose them in client-side code or GitHub repositories
- Use environment variables or secure secrets management solutions to store API keys and secrets
- Implement rate limiting on your side to avoid hitting API rate limits
- Monitor API usage to detect unusual patterns that might indicate a breach
API Key Security
- Never use API keys directly in client-side code — always proxy requests through your server
- Rotate API keys regularly, especially after team member changes
- Use scoped API keys with the minimum required permissions
- Set IP restrictions on API keys when possible
OAuth Security
- Use the Authorization Code flow with PKCE for mobile and SPA applications
- Validate all redirect URIs to prevent open redirect vulnerabilities
- Implement state parameter validation to prevent CSRF attacks
- Request the minimum required scopes to limit potential security impact
- Store refresh tokens securely on the server side, not in client-side storage
JWT Security
- Always validate JWTs on the server side, checking signature, expiration, issuer, and audience
- Use short expiration times for tokens to limit the window of vulnerability
- Implement token revocation for logout or security breaches
- Don't store sensitive information in JWT payloads, as they are easily decoded
Session Security
- Use HTTP-only, secure cookies for web applications when possible
- Implement CSRF protection for cookie-based sessions
- Regenerate session IDs after authentication state changes
- Set appropriate idle and absolute timeouts for sessions
Security Auditing
Regularly review your authentication implementation for security vulnerabilities. Consider using security tools like OWASP ZAP, automated scanners, or professional security audits for critical applications.
Troubleshooting Authentication Issues
If you encounter authentication problems, use this section to diagnose and resolve common issues:
Common Error Codes
HTTP Status | Error Code | Description | Resolution |
---|---|---|---|
401 | invalid_credentials | API key or credentials are invalid | Verify your API key or credentials are correct and active |
401 | expired_token | Token has expired | Refresh the token or re-authenticate |
401 | invalid_token | Token signature verification failed | Ensure the token hasn't been tampered with or incorrectly generated |
403 | insufficient_permissions | User lacks permission for the requested action | Request additional permissions or use an account with higher privileges |
403 | invalid_scope | Token does not have the required scope | Request the necessary scopes during OAuth authorization |
429 | rate_limit_exceeded | Too many authentication attempts | Implement exponential backoff and retry after the specified time |
Debugging Tips
- Check response headers: Authentication errors often include helpful information in response headers
- Verify token format: Ensure you're correctly formatting your authorization headers (e.g.,
Bearer <token>
) - Inspect token content: For JWTs, use tools like jwt.io to decode and inspect the contents
- Check token expiration: Verify that your tokens haven't expired and that your system's clock is correctly synchronized
- Examine scopes: Ensure your token has the necessary scopes for the requested operation
- Test with curl: Use curl commands to isolate API issues from application code problems
Getting Help
If you've tried the troubleshooting steps and still encounter issues:
- Check our FAQ for common questions and answers
- Visit the MyAppAPI Community Forum to see if others have encountered similar issues
- Contact [email protected] with details about your issue, including:
- Authentication method you're using
- Error messages and status codes
- API endpoint you're trying to access
- Code snippets demonstrating your authentication implementation (without sensitive credentials)