Está en la página 1de 20

Tutorial Paso a Paso

Las siguientes instrucciones proporcionan un tutorial detallado para ayudarlo a poner


en funcionamiento un Servidor OAuth2.

Para ver el código fuente del Servidor OAuth2 que implementa con esta biblioteca, consulte
la demostración de desde Git (https://github.com/bshaffer/oauth2-demo-php).

I) Índice
1) Requerimientos mínimos Pg. 002
2) Inicializando el proyecto Pg. 003
3) Configurando la base de datos Pg. 004
4) Conexión con el Servidor desde php Pg. 006
5) Generando Tokens Pg. 007
6) Validar los Tokens creados Pg. 011
7) Autenticar por intervención del usuario. Pg. 013
8) OpenID Conect Pg. 020

Página 1 de 20
1) Requerimientos mínimos para realizar el tutorial

Este tutorial se puede realizar desde un equipo con WAMP, XAMP y/o LAMP con las siguientes
características:

 Apache 2.4.43
 PHP 7.4.5
 MariaDB 10.4.11

Nota 1: De manera opcional se puede tener instalado Git y Composer.

2) Inicializar el Proyecto
Creamos la carpeta donde guardaremos el proyecto, podemos hacerlo de dos formas diferentes, nos
ubicamos en la carpeta donde podemos ver los proyectos desde localhost y creamos una nueva
carpeta donde posteriormente clonaremos el proyecto desde git, en este caso lo llamare tutorial.

Línea de comandos

mkdir tutorial

cd tutorial

git clone https://github.com/bshaffer/oauth2-server-php.git -b master

Modo visual

Ingresamos a https://github.com/bshaffer/oauth2-server-php,hacemos clic en Code y posteriormente


Download ZIP.

Página 2 de 20
Una vez descargado el archivo, nos dirigimos a la carpeta donde están los proyectos,
descomprimimos el archivo y renombramos la carpeta al nombre del nuevo proyecto.
(en este caso, tutorial).

Dependiendo del servidor, la ruta raíz se puede localizar en las siguientes por default.

Servidor Ruta

WAMP C:/wamp/www/

XAMP C:/xamppx/htdocs/

LAMP /var/www/html/

Página 3 de 20
3) Configurando la base de datos.
Para poder trabajar correctamente con el Servidor Oauth2 en php, es necesario crear las siguientes
tablas en la base de datos del proyecto, para este caso, el proyecto estará en una base de datos
llamada tutorial_db.

CREATE TABLE oauth_clients ( CREATE TABLE oauth_access_tokens (


client_id VARCHAR(80) NOT NULL, access_token VARCHAR(40) NOT NULL,
client_secret VARCHAR(80), client_id VARCHAR(80) NOT NULL,
redirect_uri VARCHAR(2000), user_id VARCHAR(80),
grant_types VARCHAR(80), expires TIMESTAMP NOT NULL,
scope VARCHAR(4000), scope VARCHAR(4000),
user_id VARCHAR(80), PRIMARY KEY (access_token)
PRIMARY KEY (client_id)
); );

CREATE TABLE oauth_authorization_codes ( CREATE TABLE oauth_refresh_tokens (


authorization_code VARCHAR(40) NOT NULL, refresh_token VARCHAR(40) NOT NULL,
client_id VARCHAR(80) NOT NULL, client_id VARCHAR(80) NOT NULL,
user_id VARCHAR(80), user_id VARCHAR(80),
redirect_uri VARCHAR(2000), expires TIMESTAMP NOT NULL,
expires TIMESTAMP NOT NULL, scope VARCHAR(4000),
scope VARCHAR(4000), PRIMARY KEY (refresh_token)
id_token VARCHAR(1000),
PRIMARY KEY (authorization_code)
); );

CREATE TABLE oauth_users ( CREATE TABLE oauth_scopes (


username VARCHAR(80), scope VARCHAR(80) NOT NULL,
password VARCHAR(80), is_default BOOLEAN,
first_name VARCHAR(80), PRIMARY KEY (scope)
last_name VARCHAR(80), );
email VARCHAR(80), CREATE TABLE oauth_jwt (
email_verified BOOLEAN, client_id VARCHAR(80) NOT NULL,
scope VARCHAR(4000), subject VARCHAR(80),
PRIMARY KEY (username) public_key VARCHAR(2000) NOT NULL
); );

Una vez importada la estructura a la base de datos, vamos a insertar un registro en oauth_clients
para que posteriormente podamos hacer una prueba de autenticación.

