Skip to content

Commit 80764ed

Browse files
committed
Added some tests and improved the test coverage.
1 parent f752d89 commit 80764ed

File tree

10 files changed

+119
-30
lines changed

10 files changed

+119
-30
lines changed

pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@
131131
<configuration>
132132
<excludes>
133133
<exclude>**/*Configuration.*</exclude>
134+
<exclude>**/*GrpcRole.*</exclude>
135+
<exclude>**/proto/**/*</exclude>
134136
</excludes>
135137
</configuration>
136138
<executions>
Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
package io.github.majusko.grpc.jwt.exception;
22

33
public class AuthException extends RuntimeException {
4-
public AuthException() {
5-
}
64

75
public AuthException(String message) {
86
super(message);
97
}
10-
11-
public AuthException(String message, Throwable cause) {
12-
super(message, cause);
13-
}
148
}
Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
11
package io.github.majusko.grpc.jwt.exception;
22

33
public class UnauthenticatedException extends RuntimeException {
4-
5-
public UnauthenticatedException() {
6-
}
7-
84
public UnauthenticatedException(String message) {
95
super(message);
106
}
11-
12-
public UnauthenticatedException(String message, Throwable cause) {
13-
super(message, cause);
14-
}
157
}

src/main/java/io/github/majusko/grpc/jwt/interceptor/AuthClientInterceptor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import io.grpc.*;
55
import org.slf4j.Logger;
66
import org.slf4j.LoggerFactory;
7+
import sun.jvm.hotspot.debugger.ThreadContext;
78

