diff --git a/pom.xml b/pom.xml index 566f406..e7fe8c7 100644 --- a/pom.xml +++ b/pom.xml @@ -40,6 +40,14 @@ io.quarkus quarkus-resteasy + + io.quarkus + quarkus-smallrye-jwt-build + + + io.quarkus + quarkus-smallrye-jwt + io.quarkus quarkus-junit5 diff --git a/src/main/java/com/covas/Jwt2.java b/src/main/java/com/covas/Jwt2.java new file mode 100644 index 0000000..7e98745 --- /dev/null +++ b/src/main/java/com/covas/Jwt2.java @@ -0,0 +1,36 @@ +package com.covas; + +import io.quarkus.runtime.annotations.RegisterForReflection; + +@RegisterForReflection +public class Jwt2 { + + public String name; + public Boolean status; + public String message; + + public Jwt2(){ + name = ""; + status = true; + message = ""; + } + + public Jwt2(String name){ + this.name = name; + status = true; + message = ""; + } + + public Jwt2(String name, String message){ + this.name = name; + this.message = message; + status = true; + } + + public Jwt2(String name, Boolean status, String message){ + this.name = name; + this.status = status; + this.message = message; + } + +} diff --git a/src/main/java/com/covas/Token.java b/src/main/java/com/covas/Token.java new file mode 100644 index 0000000..fe6eec7 --- /dev/null +++ b/src/main/java/com/covas/Token.java @@ -0,0 +1,36 @@ +package com.covas; + +import io.quarkus.runtime.annotations.RegisterForReflection; + +@RegisterForReflection +public class Token { + + public String name; + public Boolean isHttps; + public String authScheme; + public Boolean hasJwt; + public String birthday; + public String role = ""; + + public Token(){ + this.name = "anonymous"; + this.isHttps = false; + this.authScheme = ""; + this.hasJwt = false; + this.birthday = ""; + this.role = ""; + } + + public Token(String name, Boolean isHttps, String authScheme, Boolean hasJwt){ + this.name = name; + this.isHttps = isHttps; + this.authScheme = authScheme; + this.hasJwt = hasJwt; + this.birthday = ""; + this.role = ""; + } + + + + +} diff --git a/src/main/java/com/covas/TokenRessource.java b/src/main/java/com/covas/TokenRessource.java new file mode 100644 index 0000000..2ecd335 --- /dev/null +++ b/src/main/java/com/covas/TokenRessource.java @@ -0,0 +1,109 @@ +package com.covas; + +import java.util.Arrays; +import java.util.HashSet; + +import javax.annotation.security.PermitAll; +import javax.annotation.security.RolesAllowed; +import javax.inject.Inject; +import javax.ws.rs.CookieParam; +import javax.ws.rs.GET; +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.NewCookie; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; + +import io.smallrye.jwt.auth.principal.JWTParser; +import io.smallrye.jwt.auth.principal.ParseException; +import io.smallrye.jwt.build.Jwt; + +import org.eclipse.microprofile.jwt.JsonWebToken; + + +@Path("/token") +public class TokenRessource { + + + @Inject + JsonWebToken jwt; + + @Inject JWTParser parser; + + + @GET + @Path("authentificate") + @Produces(MediaType.APPLICATION_JSON) + public Response getUserName(@CookieParam("jwt") String jwtCookie) { + if (jwtCookie == null) { + // Create a JWT token signed using the 'HS256' algorithm + String newJwtCookie = Jwt.issuer("https://example.com/issuer").upn("Alice").groups(new HashSet<>(Arrays.asList("User"))).sign(); + // or create a JWT token encrypted using the 'A256KW' algorithm + // Jwt.upn("alice").encryptWithSecret(secret); + + return Response.status(Response.Status.CREATED).entity(new Jwt2("Alice")).cookie(new NewCookie("jwt", newJwtCookie)).build(); + } else { + // All mp.jwt and smallrye.jwt properties are still effective, only the verification key is customized. + try { + jwt = parser.parse(jwtCookie); + } + catch(ParseException p){ + return Response.status(Response.Status.NOT_ACCEPTABLE).entity(new Jwt2("Alice", false, p.getMessage())).build(); + } + // or jwt = parser.decrypt(jwtCookie, secret); + return Response.status(Response.Status.OK).entity(new Jwt2(jwt.getName())).build(); + } + } + + @GET + @Path("permit-all") + @PermitAll + @Produces(MediaType.APPLICATION_JSON) + public Token hello(@Context SecurityContext ctx) { + return getResponseString(ctx); + } + + @GET + @Path("roles-allowed") + @RolesAllowed({"Admin" }) + @Produces(MediaType.APPLICATION_JSON) + public Token helloRolesAllowed(@Context SecurityContext ctx) { + Token token = getResponseString(ctx); + token.name = jwt.getName().toString(); + token.role = "Admin"; + return token; + } + + @GET + @Path("roles-user") + @RolesAllowed({"Toto"}) + @Produces(MediaType.APPLICATION_JSON) + public Token helloRolesUser(@Context SecurityContext ctx) { + Token token = getResponseString(ctx); + token.name = jwt.getName().toString(); + token.role = "User"; + return token; + } + + + private Token getResponseString(SecurityContext ctx) { + String name; + if (ctx.getUserPrincipal() == null) { + name = "anonymous"; + } else if (!ctx.getUserPrincipal().getName().equals(jwt.getName())) { + throw new InternalServerErrorException("Principal and JsonWebToken names do not match"); + } else { + name = ctx.getUserPrincipal().getName(); + } + return new Token(name, ctx.isSecure(), ctx.getAuthenticationScheme(), hasJwt()); + } + + private boolean hasJwt() { + return jwt.getClaimNames() != null; + } + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e69de29..3e147b7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -0,0 +1,6 @@ +smallrye.jwt.sign.key.location=privateKey.pem + + + +mp.jwt.verify.publickey.location=publicKey.pem +mp.jwt.verify.issuer=https://example.com/issuer \ No newline at end of file diff --git a/src/main/resources/privateKey.pem b/src/main/resources/privateKey.pem new file mode 100644 index 0000000..d2f1062 --- /dev/null +++ b/src/main/resources/privateKey.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDpjthUAWnz5l6d +Y5UTjW8zXx4IGwU0BK2HN7oPeZs1LTA6UDbHQtNK3rBlI/ycxFcmbGWm0v5folan +rRoCkpZjbvlddyATc1puVXn8vtKUBuXfJNQL28riSzIp3ifflKEVkwtCvyeLHTWN +XTATKArmQhWEBwQozwqITMhKxHcBfKJOBv3Hwd0S8elnHLyRzzVd60ulDAtV0Glv +09B3/j1DV+5NQU9iBq7I997RX4uVekkk3vjk/71ego5WhRhMTB6WTZ3zySCndkUY +6NNygPcL1i0CVKs8nLpgreTYxeObY/yXD7SlJQHM0jO20UNt6O313BzajI/E/b0s +UiXEaJWXAgMBAAECggEAf8+D4rTDXo16yXZtZj3H1L0Amj7vIgBNVenREBbkML2B +3ud2kqSnLBmhPjfrTX7EkmpPVnOwcHVOJoQ775x4YAGixNsj2oENw8NS9lUWt5ru +wKZOxA6LgDrWQMMp3thfLodBak1hPmfFno6YeGM5U7hmPdH5HLvwb5ZVJVVOKqkV ++a5vIqxNfsk/e2WPXI1LkSE/PlXvAS/6+CCNUXekis8ug12BRUM2qxBqpZuqUty+ +IuoLHf8RZ1J0rTksbgV/Z7BYxr8nEuQ0zm2CnejGJ4v5hLID23jD9QNbvv+qrp/b +ULoo4Dmct/ju/Y6JJPxQcy17BtT0G9xGhZaJ51uFQQKBgQD9xNB6nurvRhfvjZ/O +HKcJiFVWoxdLrSGGFtPWzd1EgTD+U2hhysBSfurWZ9PiAgxAyZwh3GEagRlaCjDH +OFvAGnhZB78Zb8kcMnpej2ju/mjjpYN+t9W1fJKKgz/oaQ+bPB7EwfQfR7s+CbV2 +NBk6ZPrbLaDPy7v+zkQXh3brwwKBgQDrnIo4zSmAQGIRkmnz+1HMtZKkb533+GiQ +CAAbkf7HvsGf1wq/UQEQhhMLkTAuaWhQp0QcPoLF/udgf9pi9Ra0Y59b8RCcXDMv +u987EqNH1gUtYGOzTbIQ133aWIaKUB6+xjOfshAviu5dngz2tzswzMwkAeSIoitm +EgM1mSEVnQKBgBtHffXAgZbJHSeWPNiGQfqHWk0e6REsgk8MwybzKFcF4ENmqfDh +P71egVYdASzpdXG9eng1XYbg293O/KFd0JcdAVTovUU5vA+46Wii1+/hD1txXmpP +zrxcsNAM/eC48oGIe/JAu0Jljp5Dousa/J9HXaQUCpZr20Cv4af52vHLAoGBAKVt +mQM+0dfR3MmXsrrzB8Ei795y3EhiaxBN/b1d6bTXs92FwG8J8iRm7vJdM6YyrmKK +vuDR50Ibsttnia+XhCSOGjMU9GPEvM/UKm2wrWJf2+y7U+VuNQtsMlpfc7+jd6Ld +SRvki0bGVoz2zwVfK7kc4myZw5tHug8FsKkuZjNlAoGBAPKYRTMsxwLVGmmz4tLg +W4QyEKgtX31f8EqQxJweN6iC+55bNdLVJ8xrs3PTdn5UNq3CLu8kFdvKycmy/Mu3 +bz1ZA/fIY3stV4TzqkbKBV8vChgb+0NPxd6QLwa9z8j5zwgpVQDVoRoj/y79WGRW +GGVrsKVMuRatfJ0Q5ZWcMNOp +-----END PRIVATE KEY----- diff --git a/src/main/resources/publicKey.pem b/src/main/resources/publicKey.pem new file mode 100644 index 0000000..8c159c7 --- /dev/null +++ b/src/main/resources/publicKey.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6Y7YVAFp8+ZenWOVE41v +M18eCBsFNASthze6D3mbNS0wOlA2x0LTSt6wZSP8nMRXJmxlptL+X6JWp60aApKW +Y275XXcgE3NablV5/L7SlAbl3yTUC9vK4ksyKd4n35ShFZMLQr8nix01jV0wEygK +5kIVhAcEKM8KiEzISsR3AXyiTgb9x8HdEvHpZxy8kc81XetLpQwLVdBpb9PQd/49 +Q1fuTUFPYgauyPfe0V+LlXpJJN745P+9XoKOVoUYTEwelk2d88kgp3ZFGOjTcoD3 +C9YtAlSrPJy6YK3k2MXjm2P8lw+0pSUBzNIzttFDbejt9dwc2oyPxP29LFIlxGiV +lwIDAQAB +-----END PUBLIC KEY----- diff --git a/src/main/resources/rsaPrivateKey.pem b/src/main/resources/rsaPrivateKey.pem new file mode 100644 index 0000000..7502e44 --- /dev/null +++ b/src/main/resources/rsaPrivateKey.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA6Y7YVAFp8+ZenWOVE41vM18eCBsFNASthze6D3mbNS0wOlA2 +x0LTSt6wZSP8nMRXJmxlptL+X6JWp60aApKWY275XXcgE3NablV5/L7SlAbl3yTU +C9vK4ksyKd4n35ShFZMLQr8nix01jV0wEygK5kIVhAcEKM8KiEzISsR3AXyiTgb9 +x8HdEvHpZxy8kc81XetLpQwLVdBpb9PQd/49Q1fuTUFPYgauyPfe0V+LlXpJJN74 +5P+9XoKOVoUYTEwelk2d88kgp3ZFGOjTcoD3C9YtAlSrPJy6YK3k2MXjm2P8lw+0 +pSUBzNIzttFDbejt9dwc2oyPxP29LFIlxGiVlwIDAQABAoIBAH/Pg+K0w16Nesl2 +bWY9x9S9AJo+7yIATVXp0RAW5DC9gd7ndpKkpywZoT43601+xJJqT1ZzsHB1TiaE +O++ceGABosTbI9qBDcPDUvZVFrea7sCmTsQOi4A61kDDKd7YXy6HQWpNYT5nxZ6O +mHhjOVO4Zj3R+Ry78G+WVSVVTiqpFfmubyKsTX7JP3tlj1yNS5EhPz5V7wEv+vgg +jVF3pIrPLoNdgUVDNqsQaqWbqlLcviLqCx3/EWdSdK05LG4Ff2ewWMa/JxLkNM5t +gp3oxieL+YSyA9t4w/UDW77/qq6f21C6KOA5nLf47v2OiST8UHMtewbU9BvcRoWW +iedbhUECgYEA/cTQep7q70YX742fzhynCYhVVqMXS60hhhbT1s3dRIEw/lNoYcrA +Un7q1mfT4gIMQMmcIdxhGoEZWgowxzhbwBp4WQe/GW/JHDJ6Xo9o7v5o46WDfrfV +tXySioM/6GkPmzwexMH0H0e7Pgm1djQZOmT62y2gz8u7/s5EF4d268MCgYEA65yK +OM0pgEBiEZJp8/tRzLWSpG+d9/hokAgAG5H+x77Bn9cKv1EBEIYTC5EwLmloUKdE +HD6Cxf7nYH/aYvUWtGOfW/EQnFwzL7vfOxKjR9YFLWBjs02yENd92liGilAevsYz +n7IQL4ruXZ4M9rc7MMzMJAHkiKIrZhIDNZkhFZ0CgYAbR331wIGWyR0nljzYhkH6 +h1pNHukRLIJPDMMm8yhXBeBDZqnw4T+9XoFWHQEs6XVxvXp4NV2G4NvdzvyhXdCX +HQFU6L1FObwPuOlootfv4Q9bcV5qT868XLDQDP3guPKBiHvyQLtCZY6eQ6LrGvyf +R12kFAqWa9tAr+Gn+drxywKBgQClbZkDPtHX0dzJl7K68wfBIu/ectxIYmsQTf29 +Xem017PdhcBvCfIkZu7yXTOmMq5iir7g0edCG7LbZ4mvl4QkjhozFPRjxLzP1Cpt +sK1iX9vsu1PlbjULbDJaX3O/o3ei3Ukb5ItGxlaM9s8FXyu5HOJsmcObR7oPBbCp +LmYzZQKBgQDymEUzLMcC1Rpps+LS4FuEMhCoLV99X/BKkMScHjeogvueWzXS1SfM +a7Nz03Z+VDatwi7vJBXbysnJsvzLt289WQP3yGN7LVeE86pGygVfLwoYG/tDT8Xe +kC8Gvc/I+c8IKVUA1aEaI/8u/VhkVhhla7ClTLkWrXydEOWVnDDTqQ== +-----END RSA PRIVATE KEY-----