• Inicio
  • Web
  • Contacto
El Blog del desarrollador
Menu
  • Inicio
  • Web
  • Contacto
Inicio › General › Oauth 2 › Slim Framework › Usando Oauth 2 junto con Slim Framework para crear API segura: Parte2

Usando Oauth 2 junto con Slim Framework para crear API segura: Parte2

malakana 1 octubre, 2015     Sin Comentarios    

En el post anterior explicamos como configurar un servidor Oauth 2 para php que nos genere tokens de acceso validos con la intención de securizar nuestra API. En esta segunda parte del post vamos a desarrollar nuestra api apoyándonos en un microframework como Slim Framework y realizando conexiones CURL a nuestro servidor Oauth 2 para que nos valide si los token de accesos que enviamos están autorizados a acceder a la información de la API. Usaremos scopes para controlar los permisos de acceso a todos los métodos de nuestra API, vamos a ello.

/**
 * functions.php - Funciones para la conexión CURL que comproborá el token de acceso a la API
 * entities.php - Entidades que usaremos al extraer los datos desde la Base de datos
 */
require 'functions.php';
require 'entities.php';
/**
 * Autoloading SlimFramewok
 */
require 'vendor/autoload.php';
//

/**
 * $pdo - Adaptador para la base de datos usada para almacenar los valores oauth en la BD
 * $app - Instanciación de Slim
 */

$pdo = new PDO('mysql:host=localhost;dbname=bdname', 'user', 'password', array(
    PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'",
));
$app = new \Slim\Slim();

Para conectar a todos los métodos de nuestra api vamos a usar envío POST. A continuación el listado de métodos:

 * Listado de usuarios
 * url ejemplo: http://miaplicacion/usuarios/
 */
$app->post('/usuarios(/)', function () use ($app, $pdo) {

    if ($app->request()->post('access_token')) {

        if (curlCheckToken($app->request()->post('access_token') ,'usuarios')) {

            $stmt = $pdo->prepare("SELECT * FROM usuarios");
            $stmt->execute();
            $resultado = $stmt->fetchAll(PDO::FETCH_CLASS, "Usuarios");

            if ($resultado) {
                echo json_encode($resultado);
            }
            else {
                echo json_encode(array(
                    'error' => 'No hay registros'
                ));
            }
        }
    }
});

/**
 * Información de un usuario concreto, $id = id del usuario
 * Url ejemplo: http://miaplicacion/usuarios/1/
 */
$app->post('/usuarios/:id(/)', function ($id) use ($app, $pdo) {

    if ($app->request()->post('access_token')) {

        if (curlCheckToken($app->request()->post('access_token') ,'usuario')) {

            $stmt = $pdo->prepare("SELECT * FROM usuarios WHERE id = :id");
            $stmt->bindParam(':id', $id, PDO::PARAM_INT);
            $stmt->execute();
            $resultado = $stmt->fetchAll(PDO::FETCH_CLASS, "Usuario");

            if ($resultado) {
                echo json_encode($resultado);
            }
            else {
                echo json_encode(array(
                    'error' => 'Usuario no encontrado'
                ));
            }
        }
    }
});

/**
 * Listado de mensajes de un usuario, $id = id del usuario
 * Url ejemplo: http://miaplicacion/usuarios/1/mensajes/
 */
$app->post('/usuarios/:id/mensajes(/)', function ($id) use ($app, $pdo) {

    if ($app->request()->post('access_token')) {

        if (curlCheckToken($app->request()->post('access_token') ,'mensajes')) {

            $stmt = $pdo->prepare("SELECT * FROM mensajes WHERE usuario_id = :id");
            $stmt->bindParam(':id', $id, PDO::PARAM_INT);
            $stmt->execute();
            $resultado = $stmt->fetchAll(PDO::FETCH_CLASS, "Mensajes");

            if ($resultado) {
                echo json_encode($resultado);
            }
            else {
                echo json_encode(array(
                    'error' => 'No hay mensajes de este usuario'
                ));
            }
        }
    }
});

/**
 * Un mensaje de un usuario en concreto via $id = id del usuario y $mensajes = id del mensaje
 * Url ejemplo: http://miaplicacion/usuarios/1/mensajes/3/
 */