INSERT INTO oauth_clients (client_id, client_secret, redirect_uri) VALUES


("cliente_prueba", "clave_prueba", "http://localhost/prueba/redireccion.php");

Nota 2: Los equipos donde tienen instalado LAMP, por cuestiones de seguridad, suele estar
configurado para denegar el acceso al usuario 'root' con contraseña en blanco ' ' por tal razón,
se ejemplificarán las credenciales de acceso a la base de datos con el usuario 'Juanito' y la
contraseña 'clave-secreta-1234'.

Tip 1: Si se cuenta con la configuración previamente comentada, al intentar crear un usuario alterno
desde el PhpMyAdmin, (suponiendo que usan MariaDb o MySql ) podrán notar que solo les
permitirá crear usuarios con limitantes, para crear un usuario similar a root, deberán abrir una
terminal y seguir los siguientes pasos.

Página 4 de 20
Ejecutamos Mysql o MariaDb desde la terminal con el mismo comando (ingresar como root)

usuario@equipo:~# mysql –u root –p

una vez que salga el mensaje de bienvenida, procedemos a crear un usuario junto con su contraseña,
en este ejemplo serán los mismo que están indicados en la nota anterior.

CREATE USER 'Juanito'@'%' IDENTIFIED BY 'clave-secreta-1234';

Posteriormente a esto, le indicamos que queremos todos los permisos para el usuario que acabamos
de crear.

GRANT ALL PRIVILEGES ON *.* TO 'Juanito'@'%';

Por último, guardamos los cambios que acabamos de realizar.

FLUSH PRIVILEGES;

Con estos 3 comando, podemos crear rápidamente un usuario personalizado con privilegios de root.

Captura de pantalla desde el PhpMyAdmin donde se puede apreciar la base de datos con las tablas
creadas.

Página 5 de 20
4) Conexión con el Servidor desde php
Para este ejemplo, realizaremos la conexión a la base de datos desde un archivo de conexión en PHP
donde definiremos el Sistema Gestor de Base de Datos (SGBD), el nombre de la base de datos,
el servidor, su usuario y la contraseña, a este archivo lo llamaremos conexion.php

<?php
$dsn = 'mysql:dbname=tutorial_db;host=localhost';
$username = 'Juanito';
$password = 'clave-secreta-1234';

// Habilitamos el reporte de error, solo por ser una prueba//


ini_set('display_errors',1);error_reporting(E_ALL);

// Incluimos la ruta para que cargue el OAuth2//


require_once('oauth2-server-php/src/OAuth2/Autoloader.php');
OAuth2\Autoloader::register();

// $dsn Tiene los datos del nombre de la base de datos y el servidor//


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

// Creamos un nuevo objeto del tipo servidor OAuth2 y lo almacenamos.//


$server = new OAuth2\Server($storage);

// Agregamos las "Credenciales del cliente"//


$server->addGrantType(new OAuth2\GrantType\ClientCredentials($storage));

// Agregamos el "Código de Autorización" generado dinámicamente por Oauth2//


$server->addGrantType(new OAuth2\GrantType\AuthorizationCode($storage));
?>

Para que nuestra conexion.php esté funcionando, lo guardaremos dentro de la carpeta del
proyecto, a la altura de la carpeta oatuh2-server-php.

Página 6 de 20
5) Generando Tokens
Para el proceso de Autenticación, vamos a crear un token, el cual, le será de retorno al usuario que
realizo la petición con las credenciales (usuario y contraseña) y la ruta solicitada, para ello,
crearemos un archivo llamado token.php y tendrá el siguiente código.

<?php
// Incluimos el archivo de la conexión que creamos anteriormente//
require_once __DIR__.'/conexion.php';

// Manejamos la solicitud enviada a OAuth2 para generar un Token de Acceso//


// devolvemos la respuesta al cliente//
$server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send();
?>

Este archivo lo guardaremos a la misma altura que conexion.php

Con eso ya podemos generar los Tokens de Acceso a los usuarios autentificados, para verificarlo,
haremos uso del registro que insertamos en la pagina 4 de este documento, los datos son:

Usuario = cliente_prueba
Contraseña = clave_prueba

Con estos datos, usamos CURL desde la terminal, apuntando al URI donde se encuentra el token.php
esto lo realizaremos con el siguiente comando (tomando como datos los ejemplos)

curl -u cliente_prueba:clave_prueba http://localhost/tutorial/token.php -d


"grant_type=client_credentials"

