mirror of https://github.com/grpc/grpc-java.git
Examples: Add a JWT authentication example (#5154)
This commit is contained in:
parent
2ffc46d6fa
commit
ac52e27b2a
|
|
@ -0,0 +1,78 @@
|
|||
Authentication Example
|
||||
==============================================
|
||||
|
||||
This example illustrates a simple JWT-like credential based authentication implementation in gRPC using
|
||||
client and server interceptors. For simplicity a simple string value is used instead of an actual
|
||||
string-encoded JWT.
|
||||
|
||||
The example requires grpc-java to be pre-built. Using a release tag will download the relevant binaries
|
||||
from a maven repository. But if you need the latest SNAPSHOT binaries you will need to follow
|
||||
[COMPILING](../COMPILING.md) to build these.
|
||||
|
||||
The source code is [here](src/main/java/io/grpc/examples/authentication). Please follow the
|
||||
[steps](./README.md#to-build-the-examples) to build the examples. The build creates scripts
|
||||
`auth-server` and `auth-client` in the `build/install/examples/bin/` directory which can be
|
||||
used to run this example. The example requires the server to be running before starting the
|
||||
client.
|
||||
|
||||
Running auth-server is similar to the normal hello world example and there are no arguments to supply:
|
||||
|
||||
**auth-server**:
|
||||
|
||||
```text
|
||||
USAGE: AuthServer
|
||||
```
|
||||
|
||||
The auth-client accepts optional arguments for user-name and token-value:
|
||||
|
||||
**auth-client**:
|
||||
|
||||
```text
|
||||
USAGE: AuthClient [user-name] [token-value]
|
||||
```
|
||||
|
||||
The `user-name` value is simply passed in the `HelloRequest` message as payload and the value of
|
||||
`payload` is passed in the metadata header as a string value signifying an authentication token.
|
||||
|
||||
|
||||
#### How to run the example:
|
||||
|
||||
```bash
|
||||
# Run the server:
|
||||
./build/install/examples/bin/auth-server
|
||||
# In another terminal run the client
|
||||
./build/install/examples/bin/auth-client client-userA token-valueB
|
||||
```
|
||||
|
||||
That's it! The client will show the user-name reflected back in the message from the server as follows:
|
||||
```
|
||||
INFO: Greeting: Hello Authenticated client-userA
|
||||
```
|
||||
|
||||
And on the server side you will see the token value sent by the client:
|
||||
```
|
||||
Token: token-valueB
|
||||
```
|
||||
|
||||
## Maven
|
||||
|
||||
If you prefer to use Maven follow these [steps](./README.md#maven). You can run the example as follows:
|
||||
|
||||
```
|
||||
$ # Run the server
|
||||
$ mvn exec:java -Dexec.mainClass=io.grpc.examples.authentication.AuthServer
|
||||
$ # In another terminal run the client
|
||||
$ mvn exec:java -Dexec.mainClass=io.grpc.examples.authentication.AuthClient -Dexec.args="client-userA token-valueB"
|
||||
```
|
||||
|
||||
## Bazel
|
||||
|
||||
If you prefer to use Bazel:
|
||||
```
|
||||
(With Bazel v0.8.0 or above.)
|
||||
$ bazel build :auth-server :auth-client
|
||||
$ # Run the server
|
||||
$ bazel-bin/auth-server
|
||||
$ # In another terminal run the client
|
||||
$ bazel-bin/auth-client client-userA token-valueB
|
||||
```
|
||||
|
|
@ -98,6 +98,24 @@ java_binary(
|
|||
],
|
||||
)
|
||||
|
||||
java_binary(
|
||||
name = "auth-client",
|
||||
testonly = 1,
|
||||
main_class = "io.grpc.examples.authentication.AuthClient",
|
||||
runtime_deps = [
|
||||
":examples",
|
||||
],
|
||||
)
|
||||
|
||||
java_binary(
|
||||
name = "auth-server",
|
||||
testonly = 1,
|
||||
main_class = "io.grpc.examples.authentication.AuthServer",
|
||||
runtime_deps = [
|
||||
":examples",
|
||||
],
|
||||
)
|
||||
|
||||
java_binary(
|
||||
name = "route-guide-client",
|
||||
testonly = 1,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ before trying out the examples.
|
|||
|
||||
- [Json serialization](src/main/java/io/grpc/examples/advanced)
|
||||
|
||||
- [Authentication](AUTHENTICATION_EXAMPLE.md)
|
||||
|
||||
|
||||
### To build the examples
|
||||
|
||||
1. **[Install gRPC Java library SNAPSHOT locally, including code generation plugin](../COMPILING.md) (Only need this step for non-released versions, e.g. master HEAD).**
|
||||
|
|
|
|||
|
|
@ -91,6 +91,20 @@ task helloWorldClient(type: CreateStartScripts) {
|
|||
classpath = startScripts.classpath
|
||||
}
|
||||
|
||||
task authServer(type: CreateStartScripts) {
|
||||
mainClassName = 'io.grpc.examples.authentication.AuthServer'
|
||||
applicationName = 'auth-server'
|
||||
outputDir = new File(project.buildDir, 'tmp')
|
||||
classpath = startScripts.classpath
|
||||
}
|
||||
|
||||
task authClient(type: CreateStartScripts) {
|
||||
mainClassName = 'io.grpc.examples.authentication.AuthClient'
|
||||
applicationName = 'auth-client'
|
||||
outputDir = new File(project.buildDir, 'tmp')
|
||||
classpath = startScripts.classpath
|
||||
}
|
||||
|
||||
task compressingHelloWorldClient(type: CreateStartScripts) {
|
||||
mainClassName = 'io.grpc.examples.experimental.CompressingHelloWorldClient'
|
||||
applicationName = 'compressing-hello-world-client'
|
||||
|
|
@ -103,6 +117,8 @@ applicationDistribution.into('bin') {
|
|||
from(routeGuideClient)
|
||||
from(helloWorldServer)
|
||||
from(helloWorldClient)
|
||||
from(authServer)
|
||||
from(authClient)
|
||||
from(compressingHelloWorldClient)
|
||||
fileMode = 0755
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright 2018 The gRPC Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.grpc.examples.authentication;
|
||||
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
import io.grpc.StatusRuntimeException;
|
||||
import io.grpc.examples.helloworld.GreeterGrpc;
|
||||
import io.grpc.examples.helloworld.HelloReply;
|
||||
import io.grpc.examples.helloworld.HelloRequest;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* An authenticating client that requests a greeting from the {@link AuthServer}.
|
||||
* It uses a {@link JwtClientInterceptor} to inject a JWT credential.
|
||||
*/
|
||||
public class AuthClient {
|
||||
private static final Logger logger = Logger.getLogger(AuthClient.class.getName());
|
||||
|
||||
private final ManagedChannel channel;
|
||||
private final GreeterGrpc.GreeterBlockingStub blockingStub;
|
||||
private final JwtClientInterceptor jwtClientInterceptor = new JwtClientInterceptor();
|
||||
|
||||
/** Construct client connecting to AuthServer at {@code host:port} using a client-interceptor
|
||||
* to inject the JWT credentials
|
||||
*/
|
||||
public AuthClient(String host, int port) {
|
||||
this(ManagedChannelBuilder.forAddress(host, port)
|
||||
// Channels are secure by default (via SSL/TLS). For this example we disable TLS to avoid
|
||||
// needing certificates, but it is recommended to use a secure channel while passing
|
||||
// credentials.
|
||||
.usePlaintext());
|
||||
}
|
||||
|
||||
/** Construct client for accessing GreeterGrpc server using the existing channel. */
|
||||
AuthClient(ManagedChannelBuilder builder) {
|
||||
this.channel = builder
|
||||
.intercept(jwtClientInterceptor)
|
||||
.build();
|
||||
blockingStub = GreeterGrpc.newBlockingStub(channel);
|
||||
}
|
||||
|
||||
public void shutdown() throws InterruptedException {
|
||||
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void setTokenValue(String tokenValue) {
|
||||
jwtClientInterceptor.setTokenValue(tokenValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Say hello to server.
|
||||
*
|
||||
* @param name name to set in HelloRequest
|
||||
* @return the message in the HelloReply from the server
|
||||
*/
|
||||
public String greet(String name) {
|
||||
logger.info("Will try to greet " + name + " ...");
|
||||
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
|
||||
HelloReply response;
|
||||
try {
|
||||
response = blockingStub.sayHello(request);
|
||||
} catch (StatusRuntimeException e) {
|
||||
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
|
||||
return e.toString();
|
||||
}
|
||||
logger.info("Greeting: " + response.getMessage());
|
||||
return response.getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Greet server. If provided, the first element of {@code args} is the name to use in the
|
||||
* greeting.
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
AuthClient client = new AuthClient("localhost", 50051);
|
||||
try {
|
||||
/* Access a service running on the local machine on port 50051 */
|
||||
String user = "world";
|
||||
if (args.length > 0) {
|
||||
user = args[0]; /* Use the arg as the name to greet if provided */
|
||||
}
|
||||
if (args.length > 1) {
|
||||
client.setTokenValue(args[1]);
|
||||
}
|
||||
client.greet(user);
|
||||
} finally {
|
||||
client.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright 2018 The gRPC Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.grpc.examples.authentication;
|
||||
|
||||
import io.grpc.Server;
|
||||
import io.grpc.ServerBuilder;
|
||||
import io.grpc.examples.helloworld.GreeterGrpc;
|
||||
import io.grpc.examples.helloworld.HelloReply;
|
||||
import io.grpc.examples.helloworld.HelloRequest;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Server that manages startup/shutdown of a {@code Greeter} server.
|
||||
* This also uses a {@link JwtServerInterceptor} to intercept the JWT token passed
|
||||
*/
|
||||
public class AuthServer {
|
||||
private static final Logger logger = Logger.getLogger(AuthServer.class.getName());
|
||||
|
||||
private Server server;
|
||||
|
||||
private void start() throws IOException {
|
||||
/* The port on which the server should run */
|
||||
int port = 50051;
|
||||
server = ServerBuilder.forPort(port)
|
||||
.addService(new GreeterImpl())
|
||||
.intercept(new JwtServerInterceptor()) // add the JwtServerInterceptor
|
||||
.build()
|
||||
.start();
|
||||
logger.info("Server started, listening on " + port);
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
|
||||
System.err.println("*** shutting down gRPC server since JVM is shutting down");
|
||||
AuthServer.this.stop();
|
||||
System.err.println("*** server shut down");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void stop() {
|
||||
if (server != null) {
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Await termination on the main thread since the grpc library uses daemon threads.
|
||||
*/
|
||||
private void blockUntilShutdown() throws InterruptedException {
|
||||
if (server != null) {
|
||||
server.awaitTermination();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main launches the server from the command line.
|
||||
*/
|
||||
public static void main(String[] args) throws IOException, InterruptedException {
|
||||
final AuthServer server = new AuthServer();
|
||||
server.start();
|
||||
server.blockUntilShutdown();
|
||||
}
|
||||
|
||||
static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
|
||||
|
||||
@Override
|
||||
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
|
||||
HelloReply reply = HelloReply.newBuilder().setMessage("Hello Authenticated " + req.getName()).build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2018 The gRPC Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.grpc.examples.authentication;
|
||||
|
||||
import io.grpc.Metadata;
|
||||
|
||||
import static io.grpc.Metadata.ASCII_STRING_MARSHALLER;
|
||||
|
||||
/**
|
||||
* Constants definition
|
||||
*/
|
||||
public final class Constant {
|
||||
private Constant() {
|
||||
}
|
||||
|
||||
public static final Metadata.Key<String> JWT_METADATA_KEY = Metadata.Key.of("jwt", ASCII_STRING_MARSHALLER);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright 2018 The gRPC Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.grpc.examples.authentication;
|
||||
|
||||
import io.grpc.CallOptions;
|
||||
import io.grpc.Channel;
|
||||
import io.grpc.ClientCall;
|
||||
import io.grpc.ClientInterceptor;
|
||||
import io.grpc.ForwardingClientCall;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.MethodDescriptor;
|
||||
|
||||
/**
|
||||
* Use a {@link ClientInterceptor} to insert a JWT in the client to outgoing calls, that's designed
|
||||
* specifically to append credentials information. A token might expire, so for each call, if the
|
||||
* token has expired, you can proactively refresh it.
|
||||
*
|
||||
* Every time a call takes place, the handler will execute, and the
|
||||
* {@link io.grpc.CallCredentials2.MetadataApplier}
|
||||
* is applied to add a header. The method should not block: to refresh or fetch a token from the
|
||||
* network, it should be done asynchronously.
|
||||
*/
|
||||
public class JwtClientInterceptor implements ClientInterceptor {
|
||||
|
||||
private String tokenValue = "my-default-token";
|
||||
|
||||
public void setTokenValue(String tokenValue) {
|
||||
this.tokenValue = tokenValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
|
||||
MethodDescriptor<ReqT, RespT> methodDescriptor, CallOptions callOptions,
|
||||
Channel channel) {
|
||||
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(
|
||||
channel.newCall(methodDescriptor, callOptions)) {
|
||||
@Override
|
||||
public void start(Listener<RespT> responseListener, Metadata headers) {
|
||||
headers.put(Constant.JWT_METADATA_KEY, tokenValue);
|
||||
super.start(responseListener, headers);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2018 The gRPC Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.grpc.examples.authentication;
|
||||
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.ServerCall;
|
||||
import io.grpc.ServerCallHandler;
|
||||
import io.grpc.ServerInterceptor;
|
||||
|
||||
/**
|
||||
* Use a {@link ServerInterceptor} to capture metadata and retrieve any JWT token.
|
||||
*
|
||||
* This interceptor only captures the JWT token and prints it out.
|
||||
* Normally the token will need to be validated against an identity provider.
|
||||
*/
|
||||
public class JwtServerInterceptor implements ServerInterceptor {
|
||||
|
||||
@Override
|
||||
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata, ServerCallHandler<ReqT, RespT> serverCallHandler) {
|
||||
// Get token from Metadata
|
||||
// Capture the JWT token and just print it out.
|
||||
String token = metadata.get(Constant.JWT_METADATA_KEY);
|
||||
System.out.println("Token: " + token);
|
||||
|
||||
return serverCallHandler.startCall(serverCall, metadata);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright 2015 The gRPC Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.grpc.examples.authentication;
|
||||
|
||||
import io.grpc.*;
|
||||
import io.grpc.examples.helloworld.GreeterGrpc;
|
||||
import io.grpc.examples.helloworld.HelloReply;
|
||||
import io.grpc.examples.helloworld.HelloRequest;
|
||||
import io.grpc.inprocess.InProcessChannelBuilder;
|
||||
import io.grpc.inprocess.InProcessServerBuilder;
|
||||
import io.grpc.ServerCall.Listener;
|
||||
import io.grpc.ServerInterceptor;
|
||||
import io.grpc.testing.GrpcCleanupRule;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Matchers;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.AdditionalAnswers.delegatesTo;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AuthClient} testing the default and non-default tokens
|
||||
*
|
||||
*
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public class AuthClientTest {
|
||||
/**
|
||||
* This rule manages automatic graceful shutdown for the registered servers and channels at the
|
||||
* end of test.
|
||||
*/
|
||||
@Rule
|
||||
public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
|
||||
|
||||
private final ServerInterceptor mockServerInterceptor = mock(ServerInterceptor.class, delegatesTo(
|
||||
new ServerInterceptor() {
|
||||
@Override
|
||||
public <ReqT, RespT> Listener<ReqT> interceptCall(
|
||||
ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
|
||||
return next.startCall(call, headers);
|
||||
}
|
||||
}));
|
||||
|
||||
private AuthClient client;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
// Generate a unique in-process server name.
|
||||
String serverName = InProcessServerBuilder.generateName();
|
||||
|
||||
// Create a server, add service, start, and register for automatic graceful shutdown.
|
||||
grpcCleanup.register(InProcessServerBuilder.forName(serverName).directExecutor()
|
||||
.addService(ServerInterceptors.intercept(new GreeterGrpc.GreeterImplBase() {
|
||||
|
||||
@Override
|
||||
public void sayHello(io.grpc.examples.helloworld.HelloRequest request,
|
||||
io.grpc.stub.StreamObserver<io.grpc.examples.helloworld.HelloReply> responseObserver) {
|
||||
HelloReply reply = HelloReply.newBuilder().setMessage("AuthClientTest user=" + request.getName()).build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
}, mockServerInterceptor))
|
||||
.build().start());
|
||||
|
||||
// Create an AuthClient using the in-process channel;
|
||||
client = new AuthClient(InProcessChannelBuilder.forName(serverName).directExecutor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test default JWT token used
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void defaultTokenDeliveredToServer() throws Exception {
|
||||
ArgumentCaptor<Metadata> metadataCaptor = ArgumentCaptor.forClass(Metadata.class);
|
||||
ArgumentCaptor<HelloRequest> requestCaptor = ArgumentCaptor.forClass(HelloRequest.class);
|
||||
|
||||
String retVal = client.greet("default token test");
|
||||
|
||||
verify(mockServerInterceptor).interceptCall(
|
||||
Matchers.<ServerCall<HelloRequest, HelloReply>>any(),
|
||||
metadataCaptor.capture(),
|
||||
Matchers.<ServerCallHandler<HelloRequest, HelloReply>>any());
|
||||
assertEquals(
|
||||
"my-default-token",
|
||||
metadataCaptor.getValue().get(Constant.JWT_METADATA_KEY));
|
||||
assertEquals("AuthClientTest user=default token test", retVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test non-default JWT token used
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void nonDefaultTokenDeliveredToServer() throws Exception {
|
||||
ArgumentCaptor<Metadata> metadataCaptor = ArgumentCaptor.forClass(Metadata.class);
|
||||
ArgumentCaptor<HelloRequest> requestCaptor = ArgumentCaptor.forClass(HelloRequest.class);
|
||||
|
||||
client.setTokenValue("non-default-token");
|
||||
String retVal = client.greet("non default token test");
|
||||
|
||||
verify(mockServerInterceptor).interceptCall(
|
||||
Matchers.<ServerCall<HelloRequest, HelloReply>>any(),
|
||||
metadataCaptor.capture(),
|
||||
Matchers.<ServerCallHandler<HelloRequest, HelloReply>>any());
|
||||
assertEquals(
|
||||
"non-default-token",
|
||||
metadataCaptor.getValue().get(Constant.JWT_METADATA_KEY));
|
||||
assertEquals("AuthClientTest user=non default token test", retVal);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue