Skip to content

Commit 42490cd

Browse files
authored
Merge pull request #63 from scalecube/develop
Release
2 parents 5132128 + 5fda74a commit 42490cd

File tree

7 files changed

+70
-120
lines changed

7 files changed

+70
-120
lines changed

.gitignore

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,17 @@
1-
# Eclipse project files
2-
.project
3-
.classpath
4-
.settings
5-
6-
# IntelliJ IDEA project files and directories
7-
*.iml
8-
*.ipr
9-
*.iws
10-
.idea/
11-
12-
# Geany project file
13-
.geany
14-
15-
# KDevelop project file and directory
16-
.kdev4/
17-
*.kdev4
1+
# everything that starts with dot (hidden files)
2+
.*
3+
# except this file
4+
!.gitignore
5+
# except this file-extention
6+
!.*.yml
187

198
# Build targets
20-
/target
21-
*/target
22-
23-
# Report directories
24-
/reports
25-
*/reports
9+
**/target/
2610

27-
# Mac-specific directory that no other operating system needs.
28-
.DS_Store
11+
# logs and reports
12+
*.csv
13+
*.log
14+
*.zip
2915

30-
# JVM crash logs
31-
hs_err_pid*.log
16+
# IntelliJ IDEA project files and directories
17+
*.iml

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ jdk: openjdk8
88
before_install:
99
- "./src/main/scripts/ci/before-install.sh"
1010
- "./src/main/scripts/cd/before-deploy.sh"
11+
script: "mvn verify -B"
1112
after_success: "./src/main/scripts/ci/after-success.sh"
1213
deploy:
1314
- provider: script
Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,37 @@
11
package io.scalecube.security.jwt;
22

33
import io.jsonwebtoken.Claims;
4-
import io.jsonwebtoken.Jws;
4+
import io.jsonwebtoken.Header;
5+
import io.jsonwebtoken.Jwt;
56
import io.jsonwebtoken.JwtParser;
67
import io.jsonwebtoken.Jwts;
78
import io.scalecube.security.api.Profile;
9+
import java.util.Map;
810
import reactor.core.publisher.Mono;
911

1012
public final class DefaultJwtAuthenticator implements JwtAuthenticator {
1113

12-
private final JwtParser jwtParser;
14+
private final JwtKeyResolver jwtKeyResolver;
1315

1416
public DefaultJwtAuthenticator(JwtKeyResolver jwtKeyResolver) {
15-
jwtParser = Jwts.parser().setSigningKeyResolver(new DefaultSigningKeyResolver(jwtKeyResolver));
17+
this.jwtKeyResolver = jwtKeyResolver;
1618
}
1719

1820
@Override
1921
public Mono<Profile> authenticate(String token) {
20-
return Mono.just(token)
21-
.map(jwtParser::parseClaimsJws)
22-
.map(Jws<Claims>::getBody)
23-
.map(this::profileFromClaims)
24-
.onErrorMap(AuthenticationException::new);
22+
return Mono.defer(
23+
() -> {
24+
String tokenWithoutSignature = token.substring(0, token.lastIndexOf(".") + 1);
25+
26+
JwtParser parser = Jwts.parser();
27+
28+
Jwt<Header, Claims> claims = parser.parseClaimsJwt(tokenWithoutSignature);
29+
30+
return jwtKeyResolver
31+
.resolve((Map<String, Object>) claims.getHeader())
32+
.map(key -> parser.setSigningKey(key).parseClaimsJws(token).getBody())
33+
.map(this::profileFromClaims)
34+
.onErrorMap(AuthenticationException::new);
35+
});
2536
}
2637
}

jwt/src/main/java/io/scalecube/security/jwt/DefaultSigningKeyResolver.java

Lines changed: 0 additions & 35 deletions
This file was deleted.

jwt/src/main/java/io/scalecube/security/jwt/JwtKeyResolver.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
import java.security.Key;
44
import java.util.Map;
5+
import reactor.core.publisher.Mono;
56

67
@FunctionalInterface
78
public interface JwtKeyResolver {
89

9-
Key resolve(Map<String, Object> tokenClaims);
10+
Mono<Key> resolve(Map<String, Object> jtwHeaders);
1011
}

jwt/src/test/java/io/scalecube/security/JwtAuthenticatorTests.java

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
44
import static org.junit.jupiter.api.Assertions.assertNull;
5+
56
import io.jsonwebtoken.ExpiredJwtException;
67
import io.jsonwebtoken.Jwts;
78
import io.jsonwebtoken.SignatureAlgorithm;
@@ -22,6 +23,7 @@
2223
import javax.crypto.spec.SecretKeySpec;
2324
import org.junit.jupiter.api.Assertions;
2425
import org.junit.jupiter.api.Test;
26+
import reactor.core.publisher.Mono;
2527
import reactor.test.StepVerifier;
2628

