Autenticazione dei servizi
Autenticare i servizi distribuiti
DownToZero (DTZ) fornisce un’autenticazione integrata per i tuoi servizi distribuiti, rendendo semplice costruire applicazioni sicure senza gestire la tua infrastruttura di autenticazione.
Panoramica
Quando distribuisci un servizio su DTZ, la piattaforma fornisce automaticamente credenziali di autenticazione e informazioni di contesto tramite variabili d’ambiente. Il tuo servizio può utilizzarle per:
- Autenticare le richieste verso altri servizi DTZ (chiamate API, object storage, ecc.)
- Verificare le richieste in ingresso dagli utenti
- Accedere a risorse specifiche del contesto
- Implementare comunicazioni sicure tra servizi
Variabili d’ambiente
DTZ inietta automaticamente le seguenti variabili d’ambiente nei container del tuo servizio:
| Variabile | Descrizione | Esempio |
|---|---|---|
DTZ_ACCESS_TOKEN |
Un token JWT per accedere ai servizi DTZ all’interno del tuo contesto. | eyJhbGciOiJSUzI1NiI... |
DTZ_CONTEXT_ID |
Il tuo identificatore di contesto DTZ. | context-3cd84429-64a4-4226-b868-c83feeff0f46 |
PORT |
La porta su cui il tuo servizio dovrebbe ascoltare. | 80 |
Autenticazione delle richieste in ingresso
Il tuo servizio distribuito può autenticare le richieste in ingresso usando diversi metodi:
Autenticazione con API Key
Gli utenti possono autenticarsi con il tuo servizio usando le API key di DTZ fornendo la key nell’header X-API-KEY.
curl -H "X-API-KEY: your-api-key" https://yourservice.dtz.rocks/api/endpoint
Autenticazione con token Bearer
Fornisci un token JWT nell’header Authorization per autenticare.
curl -H "Authorization: Bearer your-jwt-token" https://yourservice.dtz.rocks/api/endpoint
Autenticazione Basic
Puoi anche passare le API key usando l’autenticazione basic.
curl -u apikey:your-api-key https://yourservice.dtz.rocks/api/endpoint
Autenticazione basata su cookie
Per le applicazioni web, il servizio Identity di DTZ può gestire l’autenticazione tramite cookie del browser.
Flusso OAuth
DTZ fornisce autenticazione OAuth automatica per le applicazioni web. Quando utenti non autenticati accedono al tuo servizio, vengono automaticamente reindirizzati alla pagina di login DTZ e poi reindirizzati indietro dopo un login riuscito.
Utilizzare l’autenticazione DTZ nel tuo servizio
Effettuare richieste autenticate ai servizi DTZ
Usa la variabile d’ambiente DTZ_ACCESS_TOKEN per effettuare chiamate autenticate verso altri servizi DTZ.
import os
import requests
# Get the DTZ access token from the environment
token = os.environ.get('DTZ_ACCESS_TOKEN')
context_id = os.environ.get('DTZ_CONTEXT_ID')
# Make an authenticated request to the DTZ API
headers = {
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
response = requests.get(
'https://api.dtz.rocks/v1/containers/services',
headers=headers
)
// Node.js example
const token = process.env.DTZ_ACCESS_TOKEN;
const contextId = process.env.DTZ_CONTEXT_ID;
const response = await fetch('https://api.dtz.rocks/v1/containers/services', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
# Bash example
curl -H "Authorization: Bearer $DTZ_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
https://api.dtz.rocks/v1/containers/services
Verificare l’autenticazione in ingresso
DTZ gestisce automaticamente l’autenticazione per le richieste in ingresso. Quando un utente effettua una richiesta autenticata al tuo servizio, DTZ:
- Valida le credenziali di autenticazione.
- Converte le API key in token JWT.
- Inoltra la richiesta con un header
Authorization: Bearer <token>.
Il tuo servizio riceve il token JWT e può estrarre le informazioni sull’utente da esso.
import jwt
import os
from flask import Flask, request
app = Flask(__name__)
@app.route('/protected')
def protected_endpoint():
auth_header = request.headers.get('Authorization')
if not auth_header or not auth_header.startswith('Bearer '):
return {'error': 'No authentication provided'}, 401
token = auth_header.split(' ')[1]
try:
# The token is already verified by DTZ, so you can
# extract claims without signature verification.
payload = jwt.decode(token, options={"verify_signature": False})
user_id = payload.get('sub') # Identity ID
context_id = payload.get('scope') # Context ID
roles = payload.get('roles', []) # User roles
return {
'user_id': user_id,
'context_id': context_id,
'roles': roles,
'message': 'Access granted'
}
except jwt.InvalidTokenError:
return {'error': 'Invalid token'}, 401
// Express.js example
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
app.get('/protected', (req, res) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'No authentication provided' });
}
const token = authHeader.split(' ')[1];
try {
// The token is already verified by DTZ.
const payload = jwt.decode(token);
const userId = payload.sub; // Identity ID
const contextId = payload.scope; // Context ID
const roles = payload.roles || []; // User roles
res.json({
user_id: userId,
context_id: contextId,
roles: roles,
message: 'Access granted'
});
} catch (error) {
res.status(401).json({ error: 'Invalid token' });
}
});
Struttura del token JWT
I token JWT di DTZ contengono le seguenti claim:
| Claim | Descrizione | Esempio |
|---|---|---|
iss |
Emittente (sempre “dtz.rocks”) | "dtz.rocks" |
sub |
Soggetto (ID identità utente) | "identity-abc123..." |
aud |
Audience (sempre “dtz.rocks”) | "dtz.rocks" |
scope |
ID del contesto | "context-3cd84429..." |
roles |
Ruoli/permessi dell’utente | ["https://dtz.rocks/context/admin/{context_id}"] |
contexts |
Contesti disponibili | ["context-3cd84429..."] |
exp |
Tempo di scadenza | 1640995200 |
iat |
Tempo di emissione | 1640908800 |
Controllo degli accessi basato sui ruoli
DTZ utilizza il controllo degli accessi basato sui ruoli con identificatori di ruolo basati su URI. Alcuni pattern di ruolo comuni includono:
https://dtz.rocks/context/admin/{context_id}- Amministratore del contestohttps://dtz.rocks/containers/admin/{context_id}- Amministratore dei servizi containerhttps://dtz.rocks/objectstore/admin/{context_id}- Amministratore dello storage oggetti
Puoi verificare i ruoli nel tuo servizio:
def check_role(token, required_role_pattern):
payload = jwt.decode(token, options={"verify_signature": False})
roles = payload.get('roles', [])
context_id = payload.get('scope')
required_role = required_role_pattern.replace('{context_id}', context_id)
return required_role in roles
# Example:
if check_role(token, 'https://dtz.rocks/containers/admin/{context_id}'):
# User has container admin permissions
pass
Buone pratiche
Sicurezza
- Verifica sempre che i token JWT contengano le claim attese.
- Controlla i ruoli degli utenti prima di concedere accesso a operazioni sensibili.
- Usa HTTPS per tutte le comunicazioni.
- Non registrare (log) token di autenticazione sensibili.
Gestione degli errori
- Restituisci codici di stato HTTP appropriati (es. 401 per non autorizzato, 403 per vietato).
- Fornisci messaggi di errore significativi senza esporre informazioni sensibili.
Prestazioni
- Cache i risultati della validazione dei token JWT quando possibile.
- Usa il connection pooling per le chiamate alle API DTZ.
- Valuta l’implementazione di limitazione della frequenza delle richieste (rate limiting).
Esempio: servizio autenticato completo
Here is a complete example of a Python Flask service with DTZ authentication:
import os
import jwt
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
DTZ_TOKEN = os.environ.get('DTZ_ACCESS_TOKEN')
DTZ_CONTEXT_ID = os.environ.get('DTZ_CONTEXT_ID')
def get_user_from_token(token):
"""Extracts user information from a DTZ JWT token."""
try:
payload = jwt.decode(token, options={"verify_signature": False})
return {
'user_id': payload.get('sub'),
'context_id': payload.get('scope'),
'roles': payload.get('roles', [])
}
except jwt.InvalidTokenError:
return None
def require_auth(f):
"""A decorator to require authentication."""
def decorated(*args, **kwargs):
auth_header = request.headers.get('Authorization')
if not auth_header or not auth_header.startswith('Bearer '):
return jsonify({'error': 'Authentication required'}), 401
token = auth_header.split(' ')[1]
user = get_user_from_token(token)
if not user:
return jsonify({'error': 'Invalid token'}), 401
request.user = user
return f(*args, **kwargs)
decorated.__name__ = f.__name__
return decorated
@app.route('/health')
def health():
"""A public health check endpoint."""
return jsonify({'status': 'healthy'})
@app.route('/profile')
@require_auth
def profile():
"""A protected endpoint that returns the user's profile."""
return jsonify({
'user_id': request.user['user_id'],
'context_id': request.user['context_id'],
'roles': request.user['roles']
})
@app.route('/admin/users')
@require_auth
def admin_users():
"""An admin-only endpoint."""
required_role = f'https://dtz.rocks/context/admin/{DTZ_CONTEXT_ID}'
if required_role not in request.user['roles']:
return jsonify({'error': 'Admin access required'}), 403
# Make an authenticated request to the DTZ API
headers = {'Authorization': f'Bearer {DTZ_TOKEN}'}
response = requests.get(
'https://identity.dtz.rocks/api/2021-02-21/users',
headers=headers
)
return jsonify(response.json())
if __name__ == '__main__':
port = int(os.environ.get('PORT', 80))
app.run(host='0.0.0.0', port=port)
Risoluzione dei problemi
Problemi comuni
- Authentication token not found: Assicurati che il tuo servizio sia distribuito tramite il servizio containers di DTZ e che le variabili d’ambiente siano lette correttamente.
- Invalid token errors: Verifica che stai estraendo correttamente il token dall’header
Authorizatione che il parsing del JWT funzioni. - 403 Forbidden errors: Verifica che l’utente abbia i ruoli richiesti nel proprio token JWT.
- Service-to-service authentication failing: Assicurati di usare la variabile d’ambiente
DTZ_ACCESS_TOKENper le richieste in uscita.
Test dell’autenticazione
Puoi testare l’autenticazione del tuo servizio usando curl:
# Test with an API key
curl -H "X-API-KEY: your-api-key" https://yourservice.dtz.rocks/profile
# Test with a bearer token
curl -H "Authorization: Bearer your-jwt-token" https://yourservice.dtz.rocks/profile
# Test unauthenticated (should return 401)
curl https://yourservice.dtz.rocks/profile
Per informazioni più dettagliate sull’autenticazione DTZ, consulta la documentazione sull’autenticazione.