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

Este é um exemplo básico sobre como configurar e utilizar o MicroProfile JWT no TomEE.

== Execute testes para diferentes cenários relacionados à validação JWT

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

== Configuração no TomEE

A classe `MoviesMPJWTConfigurationProvider.java` fornece ao TomEE as configurações necessárias para a validação do 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();
    }
}
----

== Usando o MicroProfile JWT no TomEE

O recurso JAX-RS `MoviesRest.java` contém vários endpoints que estão protegidos usando a anotação padrão `@RolesAllowed`. O MicroProfile JWT é responsável por validar solicitações recebidas com o cabeçalho `Authorization' que fornece um token de acesso assinado.

[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 a arquitetura de teste

Os casos de teste para este projeto são construídos com o Arquillian. A configuração do Arquillian pode ser encontrada em `src/test/resources/arquillian.xml`

A classe `TokenUtils.java` é usada durante o teste para atuar como um servidor de Autorização que gera `Access Tokens` com base nos arquivos de configuração `privateKey.pem`,`publicKey.pem`, `Token1.json` e `Token2.json`.

`nimbus-jose-jwt` é a biblioteca usada para a geração do JWT durante os testes.

`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"
  ]
}
----

== Cenários de teste

`MovieTest.java` contém 4 cenários OAuth2 para diferentes combinações 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);
        }
    }

}
----
