TI Capacitación
TI Capacitación
TI Capacitación
Introducción a OAuth 2 y OpenID Connect en ASP.NET Core
Acerca del entrenamiento

OAuth 2.0, OpenID Connect y JSON Web Tokens son tecnologías que surgen por la necesidad de poder acceder a recursos protegidos (APIs) en nombre de un usuario. En la actualidad, cada vez son más los servicios que soportan OAuth 2.0 como protocolo de autorización, entre estos servicios podemos mencionar a Google, Facebook, Twitter, Github o Azure Active Directory.

Típicamente, cuando trabajamos con estas tecnologías, implicamos 5 roles:

  • El recurso protegido, tradicionalmente una API.
  • El servidor web que hospeda el recurso protegido.
  • El dueño del recurso, típicamente un usuario, pero también puede ser una aplicación.
  • El servidor de autorización encargado de autenticar y autorizar el acceso al recurso.
  • El Cliente (aplicación) que desea acceder al recurso.

A lo largo de las lecciones de este entrenamiento, presentaremos una introducción a OAuth 2.0, OpenID Connect y JSON Web Tokens, así como la forma de implementar soluciones basadas en estos estándares utilizando ASP.NET Core.

Para entender los distintos flujos de autorización de OAuth 2.0, en la primera parte de este entrenamiento, nos enfocaremos en conocer a detalle la forma en que trabajan estas tecnologías y para ello utilizaremos los siguientes perfiles:

  • El recurso protegido. La API que permite el acceso al perfil de usuario.
  • El servidor web que hospeda el recurso protegido: Microsoft Graph API.
  • El dueño del recurso. El usuario.
  • El Servidor de Autorización. Azure Active Directory.
  • El Cliente. Utilizaremos varios clientes incluyendo ASP.NET Core MVC, Blazor WebAssembly y aplicaciones de Consola para simular dispositivos IoT.

En la segunda parte de este entrenamiento, presentaremos una introducción a IdentityServer4, un framework para ASP.NET Core que se adhiere a las especificaciones de OAuth 2.0 y OpenID Connect.

Utilizaremos IdentityServer4 para implementar un servidor de Inicio de Sesión Único (Single Sign-On) para centralizar el proceso de autenticación y autorización de usuarios y aplicaciones. Los usuarios podrán iniciar sesión utilizando cuentas de usuario en bases de datos locales o bien utilizando sus cuentas de usuario de proveedores externos como Google, Facebook, Microsoft o Twitter.

Objetivos

Al finalizar este entrenamiento, los participantes contarán con las habilidades y conocimientos para:

  • Describir qué es OAuth 2.0.
  • Describir qué es OpenID Connect.
  • Describir qué es JSON Web Tokens.
  • Desarrollar aplicaciones implementando el flujo de autorización Code.
  • Desarrollar aplicaciones implementando el flujo de autorización Implicit.
  • Desarrollar aplicaciones Blazor WebAssembly implementando el flujo de autorización Implicit con Refresh Tokens.
  • Desarrollar aplicaciones implementando el flujo de autorización Client Credentials.
  • Desarrollar aplicaciones implementando el flujo de autorización Resource Owner Password Credentials (ROPC) .
  • Desarrollar aplicaciones implementando el flujo de autorización Device Code.
  • Desarrollar aplicaciones implementando el flujo de autorización Code y PKCE para evitar ataques de interceptación del código.
  • Proteger una API utilizando el flujo Client Credentials e IdentityServer4.
  • Implementar autenticación de usuarios con OpenID Connect e IdentityServer4.
  • Implementar aplicaciones combinando OAuth 2.0, OpenID Connect e IdentityServer4 para proteger recursos.
  • Acceder a recursos protegidos desde clientes JavaScript.
  • Acceder a recursos protegidos desde clientes Blazor WebAssembly.
  • Utilizar Entity Framework Core con IdentityServer4.
  • Utilizar ASP.NET Core Identity con IdentityServer4.

Audiencia

Este entrenamiento está dirigido a desarrolladores de aplicaciones web con ASP.NET Core que desean implementar mecanismos de autorización y autenticación en sus aplicaciones utilizando OAuth 2.0 y OpenID Connect.

