API REST

FOSRestBundle

oauth2

whoami


Rémi JANOT

https://github.com/rjanot

Lead dev Backend à

API


Du point de vue technique, une API est un ensemble de fonctions, procédures ou classes mises à disposition par une bibliothèque logicielle, un système d'exploitation ou un service. La connaissance des API est indispensable à l'interopérabilité entre les composants logiciels.

POURQUOI UNE API ?



  • Fournir des informations à des partenaires
  • Recevoir des informations des partenaires
  • Charger / rafraichir un bloc de manière asynchrone
  • Charger / rafraichir toute la page de manière asynchrone (Backbone, Angular JS...)
  • Application mobile

Les différents Types d'Api


  • SOAP
  • REST
  • JSON-RPC, XML-RPC
  • Maison ( Facebook - FQL )

REST

GET /api/users HTTP/1.1
Host: api.local.pricebuzz.fr
Accept: text/html

FOSRESTBUNDLE


<?php
namespace Acme\ApiBundle\Controller;

class UserRestController extends \FOS\RestBundle\Controller\FOSRestController
{
    public function optionsUsersAction()
    {} // "options_users" [OPTIONS] /users

    public function getUsersAction()
    {} // "get_users"     [GET] /users

    public function getUserAction($slug)
    {} // "get_user"      [GET] /users/{slug}

    public function postUsersAction()
    {} // "post_users"    [POST] /users

    public function patchUsersAction()
    {} // "patch_users"   [PATCH] /users

    public function putUserAction($slug)
    {} // "put_user"      [PUT] /users/{slug}

    public function patchUserAction($slug)
    {} // "patch_user"    [PATCH] /users/{slug}

    public function deleteUserAction($slug)
    {} // "delete_user"   [DELETE] /users/{slug}
public function newUsersAction() {} // "new_users" [GET] /users/new public function editUserAction($slug) {} // "edit_user" [GET] /users/{slug}/edit public function lockUserAction($slug) {} // "lock_user" [PATCH] /users/{slug}/lock public function banUserAction($slug) {} // "ban_user" [PATCH] /users/{slug}/ban public function removeUserAction($slug) {} // "remove_user" [GET] /users/{slug}/remove
public function getUserCommentsAction($slug) {} // "get_user_comments" [GET] /users/{slug}/comments public function newUserCommentsAction($slug) {} // "new_user_comments" [GET] /users/{slug}/comments/new public function postUserCommentsAction($slug) {} // "post_user_comments" [POST] /users/{slug}/comments public function getUserCommentAction($slug, $id) {} // "get_user_comment" [GET] /users/{slug}/comments/{id} public function editUserCommentAction($slug, $id) {} // "edit_user_comment" [GET] /users/{slug}/comments/{id}/edit public function putUserCommentAction($slug, $id) {} // "put_user_comment" [PUT] /users/{slug}/comments/{id} public function postUserCommentVoteAction($slug, $id) {} // "post_user_comment_vote" [POST] /users/{slug}/comments/{id}/vote public function removeUserCommentAction($slug, $id) {} // "remove_user_comment" [GET] /users/{slug}/comments/{id}/remove public function deleteUserCommentAction($slug, $id) {} // "delete_user_comment" [DELETE] /users/{slug}/comments/{id}
}

FOSRESTBUNDLE


users:
    type:     rest
    resource: Acme\ApiBundle\Controller\UserRestController
                    

FOSRESTBUNDLE


rjanot@rjanot-laptop:~/workspace/pb-api $ php app/console router:debug
[router] Current routes
Name                  Method Host Pattern
get_users             GET    ANY  /api/users.{_format}
get_user              GET    ANY  /api/users/{slug}.{_format}
post_users            POST   ANY  /api/users.{_format}
put_users             PUT    ANY  /api/users/{slug}.{_format}
delete_users          DELETE ANY  /api/users/{slug}.{_format}
get_user_comments GET ANY /api/users/{slug}/comments.{_format} get_user_comment GET ANY /api/users/{slug}/comments/{id}.{_format} ...

FOSRESTBUNDLE


<?php
namespace Acme\ApiBundle\Controller;

class CommentsController extends \FOS\RestBundle\Controller\FOSRestController
{
    public function postCommentVoteAction($slug, $id)
    {} // "post_user_comment_vote" [POST] /users/{slug}/comments/{id}/vote

