[DEV] rework authentication
This commit is contained in:
parent
12231762d3
commit
dc8cae5150
2
pom.xml
2
pom.xml
@ -2,7 +2,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>kangaroo-and-rabbit</groupId>
|
||||
<artifactId>archidata</artifactId>
|
||||
<version>0.3.4</version>
|
||||
<version>0.3.5</version>
|
||||
<properties>
|
||||
<jersey.version>3.1.1</jersey.version>
|
||||
<jaxb.version>2.3.1</jaxb.version>
|
||||
|
@ -1,6 +1,4 @@
|
||||
package org.kar.archidata;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class MigrationSystem {
|
||||
|
@ -283,7 +283,7 @@ public class SqlWrapper {
|
||||
// real add in the BDD:
|
||||
try {
|
||||
String tableName = getTableName(clazz);
|
||||
boolean createIfNotExist = clazz.getDeclaredAnnotationsByType(SQLIfNotExists.class).length != 0;
|
||||
//boolean createIfNotExist = clazz.getDeclaredAnnotationsByType(SQLIfNotExists.class).length != 0;
|
||||
StringBuilder query = new StringBuilder();
|
||||
query.append("INSERT INTO ");
|
||||
query.append(tableName);
|
||||
@ -455,7 +455,7 @@ public class SqlWrapper {
|
||||
// real add in the BDD:
|
||||
try {
|
||||
String tableName = getTableName(clazz);
|
||||
boolean createIfNotExist = clazz.getDeclaredAnnotationsByType(SQLIfNotExists.class).length != 0;
|
||||
//boolean createIfNotExist = clazz.getDeclaredAnnotationsByType(SQLIfNotExists.class).length != 0;
|
||||
StringBuilder query = new StringBuilder();
|
||||
query.append("UPDATE ");
|
||||
query.append(tableName);
|
||||
@ -463,7 +463,6 @@ public class SqlWrapper {
|
||||
|
||||
boolean firstField = true;
|
||||
Field primaryKeyField = null;
|
||||
int count = 0;
|
||||
for (Field elem : clazz.getFields()) {
|
||||
boolean primaryKey = elem.getDeclaredAnnotationsByType(SQLPrimaryKey.class).length != 0;
|
||||
if (primaryKey) {
|
||||
@ -489,7 +488,6 @@ public class SqlWrapper {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
if (firstField) {
|
||||
firstField = false;
|
||||
} else {
|
||||
@ -551,7 +549,6 @@ public class SqlWrapper {
|
||||
ps.setString(iii++, dataTmp);
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
ps.setLong(iii++, id);
|
||||
// execute the request
|
||||
@ -693,6 +690,7 @@ public class SqlWrapper {
|
||||
stmt.executeUpdate(querry);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> List<T> getsWhere(Class<T> clazz, List<WhereCondition> condition, String orderBy, boolean full, Integer linit) throws Exception {
|
||||
DBEntry entry = new DBEntry(GlobalConfiguration.dbConfig);
|
||||
List<T> outs = new ArrayList<>();
|
||||
@ -774,7 +772,7 @@ public class SqlWrapper {
|
||||
if (!full && createTime) {
|
||||
continue;
|
||||
}
|
||||
String name = elem.getName();
|
||||
//String name = elem.getName();
|
||||
boolean updateTime = elem.getDeclaredAnnotationsByType(SQLUpdateTime.class).length != 0;
|
||||
if (!full && updateTime) {
|
||||
continue;
|
||||
@ -806,7 +804,7 @@ public class SqlWrapper {
|
||||
}
|
||||
}
|
||||
if (primaryKeyField != null) {
|
||||
return getWhere(clazz, primaryKeyField.getName(), "=", id);
|
||||
return SqlWrapper.getWhere(clazz, List.of(new WhereCondition(primaryKeyField.getName(), "=", id)), false);
|
||||
}
|
||||
throw new Exception("Missing primary Key...");
|
||||
}
|
||||
@ -828,7 +826,7 @@ public class SqlWrapper {
|
||||
// real add in the BDD:
|
||||
try {
|
||||
String tableName = getTableName(clazz);
|
||||
boolean createIfNotExist = clazz.getDeclaredAnnotationsByType(SQLIfNotExists.class).length != 0;
|
||||
//boolean createIfNotExist = clazz.getDeclaredAnnotationsByType(SQLIfNotExists.class).length != 0;
|
||||
StringBuilder query = new StringBuilder();
|
||||
query.append("SELECT ");
|
||||
//query.append(tableName);
|
||||
@ -985,7 +983,7 @@ public class SqlWrapper {
|
||||
if (affectedRows == 0) {
|
||||
throw new SQLException("Creating data failed, no rows affected.");
|
||||
}
|
||||
// retreive uid inserted
|
||||
// retrieve uid inserted
|
||||
try (ResultSet generatedKeys = ps.getGeneratedKeys()) {
|
||||
if (generatedKeys.next()) {
|
||||
uniqueSQLID = generatedKeys.getLong(1);
|
||||
@ -1045,7 +1043,7 @@ public class SqlWrapper {
|
||||
return out;
|
||||
}
|
||||
/**
|
||||
* Convert the list if external Ids in a string '-' separated
|
||||
* Convert the list if external id in a string '-' separated
|
||||
* @param ids List of value (null are removed)
|
||||
* @return '-' string separated
|
||||
*/
|
||||
|
@ -229,7 +229,7 @@ public class DataResource {
|
||||
public Response uploadFile(@Context SecurityContext sc, @FormDataParam("file") InputStream fileInputStream, @FormDataParam("file") FormDataContentDisposition fileMetaData) {
|
||||
GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
System.out.println("===================================================");
|
||||
System.out.println("== DATA uploadFile " + (gc==null?"null":gc.user));
|
||||
System.out.println("== DATA uploadFile " + (gc==null?"null":gc.userByToken));
|
||||
System.out.println("===================================================");
|
||||
//public NodeSmall uploadFile(final FormDataMultiPart form) {
|
||||
System.out.println("Upload file: ");
|
||||
@ -252,7 +252,7 @@ public class DataResource {
|
||||
public Response retriveDataId(@Context SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) String token, @HeaderParam("Range") String range, @PathParam("id") Long id) throws Exception {
|
||||
GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
//System.out.println("===================================================");
|
||||
System.out.println("== DATA retriveDataId ? id=" + id + " user=" + (gc==null?"null":gc.user));
|
||||
System.out.println("== DATA retriveDataId ? id=" + id + " user=" + (gc==null?"null":gc.userByToken));
|
||||
//System.out.println("===================================================");
|
||||
Data value = getSmall(id);
|
||||
if (value == null) {
|
||||
@ -344,7 +344,7 @@ public class DataResource {
|
||||
public Response retriveDataFull(@Context SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) String token, @HeaderParam("Range") String range, @PathParam("id") Long id, @PathParam("name") String name) throws Exception {
|
||||
GenericContext gc = (GenericContext) sc.getUserPrincipal();
|
||||
//System.out.println("===================================================");
|
||||
System.out.println("== DATA retriveDataFull ? id=" + id + " user=" + (gc==null?"null":gc.user));
|
||||
System.out.println("== DATA retriveDataFull ? id=" + id + " user=" + (gc==null?"null":gc.userByToken));
|
||||
//System.out.println("===================================================");
|
||||
Data value = getSmall(id);
|
||||
if (value == null) {
|
||||
|
@ -28,6 +28,7 @@ import com.nimbusds.jwt.JWTClaimsSet;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
// https://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey
|
||||
// https://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey/45814178#45814178
|
||||
@ -39,11 +40,19 @@ import java.util.Map.Entry;
|
||||
public class AuthenticationFilter implements ContainerRequestFilter {
|
||||
@Context
|
||||
private ResourceInfo resourceInfo;
|
||||
protected final String applicationName;
|
||||
|
||||
private static final String AUTHENTICATION_SCHEME = "Yota";
|
||||
private static final String AUTHENTICATION_TOKEN_SCHEME = "Zota";
|
||||
|
||||
@Override
|
||||
|
||||
|
||||
public AuthenticationFilter(String applicationName) {
|
||||
super();
|
||||
this.applicationName = applicationName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filter(ContainerRequestContext requestContext) throws IOException {
|
||||
/*
|
||||
System.out.println("-----------------------------------------------------");
|
||||
@ -95,38 +104,23 @@ public class AuthenticationFilter implements ContainerRequestFilter {
|
||||
abortWithUnauthorized(requestContext);
|
||||
return;
|
||||
}
|
||||
User user = null;
|
||||
UserByToken userByToken = null;
|
||||
if (isJwtToken) {
|
||||
// Extract the token from the Authorization header (Remove "Yota ")
|
||||
String token = authorizationHeader.substring(AUTHENTICATION_SCHEME.length()).trim();
|
||||
//System.out.println("token: " + token);
|
||||
try {
|
||||
user = validateJwtToken(token);
|
||||
userByToken = validateJwtToken(token);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Fail to validate token: " + e.getMessage());
|
||||
abortWithUnauthorized(requestContext);
|
||||
return;
|
||||
}
|
||||
if (user == null) {
|
||||
if (userByToken == null) {
|
||||
System.out.println("get a NULL user ...");
|
||||
abortWithUnauthorized(requestContext);
|
||||
return;
|
||||
}
|
||||
// We are in transition phase the user element will be removed
|
||||
userByToken = new UserByToken();
|
||||
userByToken.id = user.id;
|
||||
userByToken.name = user.login;
|
||||
userByToken.parentId = null;
|
||||
userByToken.type = UserByToken.TYPE_USER;
|
||||
if (user.removed || user.blocked) {
|
||||
userByToken.type = null;
|
||||
} else if (user.admin) {
|
||||
userByToken.right.put("ADMIN", true);
|
||||
userByToken.right.put("USER", true);
|
||||
} else {
|
||||
userByToken.right.put("USER", true);
|
||||
}
|
||||
} else {
|
||||
// Extract the token from the Authorization header (Remove "Zota ")
|
||||
String token = authorizationHeader.substring(AUTHENTICATION_TOKEN_SCHEME.length()).trim();
|
||||
@ -147,7 +141,7 @@ public class AuthenticationFilter implements ContainerRequestFilter {
|
||||
}
|
||||
// create the security context model:
|
||||
String scheme = requestContext.getUriInfo().getRequestUri().getScheme();
|
||||
MySecurityContext userContext = new MySecurityContext(user, userByToken, scheme);
|
||||
MySecurityContext userContext = new MySecurityContext(userByToken, scheme);
|
||||
// retrieve the allowed right:
|
||||
RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
|
||||
List<String> roles = Arrays.asList(rolesAnnotation.value());
|
||||
@ -196,11 +190,11 @@ public class AuthenticationFilter implements ContainerRequestFilter {
|
||||
}
|
||||
|
||||
protected UserByToken validateToken(String authorization) throws Exception {
|
||||
System.out.println("dsfgsdgsdfgsdgf");
|
||||
System.out.println("Must be Override by the application implmentation, otherwise it dose not work");
|
||||
return null;
|
||||
}
|
||||
// must be override to be good implemenres
|
||||
protected User validateJwtToken(String authorization) throws Exception {
|
||||
// must be override to be good implementation
|
||||
protected UserByToken validateJwtToken(String authorization) throws Exception {
|
||||
System.out.println(" validate token : " + authorization);
|
||||
JWTClaimsSet ret = JWTWrapper.validateToken(authorization, "KarAuth", null);
|
||||
// check the token is valid !!! (signed and coherent issuer...
|
||||
@ -211,7 +205,21 @@ public class AuthenticationFilter implements ContainerRequestFilter {
|
||||
// check userID
|
||||
String userUID = ret.getSubject();
|
||||
long id = Long.parseLong(userUID);
|
||||
System.out.println("request user: '" + userUID + "'");
|
||||
return UserDB.getUserOrCreate(id, (String)ret.getClaim("login") );
|
||||
UserByToken user = new UserByToken();
|
||||
user.id = id;
|
||||
user.name = (String)ret.getClaim("login");
|
||||
user.type = UserByToken.TYPE_USER;
|
||||
Object rowRight = ret.getClaim("right");
|
||||
if (rowRight != null) {
|
||||
Map<String, Map<String,Object>> rights = (Map<String, Map<String,Object>>) ret.getClaim("right");
|
||||
if (rights.containsKey(this.applicationName)) {
|
||||
user.right = rights.get(this.applicationName);
|
||||
} else {
|
||||
System.out.println("Connect with no right for this application '" + this.applicationName + "' full Right='" + rights + "'");
|
||||
}
|
||||
}
|
||||
System.out.println("request user: '" + userUID + "' right: '" + user.right + "' row='" +rowRight + "'");
|
||||
return user;
|
||||
//return UserDB.getUserOrCreate(id, (String)ret.getClaim("login") );
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,22 @@
|
||||
package org.kar.archidata.filter;
|
||||
|
||||
import org.kar.archidata.model.User;
|
||||
import org.kar.archidata.model.UserByToken;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
public class GenericContext implements Principal {
|
||||
|
||||
public User user;
|
||||
public UserByToken userByToken;
|
||||
|
||||
public GenericContext(User user, UserByToken userByToken) {
|
||||
this.user = user;
|
||||
public GenericContext(UserByToken userByToken) {
|
||||
this.userByToken = userByToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
if (user == null) {
|
||||
if (this.userByToken == null) {
|
||||
return "???";
|
||||
}
|
||||
return user.login;
|
||||
return this.userByToken.name;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package org.kar.archidata.filter;
|
||||
|
||||
|
||||
import org.kar.archidata.model.User;
|
||||
import org.kar.archidata.model.UserByToken;
|
||||
|
||||
import jakarta.ws.rs.core.SecurityContext;
|
||||
@ -13,8 +11,8 @@ class MySecurityContext implements SecurityContext {
|
||||
private final GenericContext contextPrincipale;
|
||||
private final String sheme;
|
||||
|
||||
public MySecurityContext(User user, UserByToken userByToken, String sheme) {
|
||||
this.contextPrincipale = new GenericContext(user, userByToken);
|
||||
public MySecurityContext(UserByToken userByToken, String sheme) {
|
||||
this.contextPrincipale = new GenericContext(userByToken);
|
||||
this.sheme = sheme;
|
||||
}
|
||||
|
||||
@ -25,18 +23,11 @@ class MySecurityContext implements SecurityContext {
|
||||
|
||||
@Override
|
||||
public boolean isUserInRole(String role) {
|
||||
if (contextPrincipale.user != null) {
|
||||
if (role.contentEquals("ADMIN")) {
|
||||
return contextPrincipale.user.admin == true;
|
||||
}
|
||||
if (role.contentEquals("USER")) {
|
||||
// if not an admin, this is a user...
|
||||
return true; //contextPrincipale.user.admin == false;
|
||||
}
|
||||
}
|
||||
if (contextPrincipale.userByToken != null) {
|
||||
Boolean value = this.contextPrincipale.userByToken.right.get(role);
|
||||
return value == true;
|
||||
Object value = this.contextPrincipale.userByToken.right.get(role);
|
||||
if (value instanceof Boolean ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -48,9 +39,6 @@ class MySecurityContext implements SecurityContext {
|
||||
|
||||
@Override
|
||||
public String getAuthenticationScheme() {
|
||||
if (contextPrincipale.user != null) {
|
||||
return "Yota";
|
||||
}
|
||||
if (contextPrincipale.userByToken != null) {
|
||||
return "Zota";
|
||||
}
|
||||
|
@ -15,11 +15,14 @@ CREATE TABLE `user` (
|
||||
*/
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
import org.kar.archidata.annotation.SQLComment;
|
||||
import org.kar.archidata.annotation.SQLDefault;
|
||||
import org.kar.archidata.annotation.SQLIfNotExists;
|
||||
import org.kar.archidata.annotation.SQLLimitSize;
|
||||
import org.kar.archidata.annotation.SQLNotNull;
|
||||
import org.kar.archidata.annotation.SQLTableLinkGeneric;
|
||||
import org.kar.archidata.annotation.SQLTableName;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
@ -11,9 +11,9 @@ public class UserByToken {
|
||||
public Integer type = null;
|
||||
|
||||
public Long id = null;
|
||||
public Long parentId = null;
|
||||
public Long parentId = null; // FOr application, this is the id of the application, and of user token, this is the USERID
|
||||
public String name = null;
|
||||
// Right map
|
||||
public Map<String, Boolean> right = new HashMap<>();
|
||||
public Map<String, Object> right = new HashMap<>();
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@ -72,11 +74,14 @@ public class JWTWrapper {
|
||||
System.out.println("GET JWT validator token not worked");
|
||||
}
|
||||
|
||||
public static void initLocalToken() throws Exception{
|
||||
public static void initLocalToken(String baseUUID) throws Exception{
|
||||
// RSA signatures require a public and private RSA key pair, the public key
|
||||
// must be made known to the JWS recipient in order to verify the signatures
|
||||
try {
|
||||
String generatedStringForKey = UUID.randomUUID().toString();
|
||||
String generatedStringForKey = baseUUID;
|
||||
if (generatedStringForKey == null) {
|
||||
generatedStringForKey = UUID.randomUUID().toString();
|
||||
}
|
||||
rsaJWK = new RSAKeyGenerator(2048).keyID(generatedStringForKey).generate();
|
||||
rsaPublicJWK = rsaJWK.toPublicJWK();
|
||||
//System.out.println("RSA key (all): " + rsaJWK.toJSONString());
|
||||
@ -121,7 +126,7 @@ public class JWTWrapper {
|
||||
* @param timeOutInMunites Expiration of the token.
|
||||
* @return the encoded token
|
||||
*/
|
||||
public static String generateJWToken(long userID, String userLogin, String isuer, String application, int timeOutInMunites) {
|
||||
public static String generateJWToken(long userID, String userLogin, String isuer, String application, Map<String, Object> rights, int timeOutInMunites) {
|
||||
if (rsaJWK == null) {
|
||||
System.out.println("JWT private key is not present !!!");
|
||||
return null;
|
||||
@ -134,17 +139,20 @@ public class JWTWrapper {
|
||||
*/
|
||||
try {
|
||||
// Create RSA-signer with the private key
|
||||
JWSSigner signer = new RSASSASigner(rsaJWK);
|
||||
// Prepare JWT with claims set
|
||||
JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
|
||||
JWSSigner signer = new RSASSASigner(rsaJWK);
|
||||
JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder()
|
||||
.subject(Long.toString(userID))
|
||||
.claim("login", userLogin)
|
||||
.claim("application", application)
|
||||
.issuer(isuer)
|
||||
.issueTime(new Date())
|
||||
.expirationTime(new Date(new Date().getTime() - 60 * timeOutInMunites * 1000 /* millisecond */)) // Do not ask why we need a "-" here ... this have no meaning
|
||||
.build();
|
||||
|
||||
.expirationTime(new Date(new Date().getTime() - 60 * timeOutInMunites * 1000 /* millisecond */)); // Do not ask why we need a "-" here ... this have no meaning
|
||||
// add right if needed:
|
||||
if (rights != null && !rights.isEmpty()) {
|
||||
builder.claim("right", rights);
|
||||
}
|
||||
// Prepare JWT with claims set
|
||||
JWTClaimsSet claimsSet = builder.build();
|
||||
SignedJWT signedJWT = new SignedJWT(new JWSHeader.Builder(JWSAlgorithm.RS256).type(JOSEObjectType.JWT)/*.keyID(rsaJWK.getKeyID())*/.build(), claimsSet);
|
||||
|
||||
// Compute the RSA signature
|
||||
|
Loading…
x
Reference in New Issue
Block a user