Explica paso a paso el flujo de authorization code de OAuth2 con PKCE
Los clientes públicos como las SPA y las apps móviles no pueden guardar un secreto, así que PKCE ata el inicio del flujo con su final.
APRENDE HACIENDOPon a prueba tu intuición3 pasos
Explica paso a paso el flujo de authorization code de OAuth2 con PKCE
Usa los ejemplos y la explicación de la lección para comprobar tu idea.
Reflexión personal. No se envía a ningún servicio de IA.#Por qué existe PKCE
El flujo de authorization code de OAuth2 se diseñó originalmente asumiendo un cliente confidencial — una aplicación del lado del servidor que puede guardar un client_secret de forma segura, lejos de los usuarios finales. Las aplicaciones de una sola página (SPA), las apps móviles y las aplicaciones nativas de escritorio no pueden asumir eso: cualquier cosa que se envíe al cliente puede extraerse de él, así que un secreto embebido no ofrece ninguna protección real. Peor aún, en plataformas nativas la redirección de vuelta a la app tras el login suele pasar por un esquema de URI personalizado (myapp://callback) o un universal link, y más de una app en el mismo dispositivo a veces puede registrar el mismo esquema — abriendo una ventana para que una app maliciosa intercepte el código de autorización destinado a la legítima.
PKCE — Proof Key for Code Exchange, RFC 7636, que se pronuncia "pixy" — cierra esa brecha sin necesitar ningún secreto compartido. Ata la petición que inicia el flujo con la petición que lo termina, de modo que incluso si un atacante intercepta el código de autorización en tránsito, no puede canjearlo por un token.
#Las piezas en juego
- code_verifier — una cadena aleatoria de alta entropía que el propio cliente genera, se mantiene solo en memoria o en el almacenamiento de sesión, y nunca se transmite hasta el último paso.
- code_challenge —
BASE64URL(SHA256(code_verifier)), enviado por adelantado en la petición de autorización. Como SHA-256 es de un solo sentido, tener el challenge no permite a nadie recuperar el verifier. - code_challenge_method —
S256en toda implementación moderna; el métodoplain(enviar el propio verifier como challenge) existe solo por compatibilidad histórica y no ofrece ninguna protección real.
#Paso a paso
- El cliente genera un
code_verifiery derivacode_challenge = BASE64URL(SHA256(code_verifier)). - El cliente redirige el navegador del usuario al endpoint
/authorizedel servidor de autorización, incluyendoclient_id,redirect_uri,response_type=code,scope, un valorstatealeatorio,code_challenge, ycode_challenge_method=S256. - El servidor de autorización autentica al propietario del recurso — una pantalla de login, posiblemente MFA — y pide consentimiento para los scopes solicitados.
- Al aprobar, el servidor de autorización redirige de vuelta a
redirect_uricon uncodede vida corta y el mismostateoriginal repetido. - El cliente verifica que el
statedevuelto coincida con el que envió en el paso 2 (esta es la defensa CSRF — una preocupación separada de PKCE), y luego hace un POST directo, por canal trasero, al endpoint/tokencongrant_type=authorization_code,code,redirect_uri,client_id, y — de forma crítica — elcode_verifieren crudo. - El servidor de autorización recalcula
SHA256(code_verifier)y lo compara contra elcode_challengeque guardó cuando emitió el código. Si no coinciden, significa que quien canjea el código no es quien inició el flujo, y se rechaza la petición. - Si coinciden, el servidor de autorización emite un
access_token(y típicamente unrefresh_token, más unid_tokensi se trata de OpenID Connect). - El cliente llama al servidor de recursos con
Authorization: Bearer <access_token>. - El servidor de recursos valida el token — verificando la firma y los claims si es un JWT, o llamando a un endpoint de introspección si es opaco — y sirve el recurso protegido.
#Por qué la interceptación sigue fallando
| Flujo | Tipo de cliente | Secreto requerido | Estado |
|---|---|---|---|
| Authorization code (clasico) | Confidencial (servidor) | client_secret | Sigue siendo valido para clientes confidenciales |
| Authorization code + PKCE | Publico (SPA, movil, nativo) | Ninguno — en su lugar, code_verifier | Recomendado para todo tipo de cliente |
| Implicit | Publico, historicamente | Ninguno | Obsoleto — evitar en trabajo nuevo |
🧠 Check your understanding
0/3 · 0/3 answered1. ¿Qué problema resuelve PKCE que el flujo clásico de authorization code de OAuth2 no resuelve, para clientes públicos como SPAs y apps móviles?
2. En el flujo PKCE, ¿cuándo se envía el code_verifier en sí al servidor de autorización?
3. ¿Contra qué protege el parámetro state que PKCE no protege?