Requisitos

Para realizar los ejercicios de esta lección se requiere de un entorno de desarrollo con:

  • Visual Studio 2019 versión 16.8 o posteriores con la carga de trabajo “ASP.NET and web development” .
  • NET 5.0 SDK.
  • Una suscripción de Microsoft Azure que será utilizada para consumir únicamente recursos gratuitos.

Lección 1

Introducción

Antes de empezar a trabajar con OAuth 2.0, OpenID Connect, JSON Web Tokens e IdentityServer, es importante conocer algunos conceptos básicos que nos permitirán entender el propósito de estas tecnologías para poder utilizarlas de forma óptima.

Al finalizar esta sección, los participantes podrán:

  • Describir el panorama actual de interacción entre aplicaciones.
  • Describir qué es OAuth 2.0.
  • Describir los flujos de autorización de OAuth 2.0.
  • Describir qué es OpenID Connect.
  • Describir qué es JSON Web Tokens.
  • Describir qué es IdentityServer.
  • Describir la terminología presente en las especificaciones, documentación y modelos de objetos de IdentityServer.
  • Listar las especificaciones soportadas por IdentityServer.

Lección 2

Implementando Authorization Code Flow de OAuth 2.0

Ahora que conocemos de forma teórica los flujos de autorización de OAuth 2.0. Es momento de entrar en detalle a cada uno de estos flujos para entenderlos mejor.

Para ejemplificar cada uno de los flujos de autorización de OAuth 2.0 y con el objetivo de conocer la forma en que funcionan, no utilizaremos librerías que nos puedan ocultar el detalle de su funcionamiento.

En esta lección describiremos el flujo de autorización Code de OAuth 2.0 y trabajaremos con los siguientes roles:

  • Servidor de Recursos (Resource Server): Microsoft Graph API.
  • Cliente (Client): Aplicación ASP.NET Core MVC.
  • Usuario (Resource Owner): Nuestra cuenta Microsoft.
  • Servidor de Autorización (Authorization Server): Azure Active Directory.

En esta lección realizaremos las siguientes tareas:

  • Configurar el Servidor de Autorización.
  • Crear el Cliente OAuth.
  • Obtener el Código de Autorización.
  • Recuperar el Código de Autorización desde la URL.
  • Obtener el Token de Acceso.
  • Acceder al recurso protegido utilizando el Token de Acceso.

Lección 3

Implementando Implicit Flow de OAuth 2.0

Cuando una aplicación no es capaz de guardar un secreto debido a que se ejecuta completamente del lado del cliente, Implicit Flow es la solución.

En esta lección veremos la forma de implementar el flujo de autorización Implicit de OAuth 2.0 y trabajaremos con los siguientes roles:

  • Servidor de Recursos (Resource Server): Microsoft Graph API.
  • Cliente (Client): Aplicación ASP.NET Core Blazor WebAssembly.
  • Usuario (Resource Owner): Nuestra cuenta Microsoft.
  • Servidor de Autorización (Authorization Server): Azure Active Directory.

En esta lección realizaremos las siguientes tareas:

  • Configurar el Servidor de Autorización.
  • Crear el Cliente OAuth.
  • Obtener el Código de Autorización.
  • Obtener el Token de Acceso.
  • Acceder al recurso protegido utilizando el Token de Acceso.

Lección 4

Implementando Implicit Flow con Refresh Token de OAuth 2.0

Los tokens que el servidor de autorización proporciona después de que el usuario ha sido autenticado, tienen un tiempo de expiración. Para seguir accediendo a los recursos protegidos es necesario tener un token válido que no haya expirado. Si para obtener un nuevo token tuviéramos que repetir el flujo, incluyendo nuevamente la autenticación del usuario, esto sería una mala experiencia para él. Con el objetivo de que esto no ocurra, existen los Tokens de Actualización , mejor conocidos como Refresh Tokens.

Los Refresh Tokens son tan confidenciales como un secreto ya que pueden ser utilizados para ser intercambiados por un Token de Acceso. Por lo tanto, por cuestiones de seguridad, los Refresh Tokens no están disponibles en todos los flujos que ofrece OAuth 2.0, ya que, si estos son expuestos en un cliente público, podrían facilitar a cualquiera recuperar el Token de Acceso.

