🎯 Banco de Preguntas — Semi-Senior
Preguntas técnicas reales para posiciones Semi-Senior Full Stack .NET + React.
A este nivel, el "por qué" es tan importante como el "qué". Siempre explica los trade-offs de tu respuesta.
C# Avanzado
❓ ¿Cuándo deberías usar ValueTask<T> en lugar de Task<T>?
A Cuando el método siempre realiza operaciones asíncronas reales (I/O, red)B Cuando el resultado puede estar disponible síncronamente sin allocations en el heapC Cuando necesitas hacer await múltiples veces sobre el mismo resultadoD Cuando trabajas con UI threads y el Dispatcher de WPF o MAUI
❓ ¿Qué constraint de generics debes usar para garantizar que T es una clase y tiene constructor sin parámetros?
A where T : structB where T : new()C where T : class, new()D where T : object, new()
❓ ¿Cuál es la diferencia principal entre record, class y struct en C# 9+?
A Los records se almacenan en el stack igual que los structs, por eso son más eficientesB Los records tienen igualdad por valor por defecto e inmutabilidad de propiedades init-only; class tiene igualdad por referenciaC Los records no pueden tener métodos de instancia, solo propiedadesD La única diferencia es sintáctica: record es un alias de class con menos código boilerplate
❓ ¿Qué ventaja ofrece el switch expression con pattern matching en C# 8+ frente a un switch statement clásico?
A El switch expression solo funciona con tipos primitivos como int, string y enumB Permite desestructurar objetos, combinar patrones y usarlo como expresión que devuelve un valor, todo de forma compactaC Es idéntico en rendimiento y capacidad al switch statement, solo es azúcar sintáctica cosméticaD Requiere que todos los casos devuelvan void, por lo que no puede usarse en asignaciones
Inyección de Dependencias
❓ ¿Cuál es el lifetime correcto para registrar un DbContext de Entity Framework en una API ASP.NET Core?
A Singleton — para reutilizar la misma conexión y aprovechar el connection poolingB Transient — para garantizar que cada operación tenga su propio contexto limpioC Scoped — un DbContext por request HTTP, que se libera al finalizar la peticiónD No importa, DbContext es thread-safe y cualquier lifetime funciona igual
❓ ¿Qué es una 'captive dependency' (dependencia cautiva) en el contenedor de DI?
A Una dependencia que no puede ser reemplazada por un mock en tests unitariosB Cuando un servicio Singleton captura una dependencia Scoped o Transient, extendiendo artificialmente su vida útilC Una dependencia circular entre dos servicios que se referencian mutuamenteD Un servicio que solo puede inyectarse en controllers, no en middleware
❓ ¿Cómo implementar el patrón Decorator para INotificationService usando el DI nativo de .NET sin librerías externas?
A Crear una nueva interfaz INotificationServiceDecorator que herede de INotificationServiceB Usar services.AddScoped<INotificationService>(sp => new LoggingDecorator(sp.GetRequiredService<EmailNotificationService>()))C Registrar ambas clases como Singleton y resolver manualmente en el constructor del decoratorD El DI nativo de .NET no soporta el patrón Decorator; es obligatorio usar Scrutor o Autofac
ASP.NET Core
❓ ¿En qué orden deben configurarse UseAuthentication y UseAuthorization en el pipeline de ASP.NET Core?
A app.UseAuthorization() debe ir antes de app.UseAuthentication()B app.UseAuthentication() debe ir antes de app.UseAuthorization()C Pueden configurarse en cualquier orden; ASP.NET Core los reordena automáticamenteD Solo se necesita app.UseAuthorization(); la autenticación es implícita con JWT
❓ ¿Cuándo deberías usar un IActionFilter en lugar de middleware en ASP.NET Core?
A Cuando necesitas lógica que aplique a toda la aplicación, incluyendo archivos estáticos y health checksB Cuando la lógica es específica de MVC/controllers y necesitas acceso al ActionContext, ModelState o ActionArgumentsC Los action filters siempre tienen mejor rendimiento que el middleware, por lo que son siempre preferiblesD Para validar y renovar tokens JWT en cada request antes de llegar al controlador
❓ Para el endpoint [HttpPut("{id}")] public IActionResult Update(int id, UpdateDto dto), ¿de dónde infiere ASP.NET Core cada parámetro?
A Ambos parámetros (id y dto) se leen del cuerpo del request (body)B id se lee del body porque es primitivo; dto se lee del query string porque es complejoC id se lee de la ruta (route) y dto se infiere como [FromBody] por ser un tipo complejoD Ambos parámetros se leen del query string si no se especifican atributos explícitos
❓ ¿Cuál es una ventaja real y documentada de Minimal APIs sobre Controllers en .NET 6+?
A Las Minimal APIs soportan más verbos HTTP que los controllers (PATCH, OPTIONS, etc.)B Tienen menor overhead en startup y menor allocations por request, siendo ideales para microservicios de alto rendimientoC Las Minimal APIs generan documentación Swagger completa de forma automática sin ninguna configuración adicionalD Solo las Minimal APIs soportan async/await; los controllers de MVC son siempre síncronos
Entity Framework Core
❓ Tienes este código: var posts = context.Posts.ToList(); foreach (var post in posts) { var count = context.Comments.Count(c => c.PostId == post.Id); } ¿Qué problema tiene y cómo solucionarlo?
A No hay problema; EF Core cachea los resultados de queries repetidas automáticamenteB Problema N+1: ejecuta 1 query para Posts y N queries para Comments. Solución: usar Include(p => p.Comments) en la query originalC El problema es que ToList() carga todo en memoria; debería usarse AsQueryable() siempreD El problema es usar Count() en lugar de Any(); Count() carga todas las entidades relacionadas
❓ ¿Cuándo es correcto y beneficioso usar .AsNoTracking() en Entity Framework Core?
A Siempre, en todas las queries, para maximizar el rendimiento de la aplicaciónB Solo en operaciones de escritura (INSERT, UPDATE, DELETE) para evitar conflictosC En queries de solo lectura donde no vas a modificar las entidades devueltas en el mismo contextoD Cuando usas transacciones explícitas con BeginTransactionAsync()
❓ ¿Cómo se revierte la base de datos a una migración anterior llamada 'AddProductsTable' en EF Core?
A dotnet ef migrations removeB dotnet ef database update AddProductsTableC dotnet ef migrations rollback AddProductsTableD dotnet ef database reset --to AddProductsTable
❓ ¿Cómo envuelves múltiples operaciones de EF Core en una transacción explícita para garantizar atomicidad?
A Llamar a SaveChanges() al final es suficiente; siempre envuelve todas las operaciones en una transacción automáticaB Usar el atributo [Transactional] sobre el método del servicioC using var transaction = await context.Database.BeginTransactionAsync(), ejecutar operaciones, llamar a SaveChangesAsync() y luego transaction.CommitAsync()D EF Core no soporta transacciones explícitas; debes usar ADO.NET directamente para ese caso
APIs REST
❓ ¿Cuál de estos verbos HTTP NO es idempotente según la especificación RFC 7231?
❓ ¿Cuál estrategia de versionado de API REST es generalmente más recomendada para APIs públicas?
A Header-based versioning: Accept: application/vnd.myapi.v1+jsonB Query string versioning: GET /products?api-version=1.0C URL path versioning: GET /api/v1/productsD No versionar; usar siempre backward compatibility con campos opcionales
❓ Un usuario autenticado intenta acceder a un recurso que pertenece a otro usuario. ¿Qué código HTTP debe devolver tu API?
A 401 Unauthorized — el usuario no tiene autorización para ese recursoB 404 Not Found — para no revelar la existencia del recurso a usuarios no autorizadosC 403 Forbidden — el servidor entendió el request pero se niega a cumplirloD 400 Bad Request — el request está malformado porque el userId no corresponde
❓ ¿Cuál es la principal ventaja de cursor-based pagination sobre offset-based pagination en una API con datos que cambian frecuentemente?
A Es más simple de implementar en el backend porque no requiere conocer el total de registrosB Evita registros duplicados o saltados cuando se insertan/eliminan datos entre páginasC Permite al cliente saltar directamente a cualquier página arbitraria (ej: ir a la página 50)D Consume menos ancho de banda porque el cursor es más pequeño que el offset numérico
Patrones de Diseño
❓ ¿Cuál es el propósito principal del Repository Pattern en una arquitectura de software?
A Mejorar automáticamente el rendimiento de las queries mediante caché transparenteB Abstraer el mecanismo de acceso a datos para que la lógica de negocio no dependa del ORM o base de datos específicaC Reemplazar Entity Framework con queries SQL puras para mayor controlD Implementar el patrón Unit of Work y gestionar las transacciones de base de datos
❓ ¿Cuál de estas clases viola el Principio de Responsabilidad Única (SRP) de SOLID?
A UserRepository con métodos GetById, GetAll, Add, Update, Delete para la entidad UserB UserService que valida los datos del usuario, lo persiste en la BD y envía el email de bienvenidaC EmailService que solo tiene métodos para enviar diferentes tipos de emailsD UserValidator que solo contiene reglas de validación para la entidad User
❓ ¿Cuándo el patrón Strategy es claramente preferible a una cadena de if/else o switch?
A Cuando solo hay 2-3 condiciones simples que raramente cambianB Cuando los algoritmos o comportamientos varían en tiempo de ejecución, se agregan frecuentemente o necesitan ser testeados de forma independienteC Strategy siempre es superior a if/else porque es más orientado a objetosD Cuando las condiciones no dependen de parámetros externos o del estado del sistema
❓ ¿Qué problema arquitectónico resuelve principalmente MediatR en aplicaciones .NET?
A Reemplaza el sistema de inyección de dependencias nativo con uno más potenteB Implementa el patrón Mediator desacoplando los handlers de sus invocadores, lo que facilita CQRS y cross-cutting concernsC Proporciona caché automático para queries a base de datos mediante pipelinesD Genera automáticamente endpoints REST a partir de la definición de Commands y Queries
Testing
❓ ¿Cuál es la definición correcta de un test de integración en el contexto de .NET?
A Prueba una sola función o método de forma aislada usando mocks para todas las dependencias externasB Prueba la interacción entre múltiples componentes reales, como un controller con EF Core conectado a una base de datos real o en memoriaC Prueba flujos completos del usuario a través de la interfaz gráfica usando herramientas como Selenium o PlaywrightD Prueba el rendimiento y la capacidad de carga del sistema bajo condiciones de estrés
❓ En un unit test de OrderService que depende de IOrderRepository y IEmailService, ¿qué debes mockear?
A Solo IEmailService, porque las operaciones de base de datos son rápidas y no afectan el aislamientoB Nada; los unit tests deben usar implementaciones reales para ser más confiablesC Ambos: IOrderRepository e IEmailService, para aislar completamente OrderService y probar solo su lógicaD Solo IOrderRepository; el EmailService puede usar una implementación real de pruebas en memoria
❓ ¿Cuál es el orden correcto del ciclo Red-Green-Refactor en TDD?
A Verde (hacer pasar el test) → Rojo (escribir test que falla) → Refactor (mejorar el código)B Rojo (escribir test que falla) → Verde (escribir código mínimo para pasarlo) → Refactor (limpiar sin romper tests)C Refactor (diseñar la solución) → Rojo (escribir el test) → Verde (implementar)D Verde (escribir el código) → Rojo (escribir el test) → Refactor (optimizar)
❓ ¿Cuál es la forma recomendada de hacer integration testing de endpoints HTTP en ASP.NET Core?
A Instanciar el Controller directamente en el test e invocar los métodos de acciónB Usar WebApplicationFactory<Program> para arrancar la app en memoria y hacer requests con HttpClient realC Mockear todos los middlewares y llamar directamente al método del controller sin pasar por el pipelineD Crear una colección de Postman y ejecutarla con newman como parte del CI/CD
React Avanzado
❓ ¿Cuál es la diferencia fundamental entre useCallback y useMemo en React?
A useCallback es para componentes de clase, useMemo es exclusivo de functional componentsB useCallback memoiza una función (retorna la misma referencia entre renders), useMemo memoiza el resultado de ejecutar un cálculoC Son equivalentes en comportamiento; solo difieren en que useMemo acepta dependencias y useCallback noD useMemo es para efectos secundarios asincrónicos, useCallback es para funciones síncronas puras
❓ ¿Cuándo deberías preferir useReducer sobre useState en un componente React?
A Siempre que el estado sea un objeto con más de dos propiedadesB Cuando la lógica de actualización es compleja, hay múltiples sub-valores interdependientes o las transiciones de estado deben ser explícitas y testeablesC useReducer solo tiene sentido cuando se combina con Context API para estado globalD Cuando necesitas estados asincrónicos; useState no soporta actualizaciones asíncronas
❓ ¿Qué problema de rendimiento puede causar el uso incorrecto de Context API en React?
A Memory leaks permanentes porque los contextos nunca liberan las referencias a sus consumidoresB Re-renders innecesarios en TODOS los componentes consumidores cuando cualquier parte del valor del contexto cambiaC El contexto solo puede actualizarse una vez por ciclo de render, perdiendo actualizaciones intermediasD Context API no es compatible con TypeScript, lo que obliga a usar casting de tipos que empeora el rendimiento
❓ ¿Qué ventaja concreta ofrece React Query sobre el patrón useState + useEffect para fetching de datos?
A React Query usa Web Workers automáticamente para no bloquear el main thread durante las peticionesB Maneja automáticamente caché, deduplicación de requests, estados de loading/error, refetching en foco y sincronización de datos en backgroundC Solo React Query permite hacer peticiones POST, PUT y DELETE; useEffect solo soporta GETD React Query elimina la necesidad de async/await usando un sistema de callbacks más eficiente
SQL Avanzado
❓ ¿Qué devuelve exactamente ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC)?
A El número total de empleados en cada departamento (COUNT por partición)B Un número secuencial para cada fila dentro de cada departamento, reiniciando en 1 para cada departamento y ordenado por salario descendenteC El rango del salario de cada empleado comparado con el promedio de su departamentoD Elimina filas duplicadas dentro de cada departamento manteniendo solo la de mayor salario
❓ ¿Cuándo son preferibles las CTEs (WITH clause) sobre subqueries en SQL?
A Siempre; las CTEs son compiladas y cacheadas por el motor SQL, lo que las hace siempre más rápidasB Cuando necesitas referenciar el mismo resultado intermedio múltiples veces, o para mejorar la legibilidad de queries complejas con múltiples pasos lógicosC Solo cuando la subquery devuelve más de 1000 filas; para resultados pequeños las subqueries son más eficientesD Las CTEs no pueden usarse con JOINs, por lo que solo son útiles en queries simples
❓ Para la query: SELECT * FROM orders WHERE status = 'active' AND created_date > '2024-01-01' ORDER BY user_id, ¿qué estrategia de índice es más óptima?
A Tres índices separados: uno en status, uno en created_date y uno en user_idB Un índice compuesto en (status, created_date, user_id) en ese orden específicoC Solo un índice en status, ya que es la columna con mayor selectividad en este casoD Los índices no ayudan con cláusulas ORDER BY; solo aceleran WHERE
Docker
❓ ¿Cuál es el beneficio principal de un multi-stage build en un Dockerfile para una app .NET?
A Permite ejecutar múltiples contenedores en paralelo dentro de un único docker runB Reduce drásticamente el tamaño de la imagen final al separar el entorno de compilación (SDK) del entorno de ejecución (runtime)C Mejora la velocidad de ejecución de la aplicación porque el código se precompila en la fase de buildD Permite usar diferentes sistemas operativos base (Windows y Linux) en la misma imagen Docker
❓ ¿Cuál es la diferencia práctica entre COPY y ADD en un Dockerfile, y cuál deberías preferir?
A COPY es para archivos locales del build context; ADD es exclusivamente para descargar desde URLs remotasB ADD puede descomprimir archivos .tar.gz automáticamente y descargar URLs remotas; COPY solo copia archivos locales. Se prefiere COPY por ser más explícito y predecibleC COPY es más lento que ADD en todos los escenarios porque no usa compresión internaD No hay diferencia funcional; ADD es simplemente el nombre antiguo de COPY en versiones anteriores de Docker
❓ ¿Cuál es la diferencia conceptual entre una imagen Docker y un contenedor Docker?
A Una imagen es un contenedor detenido; un contenedor es una imagen que está actualmente en ejecuciónB Una imagen es una plantilla inmutable de solo lectura con el sistema de archivos y configuración; un contenedor es una instancia en ejecución de esa imagen con su propia capa de escrituraC Las imágenes siempre se almacenan en Docker Hub; los contenedores son siempre locales y nunca se pueden compartirD Un contenedor puede convertirse en imagen únicamente mediante el comando docker export seguido de docker import
TypeScript Avanzado
❓ ¿Cuál es la diferencia entre Partial<T> y Required<T> en TypeScript y cuándo usar cada uno?
A Partial<T> elimina propiedades del tipo T; Required<T> añade propiedades nuevas al tipoB Partial<T> hace todas las propiedades opcionales (agrega ?); Required<T> hace todas las propiedades obligatorias (quita ?). Se usan para actualización parcial y validación respectivamenteC Son equivalentes: ambos generan el mismo tipo, solo cambia el nombre por convenciónD Partial<T> solo funciona con interfaces; Required<T> solo funciona con type aliases
❓ ¿Qué hace Pick<T, K> vs Omit<T, K> en TypeScript?
A Pick<T, K> crea un tipo con SOLO las propiedades listadas en K; Omit<T, K> crea un tipo con TODAS las propiedades EXCEPTO las de KB Pick<T, K> es para interfaces y Omit<T, K> es para clases; no pueden usarse indistintamenteC Pick<T, K> elimina propiedades en runtime del objeto; Omit<T, K> las deja en runtime pero las oculta al compiladorD Pick y Omit son idénticos, la diferencia es solo de legibilidad según cuántas propiedades quieras incluir o excluir
❓ ¿Qué son los Mapped Types en TypeScript y para qué sirven?
A Son una forma de iterar arrays de objetos en TypeScript de manera tipada, similar a Array.map pero con type safetyB Son una sintaxis que permite transformar cada propiedad de un tipo existente aplicando modificadores, creando nuevos tipos derivadosC Son decoradores de clase que mapean propiedades del constructor a columnas de una base de datosD Son aliases de tipos primitivos que se mapean a tipos de JavaScript en tiempo de ejecución
❓ ¿Cuándo deberías preferir interface sobre type en TypeScript, considerando declaration merging y extensión?
A Siempre debes usar type; interface está deprecada en TypeScript moderno y se mantendrá solo por compatibilidadB interface permite declaration merging (fusión de declaraciones) y se extiende con extends; type usa intersección con & y no puede redeclararse. Prefiere interface para contratos de objetos y APIs públicasC type es más rápido en compilación para proyectos grandes; interface solo debe usarse cuando interoperas con librerías JavaScript antiguasD La única diferencia real es que type puede definir primitivos y uniones; para objetos son completamente intercambiables sin ninguna diferencia práctica
❓ ¿Qué es el Code Splitting y cómo se implementa en React con React.lazy?
A Code Splitting divide el código CSS en múltiples archivos para cargar estilos bajo demanda según la ruta activaB Code Splitting divide el bundle de JavaScript en chunks que se cargan bajo demanda. React.lazy con Suspense carga componentes solo cuando se necesitan, reduciendo el bundle inicialC Es una técnica para dividir componentes grandes en componentes más pequeños con el fin de mejorar la legibilidad del códigoD Code Splitting es exclusivo de Next.js y no está disponible en aplicaciones React con Create React App o Vite
❓ ¿Cuál es la diferencia entre useMemo y useCallback en React?
A useMemo memoiza el resultado de una función; useCallback memoiza la referencia de la función misma. Son equivalentes y se pueden usar indistintamenteB useMemo memoiza el valor retornado por una función costosa; useCallback memoiza la definición de la función para evitar que se recree en cada renderC useMemo es para valores primitivos y useCallback es para objetos y arrays; no funcionan con el tipo equivocadoD useCallback reemplaza completamente a useMemo y es más moderno; useMemo existe solo por retrocompatibilidad
❓ ¿Qué es el LCP (Largest Contentful Paint) y cuáles son las técnicas más efectivas para mejorarlo?
A LCP mide el tiempo total hasta que la página es completamente interactiva; se mejora reduciendo el JavaScript del bundleB LCP mide cuándo el elemento de contenido más grande (imagen o bloque de texto) es visible en pantalla. Se mejora optimizando imágenes, usando CDN y precargando recursos críticosC LCP es una métrica de accesibilidad que mide si el texto principal es legible; no tiene relación con la velocidad de cargaD LCP solo se aplica a imágenes; si tu página no tiene imágenes grandes, esta métrica no te afecta
❓ ¿Por qué import _ from 'lodash' puede ser problemático para el bundle size y cómo solucionarlo?
A Lodash está deprecada y genera warnings en el bundle; debes reemplazarla con underscore.js que es más modernaB Importar el módulo completo de lodash incluye todas sus funciones (~70KB minificado+gzip) aunque solo uses una. La solución es importar funciones específicas o usar lodash-es con tree-shakingC El problema es que lodash usa CommonJS y los bundlers modernos solo entienden ES Modules; hay que configurar un alias especialD Lodash tiene muchas dependencias transitivas que aumentan el bundle; la solución es instalar cada dependencia manualmente
Caché y Redis
❓ ¿Cuál es la diferencia entre Cache-Aside y Write-Through como estrategias de caché?
A Cache-Aside es para lecturas y Write-Through es para escrituras; se deben usar juntos obligatoriamente en cualquier sistemaB Cache-Aside: la aplicación gestiona el caché manualmente (lee caché, si falla lee BD y actualiza caché); Write-Through: cada escritura en caché se propaga automáticamente a la BD de forma sincrónicaC Write-Through es más rápido en lectura porque siempre tiene los datos actualizados; Cache-Aside es más rápido en escritura porque no persiste en BDD Cache-Aside requiere Redis como backend; Write-Through solo funciona con cachés en memoria como IMemoryCache
❓ ¿Cuándo deberías usar IMemoryCache vs IDistributedCache en .NET?
A IMemoryCache es para datos pequeños (menos de 1MB); IDistributedCache es para datos más grandes sin importar la arquitecturaB IMemoryCache almacena datos en RAM del proceso actual (una sola instancia); IDistributedCache usa un almacén externo (Redis, SQL Server) compartido entre múltiples instanciasC IDistributedCache siempre es preferible porque es más rápido al usar serialización binaria optimizada frente a IMemoryCacheD Son intercambiables: IDistributedCache es simplemente la versión actualizada de IMemoryCache en .NET 6+
❓ ¿Para qué sirve el TTL (Time To Live) en Redis y qué problemas puede causar no configurarlo?
A TTL controla la velocidad máxima de transferencia de datos entre Redis y la aplicación; sin él, Redis puede saturarseB TTL define el tiempo de expiración de una clave: tras ese tiempo Redis la elimina automáticamente. Sin TTL, las claves persisten indefinidamente y la memoria de Redis puede llenarse hasta causar OOMC TTL es opcional y solo relevante para datos de sesión; para otros tipos de datos no tiene impacto porque Redis comprime datos automáticamenteD Sin TTL las claves se replican a más nodos de Redis, aumentando la disponibilidad pero también el uso de red
❓ ¿Qué es el cache stampede (thundering herd) y cómo se mitiga?
A Es cuando Redis recibe demasiadas conexiones simultáneas y colapsa; se mitiga aumentando el número de réplicas de lecturaB Es cuando una clave expira y múltiples requests simultáneos detectan el cache miss, van todos a la BD al mismo tiempo y la sobrecargan. Se mitiga con locking o probabilistic early expirationC Es un ataque de seguridad donde un cliente externo invalida masivamente el caché; se mitiga con autenticación en RedisD Es la degradación del rendimiento cuando el caché está lleno; se mitiga aumentando la RAM asignada a Redis
Autenticación Avanzada
❓ ¿Cuál es la diferencia entre OAuth 2.0 y OpenID Connect (OIDC)?
A OAuth 2.0 es más moderno y reemplaza a OIDC; son incompatibles entre sí y no deben usarse en el mismo sistemaB OAuth 2.0 es un protocolo de autorización (delegar acceso a recursos); OIDC es una capa de identidad sobre OAuth 2.0 que añade autenticación e información del usuario mediante el ID TokenC OAuth 2.0 usa tokens JWT y OIDC usa tokens opacos; la diferencia es exclusivamente el formato del tokenD Son idénticos en funcionalidad; OIDC es simplemente el nombre que usa Google y OAuth 2.0 es el nombre que usa Microsoft para el mismo protocolo
❓ ¿Por qué se recomienda el flujo PKCE para SPAs en lugar del flujo implícito (Implicit Flow) de OAuth 2.0?
A PKCE es más fácil de implementar que el flujo implícito; la seguridad es equivalente pero PKCE requiere menos códigoB El flujo implícito expone el Access Token en la URL (fragment), lo que lo hace vulnerable a robo via historial del navegador o referrer headers. PKCE usa un code verifier/challenge que solo el cliente legítimo puede completarC El flujo implícito está deprecado solo en aplicaciones móviles; para SPAs en navegador sigue siendo la opción recomendada por la especificaciónD PKCE requiere que el servidor de autorización soporte HTTPS; el flujo implícito funciona también en HTTP, por eso se prefería en desarrollo local
❓ ¿Qué es el Refresh Token Rotation y por qué mejora la seguridad frente a refresh tokens estáticos?
A Refresh Token Rotation significa que los refresh tokens se renuevan periódicamente de forma automática sin intervención del usuario, similar a una sesión con sliding expirationB Cada vez que se usa un refresh token para obtener un nuevo access token, el servidor emite un NUEVO refresh token e invalida el anterior. Si el token robado se usa, el servidor detecta la reutilización e invalida toda la sesiónC Es una técnica para rotar entre múltiples servidores de autenticación para mejorar la disponibilidad; no está relacionada con la seguridad de los tokensD Refresh Token Rotation requiere que el usuario inicie sesión de nuevo cada vez que el access token expira; es más seguro pero peor en experiencia de usuario