$app->post('/usuarios/:id/mensajes/:mensaje(/)', function ($id, $mensaje) use ($app, $pdo) {

    if ($app->request()->post('access_token')) {

        if (curlCheckToken($app->request()->post('access_token') ,'mensaje')) {

            $stmt = $pdo->prepare("SELECT * FROM mensajes WHERE usuario_id = :id AND id = :mensaje");
            $stmt->bindParam(':id', $id, PDO::PARAM_INT);
            $stmt->bindParam(':mensaje', $mensaje, PDO::PARAM_INT);
            $stmt->execute();
            $resultado = $stmt->fetchAll(PDO::FETCH_CLASS, "Mensaje");

            if ($resultado) {
                echo json_encode($resultado);
            }
            else {
                echo json_encode(array(
                    'error' => 'No existe el mensaje solicitado'
                ));
            }
        }
    }
});

$app->run();

Funcion curl:

<?php
/**
 * Realiza la conexion curl para comprobar si el token es valido en la api para el scope solicitado
 * $token - Token a comprobar
 * $scope - permisos para el usuario. Cada metodo de nuestra api va a tener su propio scope: en este caso los posibles valores son "usuarios", "usuario", "mensajes", "mensaje"
 */
function curlCheckToken($token_value, $scope = null) {

    $ch = curl_init();
    //Url al servidor Oauth
    curl_setopt($ch, CURLOPT_URL, "http://localhost/oauth-demo/response.php");
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, 'access_token=' . $token_value . '&scope=' . urlencode($scope));
    //Json response
    $raw_data = curl_exec($ch);
    curl_close($ch);

    $data = json_decode($raw_data);
    /**
     * Procesamos la respuesta de curlhttp://localhost/api-slimframework/listado/
     * Si en el array devuelto se encuentra la clave success con valor true es que hemos tenido exito
     * Si no, mostramos los errores que nos devuelve la api
     */
    if (isset($data->success) AND $data->success == true) {

        return true;
    }
    else {

        echo $raw_data;
    }
}

Clases usadas para formatear los datos que se extraigan:

<?php

class Usuarios {

    public $usuarios ;

    function __construct($usuarios = null) {
        $this->usuarios = $usuarios;
    }

}

class Usuario {

    public $id;
    public $nombre;

}

class Mensajes {

    public $mensajes ;

    function __construct($mensajes = null) {
        $this->mensajes = $mensajes;
    }

}

class Mensaje {

    public $id;
    public $texto;

}

Comprobación del token:

<?php

/**
 * En este fichero se chequea que el token y el scope, y duelve si es valido o no, y en caso de que no el porqué
 */
require 'vendor/autoload.php';

$dsn = 'mysql:host=localhost;dbname=bdname';
$username = "user";
$password = "password";

$storage = new OAuth2\Storage\Pdo(array(
    'dsn' => $dsn,
    'username' => $username,
    'password' => $password
));


$config = array();
$server = new OAuth2\Server($storage, $config);

$request = OAuth2\Request::createFromGlobals();
$response = new OAuth2\Response();

$scope = $_POST['scope'];

//Aquí es donde comprobamos si con los datos envíados tenemos acceso al recurso
if (!$server->verifyResourceRequest($request, $response, $scope)) {

  // En caso de error, se mostrará los detalles aquí
  $response->send();
  die;
}

//Respuesta en caso de éxito
echo json_encode(array('success' => true));

Como se puede ver, cada uno de los métodos básicamente comprueba mediante CURL que el token de acceso tiene permisos para cada scope, si todo va bien conecta a la base de datos y extrae la info requerida, en caso contrario lanzará un error con una descripción de porque ha fallado( Token expirado, Token sin permisos para ese método o no hay datos disponibles según sea el caso).

General Oauth 2 Slim Framework

 Previous Post

Usando Oauth 2 junto con Slim Framework para crear API segura: Parte 1

― 28 septiembre, 2015

Next Post 

Usando Doctrine 2 con Slim Framework y path personalizado en Composer

― 22 noviembre, 2015

malakana

Autor: malakana

Desarrollador web freelance, aprendedor

Deja un comentario Cancelar comentario

Autor

malakanaMalakanaDesarrollador web freelance, aprendedor

  • F
  • t
  • G
  • l

Temas

  • Doctrine 2 (1)
  • General (6)
  • Oauth 2 (2)
  • Slim Framework (3)
  • Zend Framework 2 (3)

Busca

Diego Domínguez Blog / ProgramadorMalaga.com