Implicit Flow es uno de los flujos que no soporta los Refresh Tokens, sin embargo, existe una técnica llamada Silent Refresh que nos permite actualizar el token de acceso una vez que el usuario se ha autenticado al menos una vez. La mayoría de las librerías cliente de OAuth tienen implementada esta técnica, sin embargo, en esta lección modificaremos la aplicación Blazor creada anteriormente para ejemplificar esta técnica sin utilizar ninguna librería cliente de OAuth.

En esta lección veremos la forma de implementar la técnica Silent Refresh basándonos en la aplicación Blazor creada en la lección anterior que trabaja con los siguientes roles:

  • Servidor de Recursos (Resource Server): Microsoft Graph API.
  • Cliente (Client): Aplicación ASP.NET Core Blazor WebAssembly.
  • Usuario (Resource Owner): Nuestra cuenta Microsoft.
  • Servidor de Autorización (Authorization Server): Azure Active Directory.

En esta lección realizaremos las siguientes tareas:

  • Configurar el Servidor de Autorización.
  • Crear el Cliente OAuth.
  • Implementar la técnica Silent Refresh.

Lección 5

Implementando Client Credentials Flow de OAuth 2.0

Existen aplicaciones donde no es necesario interactuar a nombre de un usuario, cualquier tipo de acción se hace a nombre de la aplicación misma. El flujo Client Credentials de OAuth 2.0 está pensado específicamente para este escenario.

En esta lección describiremos el flujo Client Credentials de OAuth 2.0 y trabajaremos con los siguientes roles:

  • Servidor de Recursos (Resource Server): Microsoft Graph API.
  • Cliente (Client): Aplicación ASP.NET Core MVC.
  • Servidor de Autorización (Authorization Server): Azure Active Directory.

En esta lección realizaremos las siguientes tareas:

  • Configurar el Servidor de Autorización.
  • Crear el Cliente OAuth.
  • Obtener el Token de acceso.
  • Acceder al recurso protegido.

Lección 6

Implementando Resource Owner Password Credentials (ROPC) Flow de OAuth 2.0

Los flujos Authorization Code, Implicit y Client Credentials que hemos visto en lecciones anteriores, están enfocados en las aplicaciones modernas para que estas tengan la mínima exposición de las credenciales de sus usuarios, así como controlar los permisos que tiene una aplicación sobre los recursos que intenta acceder. Sin embargo, en la actualidad, aún existen aplicaciones viejas (legacy) que todavía utilizan HTTP Basic Authentication donde las credenciales del usuario viajan a través de la red. Para estos casos, el flujo Resource Owner Password Credentials (RPOC) es una opción de integración con OAuth 2.0.

El flujo ROPC debería ser una solución temporal, para dar tiempo a cambiar el tipo de autenticación de la aplicación ya que, en este caso, enviamos directamente el nombre de usuario y contraseña para obtener el Token.

En esta lección describiremos el flujo Resource Owner Password Credentials de OAuth 2.0 y trabajaremos con los siguientes roles:

  • Servidor de Recursos (Resource Server): Microsoft Graph API.
  • Cliente (Client): Aplicación ASP.NET Core MVC.
  • Usuario (Resource Owner): Nuestra cuenta Microsoft.
  • Servidor de Autorización (Authorization Server): Azure Active Directory.

En esta lección realizaremos las siguientes tareas:

  • Configurar el Servidor de Autorización.
  • Crear el Cliente OAuth.
  • Obtener el Token de acceso.
  • Acceder al recurso protegido.

Lección 7

Implementando Device Code Flow de OAuth 2.0

Es probable que tengamos la necesidad de otorgar permisos a dispositivos que no cuenten con un navegador web como podría ser el caso de dispositivos IoT. Para poder otorgar permisos con OAuth a este tipo de dispositivos, existe un flujo de OAuth llamado Device Code Flow .

