Ejemplos de Implementación
Esta sección contiene ejemplos prácticos de implementación del flujo de autenticación OAuth 2.0 en diferentes lenguajes y frameworks.
JavaScript (Frontend)
Ejemplo Completo
javascript
const CLIENT_ID = 'su_client_id';
const REDIRECT_URI = 'https://su-dominio.com.br/callback';
const LOGIN_BASE_URL = '{login-producao}';
const SECURITY_BASE_URL = '{security-producao}';
function generarState() {
return btoa(Math.random().toString()).substring(0, 16);
}
function iniciarLogin() {
const state = generarState();
sessionStorage.setItem('oauth_state', state);
const authUrl = `${LOGIN_BASE_URL}/authorize?response_type=code&scope=openid profile&client_id=${CLIENT_ID}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&state=${state}`;
window.location.href = authUrl;
}
async function intercambiarCodigoPorToken(code) {
const response = await fetch(`${SECURITY_BASE_URL}/api/token/v2`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
client_id: CLIENT_ID,
client_secret: 'su_client_secret',
code: code
})
});
if (!response.ok) {
throw new Error('Error al intercambiar código por tokens');
}
return await response.json();
}
function procesarCallback() {
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const error = urlParams.get('error');
const state = urlParams.get('state');
const storedState = sessionStorage.getItem('oauth_state');
if (error) {
console.error('Error en la autenticación:', error);
return;
}
if (state !== storedState) {
console.error('State no corresponde');
return;
}
if (code) {
intercambiarCodigoPorToken(code)
.then(tokens => {
console.log('Tokens recibidos:', tokens);
validarYUsarTokens(tokens);
})
.catch(error => {
console.error('Error:', error);
});
}
}Node.js (Backend)
Ejemplo con Express
javascript
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
const CLIENT_ID = 'su_client_id';
const CLIENT_SECRET = 'su_client_secret';
const REDIRECT_URI = 'https://su-dominio.com.br/callback';
const LOGIN_BASE_URL = '{login-producao}';
const SECURITY_BASE_URL = '{security-producao}';
app.get('/login', (req, res) => {
const state = require('crypto').randomBytes(16).toString('hex');
req.session.oauthState = state;
const authUrl = `${LOGIN_BASE_URL}/authorize?response_type=code&scope=openid profile&client_id=${CLIENT_ID}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&state=${state}`;
res.redirect(authUrl);
});
app.get('/callback', async (req, res) => {
const { code, error, state } = req.query;
if (error) {
return res.status(400).send(`Error: ${error}`);
}
if (state !== req.session.oauthState) {
return res.status(400).send('State inválido');
}
try {
const tokenResponse = await fetch(`${SECURITY_BASE_URL}/api/token/v2`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
code: code
})
});
const tokens = await tokenResponse.json();
const decoded = jwt.verify(tokens.id_token, CLIENT_SECRET, {
issuer: 'fanbase',
audience: CLIENT_ID
});
req.session.user = decoded;
res.redirect('/dashboard');
} catch (error) {
res.status(500).send(`Error: ${error.message}`);
}
});
app.get('/userinfo', async (req, res) => {
const accessToken = req.session.tokens?.access_token;
if (!accessToken) {
return res.status(401).send('No autenticado');
}
try {
const response = await fetch(`${SECURITY_BASE_URL}/api/userinfo`, {
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
const userInfo = await response.json();
res.json(userInfo);
} catch (error) {
res.status(500).send(`Error: ${error.message}`);
}
});Python
Ejemplo con Flask
python
from flask import Flask, redirect, request, session
import requests
import jwt
import secrets
app = Flask(__name__)
app.secret_key = 'su_clave_secreta'
CLIENT_ID = 'su_client_id'
CLIENT_SECRET = 'su_client_secret'
REDIRECT_URI = 'https://su-dominio.com.br/callback'
LOGIN_BASE_URL = '{login-producao}'
SECURITY_BASE_URL = '{security-producao}'
@app.route('/login')
def login():
state = secrets.token_urlsafe(16)
session['oauth_state'] = state
auth_url = f'{LOGIN_BASE_URL}/authorize?response_type=code&scope=openid profile&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&state={state}'
return redirect(auth_url)
@app.route('/callback')
def callback():
code = request.args.get('code')
error = request.args.get('error')
state = request.args.get('state')
if error:
return f'Error: {error}', 400
if state != session.get('oauth_state'):
return 'State inválido', 400
token_data = {
'grant_type': 'authorization_code',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'code': code
}
response = requests.post(
f'{SECURITY_BASE_URL}/api/token/v2',
data=token_data
)
tokens = response.json()
try:
decoded = jwt.decode(
tokens['id_token'],
CLIENT_SECRET,
issuer='fanbase',
audience=CLIENT_ID,
algorithms=['HS256']
)
session['user'] = decoded
session['tokens'] = tokens
return redirect('/dashboard')
except jwt.InvalidTokenError as e:
return f'Token inválido: {e}', 400
@app.route('/userinfo')
def userinfo():
access_token = session.get('tokens', {}).get('access_token')
if not access_token:
return 'No autenticado', 401
headers = {'Authorization': f'Bearer {access_token}'}
response = requests.get(f'{SECURITY_BASE_URL}/api/userinfo', headers=headers)
return response.json()PHP
Ejemplo Básico
php
<?php
session_start();
define('CLIENT_ID', 'su_client_id');
define('CLIENT_SECRET', 'su_client_secret');
define('REDIRECT_URI', 'https://su-dominio.com.br/callback');
define('LOGIN_BASE_URL', '{login-producao}');
define('SECURITY_BASE_URL', '{security-producao}');
function iniciarLogin() {
$state = bin2hex(random_bytes(16));
$_SESSION['oauth_state'] = $state;
$authUrl = LOGIN_BASE_URL . '/authorize?' . http_build_query([
'response_type' => 'code',
'scope' => 'openid profile',
'client_id' => CLIENT_ID,
'redirect_uri' => REDIRECT_URI,
'state' => $state
]);
header('Location: ' . $authUrl);
exit;
}
function procesarCallback() {
$code = $_GET['code'] ?? null;
$error = $_GET['error'] ?? null;
$state = $_GET['state'] ?? null;
if ($error) {
die('Error: ' . $error);
}
if ($state !== $_SESSION['oauth_state']) {
die('State inválido');
}
$ch = curl_init(SECURITY_BASE_URL . '/api/token/v2');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'grant_type' => 'authorization_code',
'client_id' => CLIENT_ID,
'client_secret' => CLIENT_SECRET,
'code' => $code
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$tokens = json_decode($response, true);
$_SESSION['tokens'] = $tokens;
return $tokens;
}
function obtenerUserInfo($accessToken) {
$ch = curl_init(SECURITY_BASE_URL . '/api/userinfo');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $accessToken
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
return json_decode($response, true);
}
?>Obtener Token con Client Credentials (Para Integraciones Connect)
JavaScript
javascript
async function obtenerTokenClientCredentials() {
const CLIENT_ID = 'su_client_id';
const CLIENT_SECRET = 'su_client_secret';
const SECURITY_BASE_URL = '{security-producao}';
const params = new URLSearchParams({
grant_type: 'client_credentials',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET
});
const response = await fetch(`${SECURITY_BASE_URL}/api/token?${params}`, {
method: 'POST'
});
if (!response.ok) {
throw new Error('Error al obtener token');
}
const data = await response.json();
return data.access_token;
}Node.js
javascript
async function obtenerTokenConnect() {
const CLIENT_ID = 'su_client_id';
const CLIENT_SECRET = 'su_client_secret';
const SECURITY_BASE_URL = '{security-producao}';
const params = new URLSearchParams({
grant_type: 'client_credentials',
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET
});
const response = await fetch(`${SECURITY_BASE_URL}/api/token?${params}`, {
method: 'POST'
});
const data = await response.json();
return data.access_token;
}Usar API Connect
Ejemplo: Crear Objeto en la Cola
javascript
async function crearObjetoCola(accessToken) {
const CONNECT_BASE_URL = '{connect-producao}';
const response = await fetch(`${CONNECT_BASE_URL}/api/v1/integration/queue`, {
method: 'POST',
headers: {
'AccessToken': accessToken,
'Content-Type': 'application/json'
},
body: JSON.stringify({
action: 'ticket-create',
data: {
datos_del_boleto: 'valor',
datos_del_comprador: 'valor'
}
})
});
if (!response.ok) {
throw new Error('Error al crear objeto en la cola');
}
return await response.json();
}Ejemplo: Obtener Perfil Completo
javascript
async function obtenerPerfil(clientId, jwtToken) {
const SECURITY_BASE_URL = '{security-producao}';
const response = await fetch(`${SECURITY_BASE_URL}/api/profile/${clientId}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${jwtToken}`
}
});
if (!response.ok) {
throw new Error('Error al obtener perfil');
}
const resultado = await response.json();
if (resultado.header.codigo !== 1) {
throw new Error(resultado.header.msg);
}
return resultado.data;
}