Página 7 de 20
Tip 2 : En caso de estar en un sistema operativo de Windows, 1) Descargamos curl desde la página
oficial https://curl.haxx.se/windows/, elegimos el instalador correspondiente al tipo de arquitectura
que tiene el sistema (32 o 64 bits). 2) Descomprimimos el archivo comprimido. 3) Desde la terminal
nos ubicamos en la carpeta que se descomprimió y ejecutamos el comando.

Si todo salió bien, nos debe arrojar una respuesta similar con el mismo formato en Json.

{"access_token":"bba8f40fb4c1e64cba03f949e453ce89ae59189f","expires_in":3600,
"token_type":"Bearer","scope":null}

Si la credencial de acceso estuviera mal (pondré en la contraseña el valor 12345 para generar un
error de autentificación), nos mostraría el siguiente mensaje.

curl -u cliente_prueba:12345 http://localhost/tutorial/token.php -d


"grant_type=client_credentials"

Página 8 de 20
{"error":"invalid_client","error_description":"The client credentials are
invalid"}

Es importante indicar que, de manera interna, sucedió algo en la base de datos, se insertó un nuevo
registro en la tabla oauth_acces_token con el valor de nuestro token que se generó, un cliente_id
que corresponde a nuestro usuario (no es el id del usuario) y una fecha en que expira, como se
puede apreciar en la siguiente imagen.

Nota 3: URI significa Identificador de Recursos Uniforme es similar al Localizador Uniforme


de Recursos (URL) ya que el URL forma parte del URI como lo ilustra la siguiente imagen.

Página 9 de 20
Página 10 de 20
6) Validar los Tokens creados
Ahora que podemos crear tokens, es necesario que podamos gestionar los recursos con los tokens,
con la finalidad de permitir y/o denegar el acceso dependiendo del caso, ya que los tokens tienen
una fecha para expirar, esto lo definiremos con el siguiente archivo gestor.php que se encontrara a
la misma altura que el archivo token.php

<?php
// Incluimos el archivo de la conexión que creamos anteriormente//
require_once __DIR__.'/conexion.php';

// Verifica si el token es válido//


if (!$server->verifyResourceRequest(OAuth2\Request::createFromGlobals())) {
$server->getResponse()->send();
die;
}
// retornamos un Json con un estado de éxito verdadero y un mensaje //
echo json_encode(array('success' => true, 'message' => 'Tienes acceso a la API'));
?>

Para verificar que funciona, usaremos el token generado, desde la terminal usando curl, en este
caso 41826945adb2d0c87f2146b587c0c8070a0dee4f

curl http://localhost/tutorial/gestor.php -d
"access_token=41826945adb2d0c87f2146b587c0c8070a0dee4f"

En caso de tener un resultado favorable, en la terminal tendremos la siguiente respuesta.

Si el token ya hubiera expirado, nos arrojaría el siguiente mensaje

Página 11 de 20
"error": "invalid_token","error_description:":"The Access token provided has
expired"

Sin embargo, si el token fuera erróneo, nos arrojara el siguiente mensaje (para este caso, usare el
token con un valor de 1a2b3c4d5e6f

curl http://localhost/tutorial/gestor.php -d "access_token=41a2b3c4d5e6f"

"error":"invalid_token","error_description:":"The Access token provided is invalid"

Página 12 de 20
7) Autenticar por intervención del usuario.

OAuth2 permite a los usuarios el autorizar aplicaciones de terceros para la autenticación, la


diferencia radica en que emite un solo token una vez que el usuario ha autorizado la solicitud, esto
lo podremos realizar con el siguiente archivo llamado autorizar.php, este se encontrara en la misma
ubicación que los archivos previamente creados.

<?php
// Incluimos el archivo de la conexión que creamos anteriormente//
require_once __DIR__.'/conexion.php';

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

// Validamos la solicitud de autorizacion//