En el flujo Device Code, el dispositivo cliente hace un llamado al servidor de autorización a través del endpoint Autorización de Dispositivo. El servidor de autorización le devuelve un código de dispositivo junto con un código de usuario y un enlace además de otros valores. El dispositivo solicitará al usuario dirigirse al enlace recibido para autenticarse y proporcionar el código de usuario. Mientras tanto, a intervalos de tiempo, el dispositivo cliente estará solicitando al servidor de autorización el token de acceso. Mientras el usuario no valide el código, el servidor de autorización devolverá un error 400 indicando que debe continuar solicitando el token de acceso. Una vez que el usuario se autentique y proporcione el código de usuario al servidor de autorización, este otorgará el token de acceso al dispositivo.

En esta lección describiremos el flujo Device Code de OAuth 2.0 y trabajaremos con los siguientes roles:

  • Servidor de Recursos (Resource Server): Microsoft Graph API.
  • Cliente (Client): Aplicación de Consola .NET Core para simular un dispositivo sin navegador.
  • Usuario (Resource Owner): Nuestra cuenta Microsoft.
  • Servidor de Autorización (Authorization Server): Azure Active Directory.

En esta lección realizaremos las siguientes tareas:

  • Configurar el Servidor de Autorización.
  • Crear el Cliente OAuth.
  • Obtener el código de validación del dispositivo.
  • Esperar la confirmación del usuario para obtener el token de acceso.
  • Acceder al recurso protegido.

Lección 8

Implementando el flujo Authorization Code y PKCE de OAuth 2.0

Aunque el flujo Authorization Code se considera el más seguro de todos, se ha demostrado que, en aplicaciones nativas, el código que otorga el servidor de autorización puede ser interceptado por aplicaciones maliciosas, obteniendo con esto el token de acceso a nuestros recursos protegidos. Es por esta razón que el uso de la extensión PKCE, o Proof Key for Code Exchange, es recomendada cuando utilizamos este flujo en aplicaciones nativas.

En esta lección exploraremos la extensión PKCE incorporándola al ejemplo Authorization Code Flow que creamos previamente.

En esta lección trabajaremos con los siguientes roles:

  • Servidor de Recursos (Resource Server): Microsoft Graph API.
  • Cliente (Client): Aplicación ASP.NET Core MVC.
  • Usuario (Resource Owner): Nuestra cuenta Microsoft.
  • Servidor de Autorización (Authorization Server): Azure Active Directory.

En esta lección realizaremos las siguientes tareas:

  • Crear el Cliente OAuth.
  • Generar los valores code_verifier y code_challenge.
  • Obtener el Código de Autorización.
  • Obtener el Token de Acceso

Lección 9

Crear una API con Scopes y Azure Active Directory

La mayoría de las APIs basan su acceso en los Scopes. Ahora que ya conocemos el papel de los scopes en OAuth 2.0, en esta lección aprenderemos a configurar una API con scopes en Azure Active Directory y a validarlos con ASP.NET Core.

En esta lección trabajaremos con los siguientes roles:

  • Servidor de Recursos (Resource Server): La API WeatherAPI que crearemos con ASP.NET Core Web API.
  • Cliente (Client): Una Aplicación ASP.NET Core MVC.
  • Usuario (Resource Owner): Nuestra cuenta Microsoft.
  • Servidor de Autorización (Authorization Server): Azure Active Directory.

En esta lección realizaremos las siguientes tareas:

  • Registrar la API en Azure Active Directory.
  • Registrar la aplicación Cliente en Azure Active Directory.
  • Crear el Cliente OAuth.
  • Crear la API.
  • Obtener el Token de Acceso.
  • Invocar a la API WeatherAPI.

Lección 10

Explorando los flujos de OpenID Connect

OpenID Connect es una extensión de OAuth 2.0. A diferencia de OAuth 2.0 que especifica la forma de emitir Tokens de Acceso (Access Tokens), OpenID Connect especifica la forma de emitir Tokens de Identidad (ID Tokens).

OAuth 2.0 define response_type como un parámetro obligatorio de una petición. OpenID Connect define flujos para emitir ID Tokens extendiendo la especificación del parámetro de petición response_type.