89
public class AuthClientInterceptor implements ClientInterceptor {
910

src/main/java/io/github/majusko/grpc/jwt/interceptor/AuthContextData.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,29 @@
22

33
import io.jsonwebtoken.Claims;
44
import lombok.AllArgsConstructor;
5-
import lombok.Data;
65

76
import java.util.Set;
87

9-
@Data
108
@AllArgsConstructor
119
public class AuthContextData {
1210
private final String jwt;
1311
private final String userId;
1412
private final Set<String> roles;
1513
private final Claims jwtClaims;
14+
15+
public String getJwt() {
16+
return jwt;
17+
}
18+
19+
public String getUserId() {
20+
return userId;
21+
}
22+
23+
public Set<String> getRoles() {
24+
return roles;
25+
}
26+
27+
public Claims getJwtClaims() {
28+
return jwtClaims;
29+
}
1630
}

src/main/java/io/github/majusko/grpc/jwt/interceptor/AuthServerInterceptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ private <ReqT> void authorizeOwnerOrRoles(ReqT request, AuthContextData contextD
141141

142142
authorizeOwner(userId, new HashSet<>(allowed.getRoles()), contextData);
143143
} catch (NoSuchFieldException | IllegalAccessException e) {
144-
throw new AuthException("Missing field.", e);
144+
throw new AuthException("Missing field.");
145145
}
146146
} else {
147147
validateRoles(new HashSet<>(allowed.getRoles()), contextData.getRoles());
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package io.github.majusko.grpc.jwt.interceptor;
22

3+
import java.util.Optional;
4+
35
public class GrpcContext {
46

57
private static final String CONTEXT_DATA = "context_data";
68

79
public static io.grpc.Context.Key<AuthContextData> CONTEXT_DATA_KEY = io.grpc.Context.key(CONTEXT_DATA);
810

9-
public static AuthContextData get() {
10-
return CONTEXT_DATA_KEY.get();
11+
public static Optional<AuthContextData> get() {
12+
return Optional.ofNullable(CONTEXT_DATA_KEY.get());
1113
}
1214
}

src/main/java/io/github/majusko/grpc/jwt/service/dto/JwtMetadata.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,26 @@
22

33
import lombok.AllArgsConstructor;
44
import lombok.Builder;
5-
import lombok.Data;
6-
import lombok.NoArgsConstructor;
75

86
import javax.crypto.SecretKey;
97
import java.util.List;
108

11-
@Data
129
@Builder
13-
@NoArgsConstructor
1410
@AllArgsConstructor
1511
public class JwtMetadata {
1612
private Long expirationSec;
1713
private SecretKey key;
1814
private List<String> env;
15+
16+
public Long getExpirationSec() {
17+
return expirationSec;
18+
}
19+
20+
public SecretKey getKey() {
21+
return key;
22+
}
23+
24+
public List<String> getEnv() {
25+
return env;
26+
}
1927
}
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
package io.github.majusko.grpc.jwt.service.dto;
22

33
import lombok.AllArgsConstructor;
4-
import lombok.Data;
54

65
import java.time.LocalDateTime;
76

8-
@Data
97
@AllArgsConstructor
108
public class JwtToken {
119
private String token;
1210
private LocalDateTime expiration;
11+
12+
public String getToken() {
13+
return token;
14+
}
15+
16+
public LocalDateTime getExpiration() {
17+
return expiration;
18+
}
1319
}

src/test/java/io/github/majusko/grpc/jwt/GrpcJwtSpringBootStarterApplicationTest.java

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
import com.google.protobuf.Empty;
44
import io.github.majusko.grpc.jwt.annotation.Allow;
55
import io.github.majusko.grpc.jwt.annotation.Exposed;
6-
import io.github.majusko.grpc.jwt.interceptor.AllowedCollector;
7-
import io.github.majusko.grpc.jwt.interceptor.AuthClientInterceptor;
8-
import io.github.majusko.grpc.jwt.interceptor.AuthServerInterceptor;
9-
import io.github.majusko.grpc.jwt.interceptor.GrpcHeader;
6+
import io.github.majusko.grpc.jwt.interceptor.*;
107
import io.github.majusko.grpc.jwt.interceptor.proto.Example;
118
import io.github.majusko.grpc.jwt.interceptor.proto.ExampleServiceGrpc;
129
import io.github.majusko.grpc.jwt.service.GrpcRole;
@@ -29,6 +26,7 @@
2926
import org.springframework.test.context.junit4.SpringRunner;
3027

3128
import java.io.IOException;
29+
import java.util.Optional;
3230

3331
@RunWith(SpringRunner.class)
3432
@SpringBootTest
@@ -102,6 +100,66 @@ public void testCustomTokenWithWrongRole() throws IOException {
102100
Assert.assertEquals(Status.PERMISSION_DENIED.getCode(), status.getCode());
103101
}
104102

103+
@Test
104+
public void testWrongToken() throws IOException {
105+
106+
String token = jwtService.generate(new JwtData("some-user-id", "non-existing-role"));
107+
108+
token += "crwvvef";
109+
final ManagedChannel channel = initTestServer(new ExampleService());
110+
final ExampleServiceGrpc.ExampleServiceBlockingStub stub = ExampleServiceGrpc.newBlockingStub(channel);
111+
112+
final Metadata header = new Metadata();
113+
header.put(GrpcHeader.AUTHORIZATION, token);
114+
115+
final ExampleServiceGrpc.ExampleServiceBlockingStub injectedStub = MetadataUtils.attachHeaders(stub, header);
116+
117+
Status status = Status.OK;
118+
119+
try {
120+
final Empty ignored = injectedStub.getExample(Example.GetExampleRequest.newBuilder().build());
121+
} catch (StatusRuntimeException e) {
122+
status = e.getStatus();
123+
}
124+
125+
Assert.assertEquals(Status.UNAUTHENTICATED.getCode(), status.getCode());
126+
}
127+
128+
129+
130+
@Test
131+
public void testMissingAuth() throws IOException {
132+
final ManagedChannel channel = initTestServer(new ExampleService());
133+
final ExampleServiceGrpc.ExampleServiceBlockingStub stub = ExampleServiceGrpc.newBlockingStub(channel);
134+
135+
Status status = Status.OK;
136+
137+
try {
138+
final Empty ignored = stub.getExample(Example.GetExampleRequest.newBuilder().build());
139+
} catch (StatusRuntimeException e) {
140+
status = e.getStatus();
141+
}
142+
143+
Assert.assertEquals(Status.PERMISSION_DENIED.getCode(), status.getCode());
144+
}
145+
146+
@Test
147+
public void testMissingCredentials() throws IOException {
148+
149+
final ManagedChannel channel = initTestServer(new ExampleService());
150+
final ExampleServiceGrpc.ExampleServiceBlockingStub stub = ExampleServiceGrpc.newBlockingStub(channel);
151+
152+
Status status = Status.OK;
153+
154+
try {
155+
final Empty ignored = stub.getExample(Example.GetExampleRequest.newBuilder().build());
156+
} catch (StatusRuntimeException e) {
157+
status = e.getStatus();
158+
}
159+
160+
Assert.assertEquals(Status.PERMISSION_DENIED.getCode(), status.getCode());
161+
}
162+
105163
@Test
106164
public void testCustomTokenWithWrongRoleButMatchingOwner() throws IOException {
107165
final String ownerUserId = "matching-user-id";
@@ -173,10 +231,22 @@ private ManagedChannel initTestServer(BindableService service) throws IOExceptio
173231
@GRpcService
174232
class ExampleService extends ExampleServiceGrpc.ExampleServiceImplBase {
175233

234+
private static final String ADMIN = "admin";
235+
176236
@Override
177-
@Allow(ownerField = "userId", roles = {GrpcRole.INTERNAL, "admin"})
237+
@Allow(ownerField = "userId", roles = {GrpcRole.INTERNAL, ADMIN})
178238
public void getExample(Example.GetExampleRequest request, StreamObserver<Empty> response) {
179239

240+
AuthContextData authContext = GrpcContext.get().orElseThrow(RuntimeException::new);;
241+
242+
Assert.assertNotNull(authContext.getJwt());
243+
Assert.assertTrue(authContext.getJwtClaims().size() > 0);
244+
245+
if(!request.getUserId().equals(authContext.getUserId())) {
246+
Assert.assertTrue(authContext.getRoles().stream()
247+
.anyMatch($ -> $.equals(GrpcRole.INTERNAL) || $.equals(ADMIN)));
248+
}
249+
180250
response.onNext(Empty.getDefaultInstance());
181251
response.onCompleted();
182252
}

0 commit comments

Comments
 (0)