2729
class JwtAuthenticatorTests {
@@ -46,7 +48,7 @@ void authenticateAuthenticateUsingKidHeaderPropertyAuthenticationSuccess() {
4648
.signWith(hmacSecretKey)
4749
.compact();
4850

49-
JwtAuthenticator sut = new DefaultJwtAuthenticator(map -> hmacSecretKey);
51+
JwtAuthenticator sut = new DefaultJwtAuthenticator(map -> Mono.just(hmacSecretKey));
5052

5153
StepVerifier.create(sut.authenticate(token))
5254
.assertNext(
@@ -71,7 +73,7 @@ void authenticateCreateTokenAndAuthenticateHmacAuthenticationSuccess() {
7173
.signWith(hmacSecretKey)
7274
.compact();
7375

74-
JwtAuthenticator sut = new DefaultJwtAuthenticator(map -> hmacSecretKey);
76+
JwtAuthenticator sut = new DefaultJwtAuthenticator(map -> Mono.just(hmacSecretKey));
7577

7678
StepVerifier.create(sut.authenticate(token))
7779
.assertNext(
@@ -100,9 +102,10 @@ void authenticateValidTokenInvalidHmacSecretAuthenticationFailedExceptionThrown(
100102
JwtAuthenticator sut =
101103
new DefaultJwtAuthenticator(
102104
map ->
103-
new SecretKeySpec(
104-
UUID.randomUUID().toString().getBytes(),
105-
SignatureAlgorithm.HS256.getJcaName()));
105+
Mono.just(
106+
new SecretKeySpec(
107+
UUID.randomUUID().toString().getBytes(),
108+
SignatureAlgorithm.HS256.getJcaName())));
106109
StepVerifier.create(sut.authenticate(token))
107110
.expectErrorSatisfies(
108111
actualException ->
@@ -128,12 +131,8 @@ void authenticateUsingKidHeaderPropertyKidIsMissingAuthenticationFailsExceptionT
128131
map ->
129132
Optional.ofNullable(map.get("kid"))
130133
.filter(String.class::isInstance)
131-
.map(
132-
s -> {
133-
// Safe to cast to string, use the kid property to fetch the key
134-
return hmacSecretKey;
135-
})
136-
.orElse(null));
134+
.map(s -> Mono.just(hmacSecretKey))
135+
.orElse(Mono.empty()));
137136

138137
StepVerifier.create(sut.authenticate(token))
139138
.expectErrorSatisfies(
@@ -156,7 +155,7 @@ void authenticateCreateTokenAndValidateRsaAuthenticationSuccess() {
156155
.signWith(keys.getPrivate())
157156
.compact();
158157

159-
JwtAuthenticator sut = new DefaultJwtAuthenticator(map -> keys.getPublic());
158+
JwtAuthenticator sut = new DefaultJwtAuthenticator(map -> Mono.just(keys.getPublic()));
160159

161160
StepVerifier.create(sut.authenticate(token))
162161
.assertNext(
@@ -184,12 +183,8 @@ void authenticateCreateTokenAndValidateWrongKeyForAlgorithmAuthenticationFailsEx
184183
map ->
185184
Optional.ofNullable(map.get("kid"))
186185
.filter(String.class::isInstance)
187-
.map(
188-
s -> {
189-
// Safe to cast to string, use the kid property to fetch the key
190-
return hmacSecretKey;
191-
})
192-
.orElse(null));
186+
.map(s -> Mono.just(hmacSecretKey))
187+
.orElse(Mono.empty()));
193188

194189
StepVerifier.create(sut.authenticate(token))
195190
.expectErrorSatisfies(
@@ -208,7 +203,7 @@ void authenticateMissingClaimsInTokenAuthenticationSuccessProfilePropertyIsMissi
208203
.signWith(keys.getPrivate())
209204
.compact();
210205

211-
JwtAuthenticator sut = new DefaultJwtAuthenticator(map -> keys.getPublic());
206+
JwtAuthenticator sut = new DefaultJwtAuthenticator(map -> Mono.just(keys.getPublic()));
212207

213208
StepVerifier.create(sut.authenticate(token))
214209
.assertNext(
@@ -229,12 +224,8 @@ void authenticateUnsignedTokenAuthenticationFailsExceptionThrown() {
229224
map ->
230225
Optional.ofNullable(map.get("kid"))
231226
.filter(String.class::isInstance)
232-
.map(
233-
s -> {
234-
// Safe to cast to string, use the kid property to fetch the key
235-
return hmacSecretKey;
236-
})
237-
.orElse(null));
227+
.map(s -> Mono.just(hmacSecretKey))
228+
.orElse(Mono.empty()));
238229

239230
StepVerifier.create(sut.authenticate(token))
240231
.expectErrorSatisfies(
@@ -252,7 +243,7 @@ void authenticateKeyResolverReturnNullsAuthenticationFailsExceptionThrown() {
252243
.signWith(keys.getPrivate())
253244
.compact();
254245

255-
JwtAuthenticator sut = new DefaultJwtAuthenticator(map -> null);
246+
JwtAuthenticator sut = new DefaultJwtAuthenticator(map -> Mono.empty());
256247
StepVerifier.create(sut.authenticate(token))
257248
.expectErrorSatisfies(
258249
actualException ->
@@ -276,7 +267,7 @@ void authenticateAuthenticateExpiredTokenFails() {
276267
.signWith(hmacSecretKey)
277268
.compact();
278269

279-
JwtAuthenticator sut = new DefaultJwtAuthenticator(map -> null);
270+
JwtAuthenticator sut = new DefaultJwtAuthenticator(map -> Mono.empty());
280271
StepVerifier.create(sut.authenticate(token))
281272
.expectErrorSatisfies(
282273
actualException ->

jwt/src/test/java/io/scalecube/security/acl/AccessControlTest.java

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.scalecube.security.acl;
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
45
import io.jsonwebtoken.Jwts;
56
import io.scalecube.security.api.Authenticator;
67
import io.scalecube.security.jwt.DefaultJwtAuthenticator;
@@ -10,30 +11,32 @@
1011
import javax.crypto.SecretKey;
1112
import org.junit.jupiter.api.BeforeAll;
1213
import org.junit.jupiter.api.Test;
14+
import reactor.core.publisher.Mono;
1315
import reactor.test.StepVerifier;
1416

15-
public class AccessControlTest {
17+
class AccessControlTest {
1618

17-
// user permissions
19+
// user permissions
1820
private static final String RESOURCE_READ = "resource/read";
1921
private static final String RESOURCE_CREATE = "resource/create";
2022
private static final String RESOURCE_DELETE = "resource/delete";
21-
23+
2224
// user roles
2325
private static final String OWNER = "owner";
2426
private static final String ADMIN = "admin";
2527
private static final String MEMBER = "member";
26-
28+
2729
private static SecretKey key;
28-
private static DefaultAccessControl accessContorl;
30+
private static DefaultAccessControl accessControl;
2931

3032
@BeforeAll
31-
public static void setUp() throws Exception {
33+
static void setUp() throws Exception {
3234
key = KeyGenerator.getInstance("HmacSHA256").generateKey();
35+
3336
Authenticator authenticator =
34-
new DefaultJwtAuthenticator(m -> "1".equals(m.get("kid")) ? key : null);
37+
new DefaultJwtAuthenticator(m -> "1".equals(m.get("kid")) ? Mono.just(key) : Mono.empty());
3538

36-
accessContorl =
39+
accessControl =
3740
DefaultAccessControl.builder()
3841
.authenticator(authenticator)
3942
.authorizer(
@@ -46,16 +49,12 @@ public static void setUp() throws Exception {
4649
}
4750

4851
@Test
49-
public void shouldGrantAccess() throws NoSuchAlgorithmException {
52+
void shouldGrantAccess() throws NoSuchAlgorithmException {
5053

5154
String token =
52-
Jwts.builder()
53-
.setHeaderParam("kid", "1")
54-
.claim("roles", OWNER)
55-
.signWith(key)
56-
.compact();
55+
Jwts.builder().setHeaderParam("kid", "1").claim("roles", OWNER).signWith(key).compact();
5756

58-
StepVerifier.create(accessContorl.check(token, RESOURCE_CREATE))
57+
StepVerifier.create(accessControl.check(token, RESOURCE_CREATE))
5958
.assertNext(
6059
profile -> {
6160
assertEquals(profile.claim("roles"), OWNER);
@@ -64,16 +63,12 @@ public void shouldGrantAccess() throws NoSuchAlgorithmException {
6463
}
6564

6665
@Test
67-
public void shouldDenyAccess() throws NoSuchAlgorithmException {
66+
void shouldDenyAccess() throws NoSuchAlgorithmException {
6867

6968
String token =
70-
Jwts.builder()
71-
.setHeaderParam("kid", "1")
72-
.claim("roles", MEMBER)
73-
.signWith(key)
74-
.compact();
69+
Jwts.builder().setHeaderParam("kid", "1").claim("roles", MEMBER).signWith(key).compact();
7570

76-
StepVerifier.create(accessContorl.check(token, RESOURCE_DELETE))
71+
StepVerifier.create(accessControl.check(token, RESOURCE_DELETE))
7772
.expectError(AccessControlException.class)
7873
.verify();
7974
}

0 commit comments

Comments
 (0)