if (!$server->validateAuthorizeRequest($request, $response)) {
$response->send();
die;
}
// Mostramos un formulario de autorización
if (empty($_POST)) {
exit('
<form method="post">
<label>¿Quieres Autorizar al usuario?</label><br />
<input type="submit" name="authorized" value="Si">
<input type="submit" name="authorized" value="No">
</form>');
}

// Mostramos el codigo de autorización en caso de haberlo aceptado//


$is_authorized = ($_POST['authorized'] === 'Si');
$server->handleAuthorizeRequest($request, $response, $is_authorized);
if ($is_authorized) {
// Se realizara una redirección, mostramos el mesaje si el proceso fue exitoso//
$code = substr($response->getHttpHeader('Location'), strpos($response-
>getHttpHeader('Location'), 'code=')+5, 40);
exit("Proceso Exitoso! El codigo de autorización es: $code");
}
$response->send();
?>

Para poder ver el resultado, necesitamos ingresar desde el navegador a la siguiente ruta, pasando 3
parámetros por el método get
response_type = code
client_id = cliente_prueba
state = algo

http://localhost/tutorial/autorizar.php?response_type=code&client_id=cliente_prue
ba&state=xyz

Página 13 de 20
Si hacen click en el botón que dice "Si", el servidor insertara un nuevo registro en la tabla
oauth_authorization_codes con el valor de nuestro token, el cliente_id y una fecha de caducidad.

Sin embargo, si presionamos el botón de "No", redireccionaremos a la ruta que dejamos indicado
en nuestro primer registro que insertamos en la tabla oauth_clients.

Página 14 de 20
Como no tenemos ningún archivo con ese nombre, vamos a crear uno nuevo llamado
redirección.php, el código será el siguiente:

<?php
//Definimos una variable para mostrar un mensaje y un tipo de error//
$error = "";
$Mensaje = "Bienvenido, tu registro fue exitoso.";
// Verificamos si recibimos por get el parámetro "error"//
if (isset($_GET['error'])) {
// verificamos si tenemos un parámetro en "error_description //
if (isset($_GET['error_description'])) {
// Evaluamos el valor del mensaje //
if ($_GET['error_description'] == 'The user denied access to your
application'){
$Mensaje = "El usuario denegó el acceso a tu aplicación.";
}else{
$Mensaje = "No se autorizó el acceso por una razón desconocida.";
}
}else{
$Mensaje = "No se tiene información relacionada al error.";
}
// Evaluamos el valor del error //
if ($_GET['error'] == 'access_denied'){
$error = "Acceso denegado.";
}else{
$error = "¡Error!";
}
}
// Mostramos un mensaje y en caso de existir, un error. //
echo $error.'</br>'.$Mensaje;
?>

El archivo se ubicará junto a los archivos previamente codificados, como se muestra en la imagen.

Página 15 de 20
Una vez que hagamos clic en el botón No en la ruta que apunta al archivo Autorizar.php, nos
mostrara la siguiente pagina.

Si manualmente retiramos la variable error_description en la url, nos mostrara el siguiente mensaje

Página 16 de 20
Por ultimo, si se remueve el parámetro error, nos arrojara el siguiente resultado

Retomando el caso donde el usuario le dio clic al botón SI, el servidor nos retornó un token como
este: 7eb919701e22c1dc7e2c3f57f330d265a7bf8824, haciendo uso de la terminal, verificaremos si
nuestro token es valido desde el archivo token.php como lo hicimos previamente en la página 8,
con la diferencia que grant_type tendrá el valor asignado authorization_code e incluiremos el token

curl -u cliente_prueba:clave_prueba http://localhost/tutorial/token.php -d


"grant_type=authorization_code&code=7eb919701e22c1dc7e2c3f57f330d265a7bf8824"

Donde:
cliente_prueba es el usuario que tenemos registrado en la base de datos.
clave_prueba es la contraseña que tenemos registrado en la base de datos.
7eb919701e22c1dc7e2c3f57f330d265a7bf8824 es el token que le corresponde a nuestro usuario.

{"access_token":"6db6e6f1ec9aae1ed5ced422e706c62cc862ee06","expires_in":3600,"to
ken_type":"Bearer","scope":null,"refresh_token":"cf60c411a7c972fd033bcb29984af85
e0ccbd2cc"}

Página 17 de 20
¿Internamente que sucedió?

Si el token fue valido, el registro será eliminado de la tabla oauth_authorization_codes, además,


nos generara un nuevo registro en la tabla oauth_access_tokens, en este caso, la columna
access_token tendrá el valor 6db6e6f1ec9aae1ed5ced422e706c62cc862ee06, además, se insertará
un nuevo registro en la tabla oauth_refresh_tokens, donde la columna refresh_token guardará
el valor generado, para este caso f60c411a7c972fd033bcb29984af85e0ccbd2cc.

Si por alguna razón el token utilizado ya hubiera expirado, la respuesta que se obtendría seria la
siguiente:

Página 18 de 20
¿Qué sucede si intentamos usar el token que ya fue utilizado? Este sería el resultado

{"error":"invalid_grant","error_description":"Authorization code doesn't exist or


is invalid for the client"}

Página 19 de 20
8) OpenID Connect

Página 20 de 20

También podría gustarte