From cfe9d83d2c434468410310902752f3fe15152f9c Mon Sep 17 00:00:00 2001 From: Yannick Bour Date: Thu, 23 Feb 2023 15:48:32 +0100 Subject: [PATCH] jwt login --- .../peeratcode/Configuration.java | 2 +- src/be/jeffcheasey88/peeratcode/Main.java | 85 ++++++++++++++++++- .../jeffcheasey88/peeratcode/model/User.java | 71 ---------------- .../peeratcode/routes/ChapterElement.java | 3 +- .../peeratcode/routes/ChapterList.java | 3 +- .../peeratcode/routes/Login.java | 2 +- .../peeratcode/routes/PuzzleElement.java | 2 +- .../peeratcode/routes/Register.java | 2 +- .../peeratcode/webserver/Client.java | 8 +- .../peeratcode/webserver/Response.java | 2 - .../peeratcode/webserver/Router.java | 2 - 11 files changed, 94 insertions(+), 88 deletions(-) delete mode 100644 src/be/jeffcheasey88/peeratcode/model/User.java diff --git a/src/be/jeffcheasey88/peeratcode/Configuration.java b/src/be/jeffcheasey88/peeratcode/Configuration.java index 70bcf50..73e32b8 100644 --- a/src/be/jeffcheasey88/peeratcode/Configuration.java +++ b/src/be/jeffcheasey88/peeratcode/Configuration.java @@ -132,4 +132,4 @@ public class Configuration { public boolean useSsl(){ return this.use_ssl; } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/be/jeffcheasey88/peeratcode/Main.java b/src/be/jeffcheasey88/peeratcode/Main.java index 878c686..716a12e 100644 --- a/src/be/jeffcheasey88/peeratcode/Main.java +++ b/src/be/jeffcheasey88/peeratcode/Main.java @@ -12,13 +12,20 @@ import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSocket; +import org.jose4j.jwa.AlgorithmConstraints.ConstraintType; +import org.jose4j.jwk.JsonWebKey; +import org.jose4j.jwk.PublicJsonWebKey; import org.jose4j.jwk.RsaJsonWebKey; import org.jose4j.jwk.RsaJwkGenerator; import org.jose4j.jws.AlgorithmIdentifiers; import org.jose4j.jws.JsonWebSignature; import org.jose4j.jwt.JwtClaims; +import org.jose4j.jwt.consumer.ErrorCodes; +import org.jose4j.jwt.consumer.InvalidJwtException; +import org.jose4j.jwt.consumer.JwtConsumer; +import org.jose4j.jwt.consumer.JwtConsumerBuilder; +import org.jose4j.lang.JoseException; -import be.jeffcheasey88.peeratcode.model.User; import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; import be.jeffcheasey88.peeratcode.routes.ChapterElement; import be.jeffcheasey88.peeratcode.routes.ChapterList; @@ -32,12 +39,81 @@ import be.jeffcheasey88.peeratcode.webserver.HttpUtil; import be.jeffcheasey88.peeratcode.webserver.HttpWriter; import be.jeffcheasey88.peeratcode.webserver.Response; import be.jeffcheasey88.peeratcode.webserver.Router; +import be.jeffcheasey88.peeratcode.webserver.User; public class Main { // Define SSL Protocol parameters - public static void main(String[] args) throws Exception { + public static void main(String[] args) throws Exception { Configuration config = new Configuration("config.txt"); config.load(); + + /*try + { + JwtClaims claims = new JwtClaims(); + claims.setIssuer("Issuer"); // who creates the token and signs it + claims.setAudience("Audience"); // to whom the token is intended to be sent + claims.setExpirationTimeMinutesInTheFuture(10); // time when the token will expire (10 minutes from now) + claims.setGeneratedJwtId(); // a unique identifier for the token + claims.setIssuedAtToNow(); // when the token was issued/created (now) + claims.setNotBeforeMinutesInThePast(2); // time before which the token is not yet valid (2 minutes ago) + + claims.setClaim("username","USERNAME"); + + JsonWebSignature jws = new JsonWebSignature(); + + jws.setPayload(claims.toJson()); + + jws.setKey(rsaJsonWebKey.getPrivateKey()); + + jws.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId()); + + jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256); + + String jwt = jws.getCompactSerialization(); + + System.out.println("jwt token = " + jwt); + + + JwtConsumer jwtConsumer = new JwtConsumerBuilder() + .setRequireExpirationTime() // the JWT must have an expiration time + .setAllowedClockSkewInSeconds(30) // allow some leeway in validating time based claims to account for clock skew + .setRequireSubject() // the JWT must have a subject claim + .setExpectedIssuer("Issuer") // whom the JWT needs to have been issued by + .setExpectedAudience("Audience") // to whom the JWT is intended for + .setVerificationKey(rsaJsonWebKey.getKey()) // verify the signature with the public key + .setJwsAlgorithmConstraints( // only allow the expected signature algorithm(s) in the given context + ConstraintType.PERMIT, AlgorithmIdentifiers.RSA_USING_SHA256) // which is only RS256 here + .build(); // create the JwtConsumer instance + + // Validate the JWT and process it to the Claims + JwtClaims jwtClaims = jwtConsumer.processToClaims(jwt); + System.out.println("JWT validation = " + jwtClaims); + } + catch (InvalidJwtException e) + { + // InvalidJwtException will be thrown, if the JWT failed processing or validation in anyway. + // Hopefully with meaningful explanations(s) about what went wrong. + System.out.println("Invalid JWT! " + e); + + // Programmatic access to (some) specific reasons for JWT invalidity is also possible + // should you want different error handling behavior for certain conditions. + + // Whether or not the JWT has expired being one common reason for invalidity + if (e.hasExpired()) + { + System.out.println("JWT expired"); + } + + // Or maybe the audience was invalid + if (e.hasErrorCode(ErrorCodes.AUDIENCE_INVALID)) + { + System.out.println("JWT had wrong audience"); + } + } catch (JoseException e) { + e.printStackTrace(); + }*/ + + Class.forName("com.mysql.cj.jdbc.Driver"); Router router = new Router(); @@ -84,7 +160,7 @@ public class Main { while (!server.isClosed()) { Socket socket = server.accept(); - Client client = new Client(socket, router); + Client client = new Client(socket, router, RsaJwkGenerator.generateJwk(2048)); client.start(); } } catch (Exception e) { @@ -99,7 +175,8 @@ public class Main { try (ServerSocket server = new ServerSocket(config.getTcpPort())){ while(!server.isClosed()){ Socket socket = server.accept(); - Client client = new Client(socket, router); + RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048); + Client client = new Client(socket, router, rsaJsonWebKey); client.start(); } } diff --git a/src/be/jeffcheasey88/peeratcode/model/User.java b/src/be/jeffcheasey88/peeratcode/model/User.java deleted file mode 100644 index 4a8338e..0000000 --- a/src/be/jeffcheasey88/peeratcode/model/User.java +++ /dev/null @@ -1,71 +0,0 @@ -package be.jeffcheasey88.peeratcode.model; - -import org.jose4j.jwa.AlgorithmConstraints.ConstraintType; -import org.jose4j.jwe.JsonWebEncryption; -import org.jose4j.jwk.RsaJsonWebKey; -import org.jose4j.jws.AlgorithmIdentifiers; -import org.jose4j.jwt.JwtClaims; -import org.jose4j.jwt.consumer.ErrorCodes; -import org.jose4j.jwt.consumer.InvalidJwtException; -import org.jose4j.jwt.consumer.JwtConsumer; -import org.jose4j.jwt.consumer.JwtConsumerBuilder; - -public class User { - - private final String username; - - public User(String jwt) { - new RsaJsonWebKey(); - // Use JwtConsumerBuilder to construct an appropriate JwtConsumer, which will - // be used to validate and process the JWT. - // The specific validation requirements for a JWT are context dependent, however, - // it is typically advisable to require a (reasonable) expiration time, a trusted issuer, and - // an audience that identifies your system as the intended recipient. - // If the JWT is encrypted too, you need only provide a decryption key or - // decryption key resolver to the builder. - JwtConsumer jwtConsumer = new JwtConsumerBuilder() - .setRequireExpirationTime() // the JWT must have an expiration time - .setAllowedClockSkewInSeconds(30) // allow some leeway in validating time based claims to account for clock skew - .setRequireSubject() // the JWT must have a subject claim - .setExpectedIssuer("Issuer") // whom the JWT needs to have been issued by - .setExpectedAudience("Audience") // to whom the JWT is intended for - .setVerificationKey(rsaJsonWebKey.getKey()) // verify the signature with the public key - .setJwsAlgorithmConstraints( // only allow the expected signature algorithm(s) in the given context - ConstraintType.PERMIT, AlgorithmIdentifiers.RSA_USING_SHA256) // which is only RS256 here - .build(); // create the JwtConsumer instance - - try - { - // Validate the JWT and process it to the Claims - JwtClaims jwtClaims = jwtConsumer.processToClaims(jwt); - System.out.println("JWT validation succeeded! " + jwtClaims); - } - catch (InvalidJwtException e) - { - // InvalidJwtException will be thrown, if the JWT failed processing or validation in anyway. - // Hopefully with meaningful explanations(s) about what went wrong. - System.out.println("Invalid JWT! " + e); - - // Programmatic access to (some) specific reasons for JWT invalidity is also possible - // should you want different error handling behavior for certain conditions. - - // Whether or not the JWT has expired being one common reason for invalidity - if (e.hasExpired()) - { - System.out.println("JWT expired at " + e.getJwtContext().getJwtClaims().getExpirationTime()); - } - - // Or maybe the audience was invalid - if (e.hasErrorCode(ErrorCodes.AUDIENCE_INVALID)) - { - System.out.println("JWT had wrong audience: " + e.getJwtContext().getJwtClaims().getAudience()); - } - } - - this.username = username; - } - - public String getUsername() { - return username; - } -} \ No newline at end of file diff --git a/src/be/jeffcheasey88/peeratcode/routes/ChapterElement.java b/src/be/jeffcheasey88/peeratcode/routes/ChapterElement.java index 2cf8904..1163f25 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/ChapterElement.java +++ b/src/be/jeffcheasey88/peeratcode/routes/ChapterElement.java @@ -2,12 +2,13 @@ package be.jeffcheasey88.peeratcode.routes; import be.jeffcheasey88.peeratcode.model.Chapter; import be.jeffcheasey88.peeratcode.model.Puzzle; -import be.jeffcheasey88.peeratcode.model.User; import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; import be.jeffcheasey88.peeratcode.webserver.HttpReader; import be.jeffcheasey88.peeratcode.webserver.HttpUtil; import be.jeffcheasey88.peeratcode.webserver.HttpWriter; import be.jeffcheasey88.peeratcode.webserver.Response; +import be.jeffcheasey88.peeratcode.webserver.User; + import org.json.simple.JSONArray; import org.json.simple.JSONObject; diff --git a/src/be/jeffcheasey88/peeratcode/routes/ChapterList.java b/src/be/jeffcheasey88/peeratcode/routes/ChapterList.java index f031504..de00de9 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/ChapterList.java +++ b/src/be/jeffcheasey88/peeratcode/routes/ChapterList.java @@ -1,12 +1,13 @@ package be.jeffcheasey88.peeratcode.routes; import be.jeffcheasey88.peeratcode.model.Chapter; -import be.jeffcheasey88.peeratcode.model.User; import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; import be.jeffcheasey88.peeratcode.webserver.HttpReader; import be.jeffcheasey88.peeratcode.webserver.HttpUtil; import be.jeffcheasey88.peeratcode.webserver.HttpWriter; import be.jeffcheasey88.peeratcode.webserver.Response; +import be.jeffcheasey88.peeratcode.webserver.User; + import org.json.simple.JSONArray; import org.json.simple.JSONObject; diff --git a/src/be/jeffcheasey88/peeratcode/routes/Login.java b/src/be/jeffcheasey88/peeratcode/routes/Login.java index 16dbd49..e65ec49 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/Login.java +++ b/src/be/jeffcheasey88/peeratcode/routes/Login.java @@ -5,12 +5,12 @@ import java.util.regex.Pattern; import org.json.simple.JSONObject; -import be.jeffcheasey88.peeratcode.model.User; import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; import be.jeffcheasey88.peeratcode.webserver.HttpReader; import be.jeffcheasey88.peeratcode.webserver.HttpUtil; import be.jeffcheasey88.peeratcode.webserver.HttpWriter; import be.jeffcheasey88.peeratcode.webserver.Response; +import be.jeffcheasey88.peeratcode.webserver.User; public class Login implements Response { diff --git a/src/be/jeffcheasey88/peeratcode/routes/PuzzleElement.java b/src/be/jeffcheasey88/peeratcode/routes/PuzzleElement.java index 1f1262f..c25ea50 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/PuzzleElement.java +++ b/src/be/jeffcheasey88/peeratcode/routes/PuzzleElement.java @@ -7,12 +7,12 @@ import java.util.regex.Pattern; import org.json.simple.JSONObject; import be.jeffcheasey88.peeratcode.model.Puzzle; -import be.jeffcheasey88.peeratcode.model.User; import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; import be.jeffcheasey88.peeratcode.webserver.HttpReader; import be.jeffcheasey88.peeratcode.webserver.HttpUtil; import be.jeffcheasey88.peeratcode.webserver.HttpWriter; import be.jeffcheasey88.peeratcode.webserver.Response; +import be.jeffcheasey88.peeratcode.webserver.User; public class PuzzleElement implements Response { diff --git a/src/be/jeffcheasey88/peeratcode/routes/Register.java b/src/be/jeffcheasey88/peeratcode/routes/Register.java index 82e6d2e..ed8005d 100644 --- a/src/be/jeffcheasey88/peeratcode/routes/Register.java +++ b/src/be/jeffcheasey88/peeratcode/routes/Register.java @@ -5,12 +5,12 @@ import java.util.regex.Pattern; import org.json.simple.JSONObject; -import be.jeffcheasey88.peeratcode.model.User; import be.jeffcheasey88.peeratcode.repository.DatabaseRepository; import be.jeffcheasey88.peeratcode.webserver.HttpReader; import be.jeffcheasey88.peeratcode.webserver.HttpUtil; import be.jeffcheasey88.peeratcode.webserver.HttpWriter; import be.jeffcheasey88.peeratcode.webserver.Response; +import be.jeffcheasey88.peeratcode.webserver.User; public class Register implements Response { diff --git a/src/be/jeffcheasey88/peeratcode/webserver/Client.java b/src/be/jeffcheasey88/peeratcode/webserver/Client.java index 577b9e8..4e6b136 100644 --- a/src/be/jeffcheasey88/peeratcode/webserver/Client.java +++ b/src/be/jeffcheasey88/peeratcode/webserver/Client.java @@ -3,20 +3,22 @@ package be.jeffcheasey88.peeratcode.webserver; import java.net.Socket; import java.util.Arrays; -import be.jeffcheasey88.peeratcode.model.User; +import org.jose4j.jwk.RsaJsonWebKey; public class Client extends Thread{ private HttpReader reader; private HttpWriter writer; private Router router; + private RsaJsonWebKey key; - public Client(Socket socket, Router router) throws Exception{ + public Client(Socket socket, Router router, RsaJsonWebKey key) throws Exception{ this.reader = new HttpReader(socket); this.writer = new HttpWriter(socket); this.router = router; + this.key = key; } - + @Override public void run(){ try { diff --git a/src/be/jeffcheasey88/peeratcode/webserver/Response.java b/src/be/jeffcheasey88/peeratcode/webserver/Response.java index c6acfac..9b0d3ea 100644 --- a/src/be/jeffcheasey88/peeratcode/webserver/Response.java +++ b/src/be/jeffcheasey88/peeratcode/webserver/Response.java @@ -3,8 +3,6 @@ package be.jeffcheasey88.peeratcode.webserver; import java.util.regex.Matcher; import java.util.regex.Pattern; -import be.jeffcheasey88.peeratcode.model.User; - public interface Response{ void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception ; diff --git a/src/be/jeffcheasey88/peeratcode/webserver/Router.java b/src/be/jeffcheasey88/peeratcode/webserver/Router.java index ca48e59..4bc9882 100644 --- a/src/be/jeffcheasey88/peeratcode/webserver/Router.java +++ b/src/be/jeffcheasey88/peeratcode/webserver/Router.java @@ -4,8 +4,6 @@ import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; -import be.jeffcheasey88.peeratcode.model.User; - public class Router{ private List responses;