Comment mettre en œuvre FosOAuthServerBundle pour sécuriser une API REST?
Je tiens à fournir une API RESTful sécurisé avec OAuth2 à l'aide de FOSOAuthServerBundle et je ne suis pas vraiment sûr de ce que j'ai à faire.
J'ai suivi les étapes de base à partir de la documentation mais certaines choses sont manquant et je ne peux pas trouver un exemple complet de ce dont j'ai besoin.
Donc, j'ai essayé de comprendre du mieux que je pouvais cet exemple de mise en œuvre (le seul que j'ai trouvé), mais il ya encore des choses que je ne comprends pas.
Tout d'abord, pourquoi avons-nous besoin d'une page de connexion à un API? Supposons que mon client est un iPhone ou Application Android, je vois l'intérêt de la page de connexion à l'application, mais je pense que le client a juste à appeler un service web à partir de l'API pour obtenir son jeton, je me trompe? Alors, comment mettre en œuvre une autorisation et un jeton de fournir via le point de terminaison REST?
Puis, la documentation dit d'écrire ce pare-feu :
oauth_authorize:
pattern: ^/oauth/v2/auth
# Add your favorite authentication process here
Et je ne sais pas comment ajouter un processus d'authentification. Dois-je écrire ma propre personne, par exemple suite à ce tutoriel ou suis-je complètement tort?
À l'échelle mondiale, quelqu'un peut prendre le temps d'expliquer le processus nécessaire, après les cinq étapes dans les docs, pour fournir une OAuth2 sécurisé API RESTful? Il serait très agréable...
MODIFIER après @Sehael réponse :
J'ai encore quelques questions avant c'est parfait...
Ce qui est représenté par le "Client" ici? Pour exemaple, dois-je créer un client pour une application iPhone, et un autre pour une application Android? et dois-je créer un nouveau client pour chaque instance de vouloir utiliser l'API? quelle est la meilleure pratique dans ce cas?
Contrairement à vous, je n'utilise pas le processus d'authentification OAuth pour le front, site web, mais le "classique" de symfony façon. Il semble étrange pour vous, ou est-ce normal?
Quelle est l'utilité de la refresh_token? Comment l'utiliser?
J'ai essayé de tester mon nouveau OAuth services protégés. J'ai utilisé le Facteur extension chrome, qui prennent en charge le protocole OAuth 1.0, ne OAuth2 ressembler OAuth1 assez pour être testé avec Facteur? Il y a un "jeton secret" champ que je ne sais pas comment le remplir. Si je ne peux pas, je serais heureux de voir votre (@Sehael) classe PHP, comme vous l'avez proposé. /Edit : OK je crois que j'ai trouvé la réponse pour celui-ci. J'ai juste ajouté access_token
comme paramètre GET avec le jeton de la valeur. Il semble être au travail. Il est regrettable que je ne reverse engenering sur bundle code pour trouver que, au lieu de le lire dans la documentation.
De toute façon, merci beaucoup !
Vous devez vous connecter pour publier un commentaire.
J'ai également constaté que la documentation peut être un peu déroutant. Mais après de nombreuses heures de l'essayer, j'ai tout compris, avec l'aide de ce blog (mise à jour - le blog n'existe plus, changé à l'Internet Archive). Dans votre cas, vous n'avez pas besoin d'un pare-feu entrée pour
^/oauth/v2/auth
parce que c'est pour la page d'autorisation. Vous devez vous rappeler ce que oAuth est capable de le faire... il est utilisé pour plus que juste une api REST. Mais si une api REST est ce que vous souhaitez protéger, vous n'en avez pas besoin. voici un exemple de config du pare-feu à partir de mon application:Avis que vous avez besoin de définir un utilisateur du fournisseur. Si vous utiliser FOSUserBundle, il y a un utilisateur fournisseur déjà créé pour vous. Dans mon cas, j'ai fait mon propre et de créer un service hors de lui.
Et dans ma config.yml:
Je dois aussi mentionner que les tables que vous créez dans la base de données (access_token, client, auth_code, refresh_token) sont tenus d'avoir plus de champs que de ce qui est indiqué dans les docs...
Jeton d'accès de la Table: id(int), client_id(int), user_id(int), jeton(chaîne de caractères), la portée(string), expires_at(int)
Client de la Table: id(int), random_id(string), secret(string), redirect_urls(string), allowed_grant_types(string)
Auth Code de la Table: id(int), client_id(int), user_id(int)
Jeton d'actualisation de la Table: id(int), client_id(int), user_id(int), jeton(string), expires_at(int), la portée(string)
Ces tableaux de stocker les informations nécessaires pour oAuth, afin de mettre à jour votre Doctrine entités afin qu'elles correspondent à la db tables comme ci-dessus.
Et puis vous avez besoin d'un moyen de générer le secret et client_id, alors c'est la "Création d'un Client" section de la documentation vient, mais il n'est pas très utile...
Créer un fichier à
/src/My/AuthBundle/Command/CreateClientCommand.php
(vous en aurez besoin pour créer le dossierCommand
) Ce code est à partir de l'article que j'ai lié ci-dessus, et montre un exemple de ce que vous pouvez mettre dans ce fichier:Ensuite pour créer le client_id et secret, exécuter cette commande à partir de la ligne de commande (ce sera à insérer dans la base de données de la nécessaire id et d'autres trucs):
php app/console acme:oauth-server:client:create --redirect-uri="http://clinet.local/" --grant-type="password" --grant-type="refresh_token" --grant-type="client_credentials"
avis que le
acme:oauth-server:client:create
peut être tout ce que vous avez réellement nom de votre commande dans leCreateClientCommand.php
fichier avec$this->setName('acme:oauth-server:client:create')
.Une fois que vous avez le client_id et secret, vous êtes prêt à s'authentifier. Faites une demande à votre navigateur et qui est quelque chose comme ceci:
http://example.com/oauth/v2/token?client_id=[CLIENT_ID_YOU GENERATED]&client_secret=[SECRET_YOU_GENERATED]&grant_type=password&username=[USERNAME]&password=[PASSWORD]
Espérons que cela fonctionne pour vous. Il y a certainement beaucoup de choses à configurer, il suffit d'essayer de prendre une étape à la fois.
J'ai aussi écrit une simple classe PHP pour appeler mon Symfony api REST en utilisant oAuth, si vous pensez que ce serait utile, faites le moi savoir et je peux le transmettre.
Mise à JOUR
En réponse à vos autres questions:
Le "client" est décrite sur le même blog, juste un autre article. Lire la Les Clients et les champs l'article ici, il convient de clarifier pour vous ce qu'est un client. Comme mentionné dans l'article, vous n'avez pas besoin d'un client pour chaque utilisateur. Vous pourriez avoir un client unique pour toutes vos utilisateurs, si vous le souhaitez.
Je suis également à l'aide de la classique de Symfony authentification pour mon frontend du site, mais cela peut changer dans l'avenir. Donc, il est toujours bon de garder ces choses dans le dos de votre esprit, mais je ne dirais pas que c'est étrange de combiner les deux méthodes.
La refresh_token est utilisé lorsque l'access_token a expiré et vous souhaitez demander une nouvelle access_token sans renvoyer les informations d'identification utilisateur. au lieu de cela, vous envoyer le jeton d'actualisation et d'obtenir un nouveau access_token. Ce n'est pas vraiment nécessaire pour une API REST, car une seule demande ne sera probablement pas prendre suffisamment longtemps pour que l'access_token le point d'expirer.
oAuth1 et oAuth2 sont très différents, donc, je suppose que la méthode que vous utilisez ne fonctionne pas, mais je n'ai jamais essayé avec qui. Mais juste pour le test, vous pouvez faire un normal requête GET ou POST, aussi longtemps que vous passez le
access_token=[ACCESS_TOKEN]
dans la chaîne de requête GET (pour tous les types de demandes, en fait).Mais de toute façon, ici, c'est ma classe. J'ai utilisé un fichier de configuration pour stocker des variables, et je n'ai pas implémenté la possibilité de SUPPRIMER, mais ce n'est pas trop dur.
Puis d'utiliser la classe, tout:
/api
est protégé par le protocole oauth, mais si vous ajoutez une nouvelle définition de la route (avec préfixe différent) qui pointe vers la même contrôleurs, vous pouvez le protéger d'une manière différente (comme un formulaire de login)