Je travaille sur l'ajout d'une API REST à un ancien site PHP site. Il s'agit de fournir un point de terminaison pour une application interne, donc je suis assez libre dans la façon dont Je conçois des choses et ce que je supporte ou non.
Ce que je dois maintenant ajouter à cette API est un moyen de se connecter, puis d'effectuer des actions en tant qu'utilisateur spécifique. Le site a été construit il y a des années et ne correspond pas nécessairement aux meilleures pratiques de l'époque, donc je suis malheureusement un peu limité dans ma façon de procéder. Tout cela doit être exécuté en PHP 5.4 avec MySQL 5.6.
J'ai lu sur des conceptions courantes pour cela et OAuth1/2 ressemble à la norme la plus courante. Cependant, cela semble être une surpuissance massive pour mes besoins, car il a diverses fonctionnalités dont je n'ai pas besoin et semble très compliqué à mettre en œuvre.
Au lieu de cela, je prévois de faire quelque chose comme ça:
get_session
Le point de terminaison API, qui génère un ID de session aléatoire, l'enregistre dans une table de la base de données et le renvoie au client.login
, en envoyant le nom d'utilisateur, le mot de passe et l'ID de session (via HTTPS évidemment).logout
et le serveur supprime l'association avec le compte d'utilisateur.Est-ce une conception raisonnable? Ce n'est évidemment pas très sophistiqué, mais je suis à la recherche de quelque chose que je peux implémenter sans tracas énormes ou nécessitant des bibliothèques tierces.
L'un des principaux points de REST en tant que concept est d'éviter l'utilisation de l'état de session afin de faciliter la mise à l'échelle horizontale des ressources de votre point de terminaison REST). Si vous prévoyez d'utiliser le PHP de $_SESSION
comme indiqué dans votre question, vous allez vous retrouver dans une position difficile de devoir implémenter le stockage de session partagée dans le cas où vous souhaitez évoluer.
Alors que OAuth serait la méthode préférée pour ce que vous voulez faire, une implémentation complète peut être plus de travail que vous ne voudriez y mettre. Cependant, vous pouvez vous tailler quelque chose d'un demi- mesure et restent sans session. Vous avez probablement déjà vu des solutions similaires auparavant.
De cette façon, vous maintenez l'idéal "sans session" REST) et vous ne transmettez jamais réellement le secret pendant une partie de l'échange.
Exemple client:
$token = "Bmn0c8rQDJoGTibk"; // base64_encode(random_bytes(12));
$secret = "yXWczx0LwgKInpMFfgh0gCYCA8EKbOnw"; // base64_encode(random_bytes(24));
$stamp = "2017-10-12T23:54:50+00:00"; // date("c");
$sig = hash_hmac('SHA256', $stamp, base64_decode($secret));
// Result: "1f3ff7b1165b36a18dd9d4c32a733b15c22f63f34283df7bd7de65a690cc6f21"
$request->addHeader("X-Auth-Token: $token");
$request->addHeader("X-Auth-Signature: $sig");
$request->addHeader("X-Auth-Timestamp: $stamp");
Exemple de serveur:
$token = $request->getToken();
$secret = $auth->getSecret($token);
$sig = $request->getSignature();
$success = $auth->validateSignature($sig, $secret);
Il convient de noter que si vous décidez d'utiliser un horodatage en tant que nonce, vous ne devez accepter que les horodatages générés au cours des dernières minutes pour éviter les attaques de relecture. La plupart des autres schémas d'authentification incluront des composants supplémentaires dans les données signées, tels que le chemin d'accès aux ressources, des sous-ensembles de données d'en-tête, etc. pour verrouiller davantage la signature afin de ne l'appliquer qu'à une seule demande.
Je dirais que vous devez générer un jeton unique et l'utiliser pour la communication. Fondamentalement:
login
.sessions
et le renvoie à l'utilisateur, avec une mise à jour d'état comme logged_in = TRUE
.token
(soit sous la forme d'un champ POST
ou d'un paramètre GET
). À ce stade, je reconsidérerais l'utilisation de REST et n'utiliserais que POST
requêtes pour tout, avec le operation
comme un POST champ. Cela n'ajouterait pas le jeton à l'URL et, donc, le laisserait être enregistré sur un historique de navigation Web, des routeurs et autres.403 Forbidden
Et logged_in = FALSE
.Le système pourrait également nécessiter d'envoyer d'autres données pour les rendre plus sécurisées, comme un unique id
Généré par le client et des trucs comme ça, qui devraient être envoyés avec le jeton et vérifié côté serveur.
Les points de votre plan sont essentiellement les fonctionnalités de base d'OAuth. Cela dépend de vos besoins. Si vos API sont à usage interne uniquement, vous pouvez envoyer une clé secrète avec l'authentification HMAC-SHA.
Eh bien, vous avez beaucoup écrit comment inventer des cookies à partir de zéro et comment les stocker dans la base de données.
Dans le même temps, vous avez déjà des noms d'utilisateur, des mots de passe et HTTPS pour le transfert de données de sécurité. Pourquoi n'utilisez-vous pas uniquement des cookies?