Skip to content

Commit 3de0116

Browse files
committed
Merge branch 'IM-755-Give-group-information-to-services' into develop
2 parents b7f84c4 + 405664d commit 3de0116

File tree

10 files changed

+128
-528
lines changed

10 files changed

+128
-528
lines changed

api/org.integratedmodelling.klab.api/src/org/integratedmodelling/klab/api/API.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,14 @@ public static interface HUB {
332332
* Base URL path for user resources on the hub with no authentication.
333333
*/
334334
public static final String USER_BASE_ID_NOAUTH = USER_BASE_NOAUTH + "/{id}";
335+
/**
336+
* Base URL path for user resources on the hub for services
337+
*/
338+
public static final String USER_BASE_SERVICES = USER_BASE + "/services";
339+
/**
340+
* Base URL path for user resources on the hub with no authentication.
341+
*/
342+
public static final String USER_BASE_ID_SERVICES = USER_BASE_SERVICES + "/{id}";
335343
/**
336344
* Base URL path for user resources on the hub.
337345
*/
@@ -586,9 +594,10 @@ public static interface PARAMETERS {
586594

587595
public static interface LABELS {
588596
/**
589-
* Label for authorization HEADER
597+
* Label for authorization and Authentication HEADER
590598
*/
591599
public static final String AUTHORIZATION = "Authorization";
600+
public static final String AUTHENTICATION = "Authentication";
592601
}
593602

594603
public static interface CUSTOM_PROPERTY_KEYS {

klab.authentication/src/main/java/org/integratedmodelling/klab/auth/Role.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public enum Role implements GrantedAuthority {
4141

4242
public static final String NODE = "ROLE_TEMPORARY";
4343

44-
public static final String SERVICE = "ROLE_TEMPORARY";
44+
public static final String SERVICE = "ROLE_SERVICE";
4545

4646
@Override
4747
public String getAuthority() {

klab.hub/src/main/java/org/integratedmodelling/klab/hub/licenses/dto/JwtToken.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class JwtToken {
2525

2626
private static final String JWT_CLAIM_KEY_PERMISSIONS = "perms";
2727
private static final String ENGINE_AUDIENCE = "engine";
28-
private static final String SERVICE_AUDIENCE = "engine";
28+
private static final String SERVICE_AUDIENCE = "service";
2929
private static final int EXPIRATION_DAYS = 10;
3030
private static final String JWT_CLAIM_KEY_ROLES = "roles";
3131

@@ -71,7 +71,7 @@ public String createServiceJwtToken(INodeIdentity service, Set<Group> groups) {
7171
JwtClaims claims = new JwtClaims();
7272
Hub hub = Authentication.INSTANCE.getAuthenticatedIdentity(Hub.class);
7373
claims.setIssuer(hub.getName());
74-
claims.setSubject(service.getId());
74+
claims.setSubject(service.getName());
7575
claims.setAudience(SERVICE_AUDIENCE);
7676
claims.setIssuedAtToNow();
7777
claims.setExpirationTimeMinutesInTheFuture(60 * 24 * EXPIRATION_DAYS);

klab.hub/src/main/java/org/integratedmodelling/klab/hub/security/KeyManager.java

Lines changed: 0 additions & 196 deletions
This file was deleted.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package org.integratedmodelling.klab.hub.security;
2+
3+
import java.security.KeyFactory;
4+
import java.security.PublicKey;
5+
import java.security.spec.X509EncodedKeySpec;
6+
import java.util.Base64;
7+
8+
import javax.servlet.http.HttpServletRequest;
9+
10+
import org.integratedmodelling.klab.api.API;
11+
import org.integratedmodelling.klab.exceptions.KlabAuthorizationException;
12+
import org.jose4j.jwt.JwtClaims;
13+
import org.jose4j.jwt.MalformedClaimException;
14+
import org.jose4j.jwt.NumericDate;
15+
import org.jose4j.jwt.consumer.InvalidJwtException;
16+
import org.jose4j.jwt.consumer.JwtConsumer;
17+
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
18+
import org.springframework.http.HttpStatus;
19+
import org.springframework.web.client.HttpClientErrorException;
20+
21+
public enum KlabJWTAuthentication {
22+
23+
INSTANCE;
24+
25+
private static final int ALLOWED_CLOCK_SKEW_MS = 30000;
26+
27+
public void checkKlabJWT(HttpServletRequest req) throws KlabAuthorizationException {
28+
29+
String token = req.getHeader(API.HUB.LABELS.AUTHORIZATION);
30+
// we are not entering via Keycloack Beader Token, check our own JWT
31+
if (token == null) {
32+
/*
33+
* Check own jwtToken
34+
*/
35+
36+
String jwtToken =req.getHeader(API.HUB.LABELS.AUTHENTICATION);
37+
38+
if (jwtToken == null) {
39+
throw new HttpClientErrorException(HttpStatus.UNAUTHORIZED, "Not authenticated");
40+
}
41+
42+
PublicKey publicKey = null;
43+
44+
try {
45+
byte publicKeyData[] = Base64.getDecoder().decode(NetworkKeyManager.INSTANCE.getEncodedPublicKey());
46+
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyData);
47+
KeyFactory kf = KeyFactory.getInstance("RSA");
48+
publicKey = kf.generatePublic(spec);
49+
} catch (Exception e) {
50+
throw new KlabAuthorizationException("invalid public key");
51+
}
52+
53+
/*
54+
* Build a verifier for the token coming from any engine that has validated with
55+
* the authenticating hub.
56+
*/
57+
58+
/*
59+
* Build a verifier for the token coming from any engine that has validated with
60+
* the authenticating hub.
61+
*/
62+
63+
JwtConsumer jwtVerifier = new JwtConsumerBuilder().setSkipDefaultAudienceValidation()
64+
.setAllowedClockSkewInSeconds(ALLOWED_CLOCK_SKEW_MS / 1000).setVerificationKey(publicKey).build();
65+
66+
try {
67+
68+
JwtClaims claims = jwtVerifier.processToClaims(jwtToken);
69+
String username = claims.getSubject();
70+
71+
/*
72+
* Expiration time (exp) - The "exp" (expiration time) claim identifies the
73+
* expiration time on or after which the JWT must not be accepted for
74+
* processing. The value should be in NumericDate[10][11] format.
75+
*/
76+
NumericDate expirationTime = claims.getExpirationTime();
77+
long now = System.currentTimeMillis();
78+
if (expirationTime.isBefore(NumericDate.fromMilliseconds(now - ALLOWED_CLOCK_SKEW_MS))) {
79+
throw new KlabAuthorizationException("User " + username + " is using an expired authorization");
80+
}
81+
82+
83+
} catch (MalformedClaimException | InvalidJwtException e) {
84+
e.printStackTrace();
85+
throw new KlabAuthorizationException("JWT error", e);
86+
} catch (Exception e) {
87+
throw new KlabAuthorizationException("Error validating JWT", e);
88+
}
89+
}
90+
}
91+
92+
}

0 commit comments

Comments
 (0)