En OAuth 2.0 el valor de response_type puede ser code o token. OpenID Connect ha agregado un nuevo valor: id_token. Como resultado, ahora response_type puede tener como valor una combinación entre code, token e id_token.

Algo importante de mencionar es que al realizar peticiones de un ID Token es necesario incluir el valor openid en el parámetro scope. Si este valor no es incluido, el ID Token no es emitido.

OpenID Connect define 3 flujos, 2 de los cuales se basan en los flujos definidos por OAuth 2.0: Authorization Code Flow, Implicit Flow y Hybrid Flow. Estos flujos establecen los tipos de respuesta (response_type) que puede solicitar una petición de autorización y la forma en que los tokens son devueltos a la aplicación cliente.

En esta lección realizaremos las siguientes tareas:

  • Implementar Authorization Code Flow.
  • Implementar Implicit Flow.
  • Implementar Hybrid Flow.

Lección 11

Protegiendo una API con IdentityServer utilizando Credenciales de Cliente

Es momento ahora de ver algunos casos prácticos de implementación de OAuth 2.0 y OpenID Connect. Con esta lección empezaremos nuestro recorrido por varios escenarios comunes utilizando el framework IdentityServer, desde escenarios básicos hasta escenarios más complejos.

En esta lección presentaremos el escenario más básico para proteger APIs utilizando IdentityServer y el flujo Client Credentials.

En esta lección crearemos un servidor de autorización, una API y un cliente para consumirla. El cliente solicitará un token de acceso al servidor de autorización utilizando su ID de Cliente y un Secreto para posteriormente utilizar el token de acceso para acceder a la API.

En esta lección realizaremos las siguientes tareas:

  • Crear el servidor de autorización.
  • Definir la configuración de la API, los Scopes y el Cliente.
  • Configurar IdentityServer.
  • Crear la API.
  • Invocar a la API.
  • Explorar escenarios de error.

Lección 12

Protegiendo una API con IdentityServer utilizando Credenciales de Usuario

Debido a que en el flujo ROPC el password es enviado a través de la red, la especificación recomienda no utilizar este flujo. En vez de ello, se recomienda utilizar alguno de los flujos interactivos de OpenID Connect cuando se desee autenticar a un usuario y solicitar tokens de acceso.

Con fines didácticos y para el caso en que nos encontremos con algún escenario donde debamos implementar este flujo, en esta lección mostraremos la forma de implementar el flujo ROPC con IdentityServer y aprovecharemos la oportunidad para introducir el concepto de usuarios.

En esta lección realizaremos las siguientes tareas:

  • Agregar usuarios.
  • Agregar soporte para el flujo Resource Owner Password Credentials.
  • Solicitar el token de acceso utilizando el grant type password.

Lección 13

Agregar autenticación de Usuarios con OpenID Connect

En esta lección agregaremos soporte a nuestro servidor de identidad para poder realizar una autenticación de usuario interactiva a través del protocolo OpenID Connect.

Agregaremos también una aplicación ASP.NET Core MVC que utilizará al servidor de identidad para autenticación.

En esta lección realizaremos las siguientes tareas:

  • Agregar la interfaz de usuario.
  • Crear un cliente ASP.NET Core MVC.
  • Agregar soporte para scopes de identidad de OpenID Connect.
  • Agregar soporte para finalizar la sesión del usuario.
  • Obtener claims desde el endpoint UserInfo.
  • Obtener claims personalizados.
  • Agregar soporte para autenticación externa con Google, Facebook, Microsoft y Twitter.

Lección 14

Implementando el acceso a recursos y la autenticación de usuarios

En las lecciones anteriores, exploramos el acceso a la API y la autenticación de usuarios. Ahora veamos como combinar las dos partes.

La belleza de la combinación de OpenID Connect y OAuth 2.0 es que podemos lograr ambas cosas con un solo intercambio con el servicio de tokens.

Hasta ahora, solo solicitamos recursos de identidad durante la solicitud del token, una vez que comencemos a incluir también los recursos de APIs, IdentityServer nos devolverá dos tokens: el token de identidad que contiene la información sobre la autenticación y el token de acceso para acceder a las APIs en nombre del usuario autenticado.

