= MicroProfile JWT
:index-group: MicroProfile
:jbake-type: page
:jbake-status: published

Este es un ejemplo básico sobre cómo configurar y usar MicroProfile JWT en TomEE.

== Ejecute las pruebas para diferentes escenarios relacionados con la validación JWT

[source,java]
----
mvn clean test 
----

== Configuración en TomEE

La clase `MoviesMPJWTConfigurationProvider.java` proporciona a TomEE la configuración 
necesaria para la validación JWT.

[source,java]
----
package org.superbiz.moviefun.rest;

import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo;

import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Optional;

@Dependent
public class MoviesMPJWTConfigurationProvider {

    @Produces
    Optional<JWTAuthContextInfo> getOptionalContextInfo() throws NoSuchAlgorithmException, InvalidKeySpecException {
        JWTAuthContextInfo contextInfo = new JWTAuthContextInfo();

        // todo use MP Config to load the configuration
        contextInfo.setIssuedBy("https://server.example.com");

        final String pemEncoded = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq" +
                "Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR" +
                "TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e" +
                "UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9" +
                "AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn" +
                "sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x" +
                "nQIDAQAB";
        byte[] encodedBytes = Base64.getDecoder().decode(pemEncoded);

        final X509EncodedKeySpec spec = new X509EncodedKeySpec(encodedBytes);
        final KeyFactory kf = KeyFactory.getInstance("RSA");
        final RSAPublicKey pk = (RSAPublicKey) kf.generatePublic(spec);

        contextInfo.setSignerKey(pk);

        return Optional.of(contextInfo);
    }

    @Produces
    JWTAuthContextInfo getContextInfo() throws InvalidKeySpecException, NoSuchAlgorithmException {
        return getOptionalContextInfo().get();
    }
}
----

== Utilizando MicroProfile JWT en TomEE

El recurso JAX-RS `MoviesRest.java` contiene varios puntos finales seguros, que se consiguen
mediante el uso de anotación estándar `@RolesAllowed`. MicroProfile JWT se encarga de realizar 
la validación de las solicitudes entrantes con el encabezado `Authorization` 
que proveen un `Access Token` firmado

[source,java]
----
   package org.superbiz.moviefun.rest;
   
   import org.superbiz.moviefun.Movie;
   import org.superbiz.moviefun.MoviesBean;
   
   import javax.annotation.security.RolesAllowed;
   import javax.inject.Inject;
   import javax.ws.rs.*;
   import javax.ws.rs.core.MediaType;
   import java.util.List;
   
   @Path("cinema")
   @Produces(MediaType.APPLICATION_JSON)
   @Consumes(MediaType.APPLICATION_JSON)
   public class MoviesRest {
   
       @Inject
       private MoviesBean moviesBean;
   
       @GET
       @Produces(MediaType.TEXT_PLAIN)
       public String status() {
           return "ok";
       }
   
       @GET
       @Path("/movies")
       @RolesAllowed({"crud", "read-only"})
       public List<Movie> getListOfMovies() {
           return moviesBean.getMovies();
       }
   
       @GET
       @Path("/movies/{id}")
       @RolesAllowed({"crud", "read-only"})
       public Movie getMovie(@PathParam("id") int id) {
           return moviesBean.getMovie(id);
       }
   
       @POST
       @Path("/movies")
       @RolesAllowed("crud")
       public void addMovie(Movie newMovie) {
           moviesBean.addMovie(newMovie);
       }
   
       @DELETE
       @Path("/movies/{id}")
       @RolesAllowed("crud")
       public void deleteMovie(@PathParam("id") int id) {
           moviesBean.deleteMovie(id);
       }
   
       @PUT
       @Path("/movies")
       @RolesAllowed("crud")
       public void updateMovie(Movie updatedMovie) {
           moviesBean.updateMovie(updatedMovie);
       }
   
   }

 @Inject
 @ConfigProperty(name = "java.runtime.version")
 private String javaVersion;
 
----

== Sobre la arquitectura de prueba

Los casos de prueba de este proyecto se construyen con Arquillian. 
La configuración arquillian se puede encontrar en 
`src/test/resources/arquillian.xml`

La clase `TokenUtils.java` se utiliza durante la prueba para actuar como 
un servidor de Autorización que genera `Access Tokens` basados en los archivos 
de configuración `privateKey.pem`, ` publicKey.pem`, `Token1.json` y 
` Token2 .json`. 

`nimbus-jose-jwt` es la libreria utilizada para la generación de JWT durante
 las pruebas.

`Token1.json`