    public function getCommentsAction($slug)
    {} // "get_user_comments"   [GET] /users/{slug}/comments

    public function getCommentAction($slug, $id)
    {} // "get_user_comment"    [GET] /users/{slug}/comments/{id}

    public function deleteCommentAction($slug, $id)
    {} // "delete_user_comment" [DELETE] /users/{slug}/comments/{id}

    public function newCommentsAction($slug)
    {} // "new_user_comments"   [GET] /users/{slug}/comments/new

    public function editCommentAction($slug, $id)
    {} // "edit_user_comment"   [GET] /users/{slug}/comments/{id}/edit

    public function removeCommentAction($slug, $id)
    {} // "remove_user_comment" [GET] /users/{slug}/comments/{id}/remove
}
                    

FOSRESTBUNDLE


users:
    type:     rest
    resource: Acme\HelloBundle\Controller\UsersController

comments:
    type:     rest
    parent:   users
    resource: Acme\HelloBundle\Controller\CommentsController
                    

// src/Acme/DemoBundle/Controller/TestController.php
namespace Acme\DemoBundle\Controller;

use FOS\RestBundle\Controller\FOSRestController;

class TestController extends FOSRestController
{
    public function getAction()
    {
        $data = array(
            'text'          => 'lol',
            'assoc_array'   => array(
                'text'          => 'truc',
                'number'        => 42,
                'float'         => 42.24,
                'empty'         => '',
            ),
            'number'        => 1,
            'simple_array'  => array('symfony','php','zend'),
        );

        $view = $this->view($data);

        return $this->handleView($view, 200);
    }
}
                

FOSRESTBUNDLE


rjanot@rjanot-laptop:~/workspace/pb-api $ php app/console router:debug
[router] Current routes
Name                  Method Host Pattern
get_users             GET    ANY  /api/users.{_format}
get_user              GET    ANY  /api/users/{slug}.{_format}
post_users            POST   ANY  /api/users.{_format}
put_users             PUT    ANY  /api/users/{slug}.{_format}
delete_users          DELETE ANY  /api/users/{slug}.{_format}
                    

FOSRESTBUNDLE


# app/config/config.yml
fos_rest:
    routing_loader:
        default_format: json
    view:
        formats:
            json: true
            xml: false
                    

OAuth2

Principe d'une session sur un site classique


  • Header HTTP : token de session dans le cookie PHPSESSID
  • Recherche de la session : filesystem, memcache, DB, ...
  • Chargement des informations dans $_SESSION

Permet d'enregistrer:
  • l'utilisateur
  • un panier d'achat
  • ...

Principe de l'authentification OAuth 2


Ne s'occupe que de l'authentification et des permissions de l'application sur les informations / actions de l'utilisateur !

  • récupération d'un access_token d'identification:
    • dans la query string
    • dans le corps de la requête
    • dans les en-têtes HTTP
  • Recherche des permissions, de l'application et de l'utilisateur : filesystem, memcache, DB, Redis, ...
  • Chargement des informations dans la sécurité SF2

Plusieurs methodes d'obtention d'un access_token:


  • redirection avec un hash
    • GET /authenticate_me
    • client_id=123&scope=email&response_type=token
    • Location: myapp.com/validate_auth_code#access_token=...&refresh_token=...&user_id=...
  • redirection vers le server OAuth en demandant un auth_code
    • GET /authenticate_me
    • client_id=123&scope=email&response_type=auth_code
    • Location: myapp.com/validate_auth_code?auth_code=1234567890abcdef

Schema d'btention d'un access_token à partir d'un auth_code:


Plusieurs methodes d'obtention d'un access_token:


  • auth_code
    • POST /token
    • grant_type=auth_code&client_id=123&scope=email,feed&code=1234567890abcdef
  • password
    • POST /token
    • grant_type=password&client_id=123&scope=email,feed&username=r.janot@gmail.com&password=symfony
  • assertion
    • POST /token
    • grant_type=assertion&client_id=123&scope=email,feed&assertion_type=fb_sr&assertion=....
  • refresh_token
    • POST /token
    • grant_type=refresh_token&client_id=123&scope=email,feed&refresh_token=azertyuiop

Liens