# __Protegiendo servicios REST con Oauth2__
En este proyecto encontrarás algunas herramientas para añadir la seguridad del framework **OAuth2** a los recursos exhibidos por cualquier _endpoint_ de un servicio REST.
## **Clases importantes**
### **GestorHttp**
:::info
- _recibirToken_
~ Método se encarga de realizar una llamada POST al endpoint "*/oauth2/token" del servidor **Ory Hydra** y recibe el token que se enviará al cliente. En cualquier otro caso se lanzará una excepción con el código de error Http y la descripción del error devuelto por el servidor.
- _intospeccionarToken_
~ Método se encarga de realizar una llamada POST al endpoint "*/oauth2/introspect" del servidor **Ory Hydra** y recibe comprueba que el token enviado es valido. En cualquier otro caso se lanzará una excepción con el código de error Http y la descripción del error devuelto por el servidor.
- _comprobarValidezToken_
~ Método se encarga de realizar una llamada POST al endpoint "*/oauth2/introspect" del servidor **Ory Hydra** para comprobar que un token en concreto, enviado en la petición, sea válido. También recibe el _Scope_ del recurso desde donde se le llamó para asegurarse de que el token recibido corresponde con el _scope_ del recurso.
- _formatearJson_
~ Método encargado de recibir el cuerpo de las respuestas de __Ory Hydra__ y formatearlas para enviarlas de nuevo al cliente.
- _extraerParametrosCuerpoRequest_
~ Método encargado de recibir el cuerpo de las peticiones recibidas en nuestra aplicación guardando la información necesaria en estructuras de datos para su posterior uso.
- _extraerValidezToken_
~ Método auxiliar privado que extrae el campo de la respuesta del servidor, al realizar la introspección del token, donde se indica la validez del token.
- _crearClienteHttpSinSeguridad_
~ Junto con esta clase envoltorio, que reliza las comunicaciones entre el servidor y nuestros servicios, se incluye un método que construye peticiones HTTP con certificados auto firmados. Este método se incluye por motivos de desarrollo y testeo. La manera de utilzarlo se explicará en la [sección correspondiente](#instalacion).
:::
## **Endpoints importantes**
### **TokenEndpoint**
:::info
- path
~ */oauth2/token
- get
~ Método no permitido. En caso de realizar una petición a este endopoint se envía al cliente información para relizar correctamente la llamada POST.
- post
~ Endpoint que recibe el _client_id_, _client_secret_, _scope_ y _grant_type_ por el cuerpo de la llamada POST. Estos datos son después enviados al _GestorHttp_ para procesar las comunicaciones con el servidor.
:::
## **Modo de uso**
### [Incorporación en proyecto](#instalacion)
1. Para incluir estas funcionalidades en cualquier proyecto será necesario incluir la clase **GestorHttp** en tu proyecto.
2. Después debes definir que tipo de cliente se va a crear. Para ello se debe comentar/descomentar un par de líneas de código dentro de **GestorHttp** en los siguientes métodos:
- Cliente sin seguridad https (acepta certificados auto firmados), muy útil para desarrollo y testeo)


- Cliente con seguridad


### Uso
Una vez seleccionado el tipo de cliente tan sólo habría que instanciar dicha clase dentro del servicio REST que queramos y llamar a los métodos correspondientes:
- Recibiendo token
``` java
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Map<String, Object> post(String cuerpo) {
try {
return gestorHttp.recibirToken(cuerpo);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
```
- Realizando la introscpección de un token concreto(El token será válido en caso de que el _SCOPE_ sobre el que se pidió el token coincida con el indicado en el cuerpo de la llamada POST o que no se envíe _SCOPE_ ninguno)
```java
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Map<String, Object> post(String cuerpo) {
try {
return gestorHttp.introspeccionarToken(cuerpo);
} catch (Exception ex) {
Logger.getLogger(IntrospectPoint.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
```
- Comprobando la validez y recibiendo recursos (una lista de usuarios en nuestro ejemplo). Hay que tener en cuenta que la variable _SCOPE_ es una constante del recurso.
``` java
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Usuario> get(@Context HttpHeaders header) {
try {
if(gestorHttp.comprobarValidezToken("", header.getHeaderString("token"), SCOPE)) {
return usuarioService.getUsuarios();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
```
## **Referencias**
- [Ory Hydra Oauth2 Server API](https://www.ory.sh/docs/api/hydra/)
- [Configuración Servidor Oauth2](https://hackmd.io/s/Hy3aT4Y8X)