En esta lección realizaremos las siguientes tareas:

  • Modificar la configuración del Cliente.
  • Modificar la aplicación cliente.
  • Utilizar el token de acceso.
  • Utilizar el token de identidad.

Lección 15

Agregar un cliente JavaScript

En esta lección conoceremos la forma de construir aplicaciones JavaScript basadas en el navegador web, también conocidas como aplicaciones SPA ( Single Page Application ).

El usuario iniciará sesión en IdentityServer, invocará la web API con un token de acceso emitido por IdentityServer y cerrará su sesión de IdentityServer. Haremos todo esto desde la aplicación JavaScript ejecutándose en el navegador web.

En esta lección realizaremos las siguientes tareas:

  • Crear un cliente JavaScript.
  • Agregar la referencia de la biblioteca JavaScript oidc-client.
  • Agregar archivos HTML y JavaScript.
  • Registrar el cliente JavaScript con IdentityServer.
  • Permitir peticiones AJAX en la API Web.

Lección 16

Agregar un cliente Blazor WebAssembly

En esta lección conoceremos la forma de construir aplicaciones Blazor WebAssembly basadas en el navegador web, también conocidas como aplicaciones SPA ( Single Page Application ).

Blazor WebAssembly incluye soporte para autenticación del lado del cliente que hace relativamente simple implementar OAuth2 y OpenID Connect en aplicaciones SPA.

El usuario iniciará sesión en IdentityServer, invocará la web API con un token de acceso emitido por IdentityServer y cerrará su sesión de IdentityServer. Haremos todo esto desde la aplicación Blazor WebAssembly ejecutándose en el navegador web.

Mostraremos también la forma de configurar IdentityServer para dar soporte al manejo de roles de usuario para implementar políticas de autorización basadas en roles en APIs Web y aplicaciones Blazor WebAssembly.

En esta lección realizaremos las siguientes tareas:

  • Crear una aplicación Blazor WebAssembly.
  • Agregar soporte para autenticación.
  • Compartir información de autorización.
  • Agregar el componente de autenticación.
  • Mostar el estado actual de autenticación.
  • Requerir autenticación en componentes razor.
  • Mostrar los claims del usuario.
  • Invocar a la API utilizando el token de acceso.
  • Proporcionar soporte para manejo de roles de usuario.

Lección 17

Utilizar Entity Framework Core con IdentityServer

En los ejercicios anteriores hemos creado nuestros clientes y datos de scope mediante código. Al iniciar la aplicación, IdentityServer carga los datos de configuración a la memoria. Si queremos modificar estos datos de configuración, necesitamos detener e iniciar nuevamente a IdentityServer.

IdentityServer también genera datos temporales, tales como códigos de autorización, opciones de consentimiento y tokens de actualización. De manera predeterminada, estos datos son almacenados en memoria.

En esta lección, describiremos la forma de integrar Entity Framework Core con IdentityServer para mover los datos de configuración y operación de IdentityServer a una base de datos que sea persistente entre reinicios y a través de múltiples instancias de IdentityServer.

En esta lección realizaremos las siguientes tareas:

  • Utilizar la biblioteca IdentityServer4.EntityFramework.
  • Configurar los almacenes de datos.
  • Agregar las migraciones.
  • Inicializar la base de datos.
  • Ejecutar las aplicaciones cliente.

Lección 18

Utilizar ASP.NET Core Identity con IdentityServer

IdentityServer está diseñado para ofrecer flexibilidad y parte de esa flexibilidad nos permite utilizar cualquier base de datos que deseemos para nuestros usuarios y sus datos, incluidas las contraseñas.

Si estamos iniciando con una nueva base de datos de usuarios, entonces ASP.NET Core Identity puede ser una opción que podemos elegir.

En esta lección mostraremos la forma de utilizar ASP.NET Core Identity con IdentityServer.

En esta lección realizaremos las siguientes tareas:

  • Crear un proyecto para ASP.NET Core Identity.
  • Agregar soporte para IdentityServer.
  • Crear la base de datos de ASP.NET Core Identity.
  • Ejecutar las aplicaciones cliente.