JWT refractor

This commit is contained in:
jeffcheasey88 2023-02-24 00:08:17 +01:00
parent c915a96535
commit 64a88f7282
9 changed files with 142 additions and 43 deletions

View file

@ -48,7 +48,7 @@ public class Main {
Class.forName("com.mysql.cj.jdbc.Driver");
Router router = new Router();
Router router = new Router(new DatabaseRepository(config));
router.setDefault(new Response(){
@ -66,19 +66,19 @@ public class Main {
}
});
initRoutes(router, new DatabaseRepository(config));
initRoutes(router);
startWebServer(config, router);
}
private static void initRoutes(Router router, DatabaseRepository repo) {
router.register(new ChapterElement(repo));
router.register(new ChapterList(repo));
router.register(new PuzzleElement(repo));
router.register(new Register(repo));
router.register(new Login(repo));
router.register(new Result(repo));
router.register(new PuzzleResponse(repo));
private static void initRoutes(Router router) {
router.register(new ChapterElement(router.getDataBase()));
router.register(new ChapterList(router.getDataBase()));
router.register(new PuzzleElement(router.getDataBase()));
router.register(new Register(router.getDataBase(), router));
router.register(new Login(router.getDataBase(), router));
router.register(new Result(router.getDataBase()));
router.register(new PuzzleResponse(router.getDataBase()));
}
private static void startWebServer(Configuration config, Router router) throws IOException {

View file

@ -0,0 +1,45 @@
package be.jeffcheasey88.peeratcode.model;
public class Player {
private String pseudo;
private String email;
private String firstname;
private String lastname;
private String description;
private String sgroup;
public Player(String pseudo, String email, String firstname, String lastname, String description, String sgroup){
this.pseudo = pseudo;
this.email = email;
this.firstname = firstname;
this.lastname = lastname;
this.description = description;
this.sgroup = sgroup;
}
public String getPseudo(){
return this.pseudo;
}
public String getEmail(){
return this.email;
}
public String getFirstname(){
return this.firstname;
}
public String getLastname(){
return this.lastname;
}
public String getDescription(){
return this.description;
}
public String getGroup(){
return this.sgroup;
}
}

View file

@ -1,19 +1,21 @@
package be.jeffcheasey88.peeratcode.repository;
import be.jeffcheasey88.peeratcode.Configuration;
import be.jeffcheasey88.peeratcode.model.Chapter;
import be.jeffcheasey88.peeratcode.model.Puzzle;
import com.password4j.Hash;
import com.password4j.Password;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import com.password4j.Hash;
import com.password4j.Password;
import be.jeffcheasey88.peeratcode.Configuration;
import be.jeffcheasey88.peeratcode.model.Chapter;
import be.jeffcheasey88.peeratcode.model.Puzzle;
public class DatabaseRepository {
private static final String SPECIFIC_PUZZLE_QUERY = "SELECT * FROM puzzles WHERE id_puzzle = ?";
private static final String SPECIFIC_CHAPTER_QUERY = "SELECT * FROM chapters WHERE id_chapter = ?";
@ -22,7 +24,7 @@ public class DatabaseRepository {
private static final String CHECK_PSEUDO_AVAILABLE_QUERY = "SELECT * FROM players WHERE pseudo = ?";
private static final String CHECK_EMAIL_AVAILABLE_QUERY = "SELECT * FROM players WHERE email = ?";
private static final String REGISTER_QUERY = "INSERT INTO players (pseudo, email, passwd, firstname, lastname, description, sgroup, avatar) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
private static final String CHECK_PASSWORD = "SELECT passwd FROM players WHERE pseudo=?";
private static final String CHECK_PASSWORD = "SELECT id_player, passwd FROM players WHERE pseudo=?";
private static final String SCORE = "SELECT score FROM completions WHERE fk_player = ? AND fk_puzzle = ?";
private static final String GET_PUZZLE_SOLUTION = "SELECT soluce FROM puzzles WHERE id_puzzle=?";
private static final String GET_PUZZLE_SCORE_MAX = "SELECT score_max FROM puzzles WHERE id_puzzle=?";
@ -192,11 +194,11 @@ public class DatabaseRepository {
* @param avatar The avatar of the user
* @return True if the user was registered, false if an error occurred
*/
public boolean register(String pseudo, String email, String password, String firstname, String lastname, String description, String sgroup, String avatar) {
public int register(String pseudo, String email, String password, String firstname, String lastname, String description, String sgroup, String avatar) {
Hash hash = Password.hash(password).withArgon2();
try {
ensureConnection();
PreparedStatement statement = con.prepareStatement(REGISTER_QUERY);
PreparedStatement statement = con.prepareStatement(REGISTER_QUERY, Statement.RETURN_GENERATED_KEYS);
statement.setString(1, pseudo);
statement.setString(2, email);
statement.setString(3, hash.getResult());
@ -205,11 +207,14 @@ public class DatabaseRepository {
statement.setString(6, description);
statement.setString(7, sgroup);
statement.setString(8, avatar);
return statement.executeUpdate() == 1;
if(statement.executeUpdate() == 1){
ResultSet inserted = statement.getGeneratedKeys();
if(inserted.next()) return inserted.getInt("id_player");
}
} catch (SQLException e) {
e.printStackTrace();
}
return false;
return -1;
}
/**
@ -217,9 +222,9 @@ public class DatabaseRepository {
*
* @param username The username of the user
* @param password The password of the user
* @return True if the user's information are correct, false otherwise (or if an error occurred)
* @return id the id of the user, -1 if not login successefuly
*/
public boolean login(String username, String password) {
public int login(String username, String password) {
try {
ensureConnection();
PreparedStatement statement = con.prepareStatement(CHECK_PASSWORD);
@ -227,12 +232,11 @@ public class DatabaseRepository {
ResultSet result = statement.executeQuery();
if (result.next()) {
String hashedPassword = result.getString("passwd");
return Password.check(password, hashedPassword).withArgon2();
if(Password.check(password, hashedPassword).withArgon2()) return result.getInt("id_player");
}
} catch (SQLException e) {
e.printStackTrace();
}
return false;
return -1;
}
public byte[] getPuzzleSolution(int puzzleId) {

View file

@ -3,6 +3,10 @@ package be.jeffcheasey88.peeratcode.routes;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.json.simple.JSONObject;
import be.jeffcheasey88.peeratcode.repository.DatabaseRepository;
@ -10,14 +14,17 @@ 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.Router;
import be.jeffcheasey88.peeratcode.webserver.User;
public class Login implements Response {
private final DatabaseRepository databaseRepo;
private DatabaseRepository databaseRepo;
private Router router;
public Login(DatabaseRepository databaseRepo) {
public Login(DatabaseRepository databaseRepo, Router router){
this.databaseRepo = databaseRepo;
this.router = router;
}
@Override
@ -27,8 +34,11 @@ public class Login implements Response {
if (informations != null) {
String pseudo = (String) informations.get("pseudo");
String password = (String) informations.get("passwd");
if (databaseRepo.login(pseudo, password)) {
HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *");
int id;
if ((id = databaseRepo.login(pseudo, password)) >= 0){
HttpUtil.responseHeaders(writer, 200,
"Access-Control-Allow-Origin: *",
"Authorization: Bearer "+this.router.createAuthUser(id));
return;
}
}

View file

@ -22,8 +22,12 @@ public class PuzzleResponse implements Response {
@Override
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {
HttpUtil.skipHeaders(reader);
if(user == null){
HttpUtil.responseHeaders(writer, 403, "Access-Control-Allow-Origin: *");
return;
}
HttpUtil.skipHeaders(reader);
int puzzleId = Integer.parseInt(matcher.group(1));
byte[] response;
byte[] fileName;

View file

@ -10,14 +10,17 @@ 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.Router;
import be.jeffcheasey88.peeratcode.webserver.User;
public class Register implements Response {
private final DatabaseRepository databaseRepo;
private DatabaseRepository databaseRepo;
private Router router;
public Register(DatabaseRepository databaseRepo) {
public Register(DatabaseRepository databaseRepo, Router router) {
this.databaseRepo = databaseRepo;
this.router = router;
}
@Override
@ -45,8 +48,11 @@ public class Register implements Response {
boolean pseudoAvailable = databaseRepo.checkPseudoAvailability(pseudo);
boolean emailAvailable = databaseRepo.checkEmailAvailability(email);
if (pseudoAvailable && emailAvailable) {
if (databaseRepo.register(pseudo, email, password, firstname, lastname, description, group, avatar)){
HttpUtil.responseHeaders(writer, 200, "Access-Control-Allow-Origin: *");
int id;
if ((id = databaseRepo.register(pseudo, email, password, firstname, lastname, description, group, avatar)) >= 0){
HttpUtil.responseHeaders(writer, 200,
"Access-Control-Allow-Origin: *",
"Authorization: Bearer "+this.router.createAuthUser(id));
return;
}
} else {

View file

@ -20,9 +20,14 @@ public class Result implements Response{
@Override
public void exec(Matcher matcher, User user, HttpReader reader, HttpWriter writer) throws Exception {
if(user == null){
HttpUtil.responseHeaders(writer, 403, "Access-Control-Allow-Origin: *");
return;
}
int puzzle = Integer.parseInt(matcher.group(1));
int score = this.repo.getScore(0, puzzle);
int score = this.repo.getScore(user.getId(), puzzle);
if(score < 0) {
HttpUtil.responseHeaders(writer, 425, "Access-Control-Allow-Origin: *");
}else{

View file

@ -6,18 +6,30 @@ import java.util.regex.Matcher;
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.lang.JoseException;
import be.jeffcheasey88.peeratcode.repository.DatabaseRepository;
public class Router{
private List<Response> responses;
private Response noFileFound;
private RsaJsonWebKey rsaJsonWebKey;
private DatabaseRepository repo;
public Router() throws Exception{
public Router(DatabaseRepository repo) throws Exception{
this.repo = repo;
this.responses = new ArrayList<>();
this.rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
}
public DatabaseRepository getDataBase(){
return this.repo;
}
public void register(Response response){
this.responses.add(response);
}
@ -42,4 +54,23 @@ public class Router{
public RsaJsonWebKey getWebKey(){
return this.rsaJsonWebKey;
}
public String createAuthUser(int id) throws JoseException{
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("id", id);
JsonWebSignature jws = new JsonWebSignature();
jws.setPayload(claims.toJson());
jws.setKey(rsaJsonWebKey.getPrivateKey());
jws.setKeyIdHeaderValue(rsaJsonWebKey.getKeyId());
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
return jws.getCompactSerialization();
}
}

View file

@ -4,18 +4,12 @@ import org.jose4j.jwt.JwtClaims;
public class User {
private String username;
private int id;
public User(JwtClaims jwtClaims){
this.username = (String) jwtClaims.getClaimValue("username");
this.id = (int) jwtClaims.getClaimValue("id");
}
public String getUsername(){
return username;
}
public int getId(){
return this.id;
}