[source,java]
----
{
    "iss": "https://server.example.com",
    "jti": "a-123",
    "sub": "24400320",
    "upn": "jdoe@example.com",
    "preferred_username": "jdoe",
    "aud": "s6BhdRkqt3",
    "exp": 1311281970,
    "iat": 1311280970,
    "auth_time": 1311280969,
    "groups": [
        "group1",
        "group2",
        "crud",
        "read-only"
    ]
}
----

`Token2.json`

[source,java]
----
{
  "iss": "https://server.example.com",
  "jti": "a-123",
  "sub": "24400320",
  "upn": "alice@example.com",
  "preferred_username": "alice",
  "aud": "s6BhdRkqt3",
  "exp": 1311281970,
  "iat": 1311280970,
  "auth_time": 1311280969,
  "groups": [
    "read-only"
  ]
}
----

== Escenarios de prueba

`MovieTest.java` contiene 4 escenarios OAuth2 para diferentes combinaciones de JWT.

[source,java]
----
package org.superbiz.moviefun;

import org.apache.cxf.feature.LoggingFeature;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.johnzon.jaxrs.JohnzonProvider;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.superbiz.moviefun.rest.ApplicationConfig;
import org.superbiz.moviefun.rest.MoviesMPJWTConfigurationProvider;
import org.superbiz.moviefun.rest.MoviesRest;

import javax.ws.rs.core.Response;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.logging.Logger;

import static java.util.Collections.singletonList;
import static org.junit.Assert.assertTrue;

@RunWith(Arquillian.class)
public class MoviesTest {

    @Deployment(testable = false)
    public static WebArchive createDeployment() {
        final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "test.war")
                                                .addClasses(Movie.class, MoviesBean.class, MoviesTest.class)
                                                .addClasses(MoviesRest.class, ApplicationConfig.class)
                                                .addClass(MoviesMPJWTConfigurationProvider.class)
                                                .addAsWebInfResource(new StringAsset("<beans/>"), "beans.xml");

        System.out.println(webArchive.toString(true));

        return webArchive;
    }

    @ArquillianResource
    private URL base;


    private final static Logger LOGGER = Logger.getLogger(MoviesTest.class.getName());

    @Test
    public void movieRestTest() throws Exception {

        final WebClient webClient = WebClient
                .create(base.toExternalForm(), singletonList(new JohnzonProvider<>()),
                        singletonList(new LoggingFeature()), null);


        //Testing rest endpoint deployment (GET  without security header)
        String responsePayload = webClient.reset().path("/rest/cinema/").get(String.class);
        LOGGER.info("responsePayload = " + responsePayload);
        assertTrue(responsePayload.equalsIgnoreCase("ok"));


        //POST (Using token1.json with group of claims: [CRUD])
        Movie newMovie = new Movie(1, "David Dobkin", "Wedding Crashers");
        Response response = webClient.reset()
                                     .path("/rest/cinema/movies")
                                     .header("Content-Type", "application/json")
                                     .header("Authorization", "Bearer " + token(1))
                                     .post(newMovie);
        LOGGER.info("responseCode = " + response.getStatus());
        assertTrue(response.getStatus() == 204);


        //GET movies (Using token1.json with group of claims: [read-only])
        //This test should be updated to use token2.json once TOMEE- gets resolved.
        Collection<? extends Movie> movies = webClient
                .reset()
                .path("/rest/cinema/movies")
                .header("Content-Type", "application/json")
                .header("Authorization", "Bearer " + token(1))
                .getCollection(Movie.class);
        LOGGER.info(movies.toString());
        assertTrue(movies.size() == 1);


        //Should return a 403 since POST require group of claims: [crud] but Token 2 has only [read-only].
        Movie secondNewMovie = new Movie(2, "Todd Phillips", "Starsky & Hutch");
        Response responseWithError = webClient.reset()
                                              .path("/rest/cinema/movies")
                                              .header("Content-Type", "application/json")
                                              .header("Authorization", "Bearer " + token(2))
                                              .post(secondNewMovie);
        LOGGER.info("responseCode = " + responseWithError.getStatus());
        assertTrue(responseWithError.getStatus() == 403);


        //Should return a 401 since the header Authorization is not part of the POST request.
        Response responseWith401Error = webClient.reset()
                                                 .path("/rest/cinema/movies")
                                                 .header("Content-Type", "application/json")
                                                 .post(new Movie());
        LOGGER.info("responseCode = " + responseWith401Error.getStatus());
        assertTrue(responseWith401Error.getStatus() == 401);

    }


    private String token(int token_type) throws Exception {
        HashMap<String, Long> timeClaims = new HashMap<>();
        if (token_type == 1) {
            return TokenUtils.generateTokenString("/Token1.json", null, timeClaims);
        } else {
            return TokenUtils.generateTokenString("/Token2.json", null, timeClaims);
        }
    }

}
----
