Skip to content

Commit

Permalink
examples: Add a JWT authentication example (grpc#5915)
Browse files Browse the repository at this point in the history
  • Loading branch information
anarsultanov authored and dfawley committed Jan 15, 2021
1 parent 8aed4de commit 5c3d2be
Show file tree
Hide file tree
Showing 13 changed files with 861 additions and 0 deletions.
2 changes: 2 additions & 0 deletions RELEASING.md
Expand Up @@ -45,6 +45,8 @@ $ VERSION_FILES=(
examples/example-alts/build.gradle
examples/example-gauth/build.gradle
examples/example-gauth/pom.xml
examples/example-jwt-auth/build.gradle
examples/example-jwt-auth/pom.xml
examples/example-hostname/build.gradle
examples/example-hostname/pom.xml
examples/example-kotlin/build.gradle
Expand Down
2 changes: 2 additions & 0 deletions examples/README.md
Expand Up @@ -156,6 +156,8 @@ $ bazel-bin/hello-world-client

- [Google Authentication](example-gauth)

- [JWT-based Authentication](example-jwt-auth)

- [Kotlin examples](example-kotlin)

- [Kotlin Android examples](example-kotlin/android)
Expand Down
70 changes: 70 additions & 0 deletions examples/example-jwt-auth/README.md
@@ -0,0 +1,70 @@
Authentication Example
==============================================

This example illustrates a simple JWT-based authentication implementation in gRPC using
server interceptor. It uses the JJWT library to create and verify JSON Web Tokens (JWTs).

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/jwtauth).
To build the example, run in this directory:
```
$ ../gradlew installDist
```
The build creates scripts `auth-server` and `auth-client` in the `build/install/example-jwt-auth/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**:

The auth-server accepts optional argument for port on which the server should run:

```text
USAGE: auth-server [port]
```

The auth-client accepts optional arguments for server-host, server-port, user-name and client-id:

**auth-client**:

```text
USAGE: auth-client [server-host [server-port [user-name [client-id]]]]
```

The `user-name` value is simply passed in the `HelloRequest` message as payload and the value of
`client-id` is included in the JWT claims passed in the metadata header.


#### How to run the example:

```bash
# Run the server:
./build/install/example-jwt-auth/bin/auth-server 50051
# In another terminal run the client
./build/install/example-jwt-auth/bin/auth-client localhost 50051 userA clientB
```

That's it! The client will show the user-name reflected back in the message from the server as follows:
```
INFO: Greeting: Hello, userA
```

And on the server side you will see the message with the client's identifier:
```
Processing request from clientB
```

## 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 -Dexec.args="50051"
$ # In another terminal run the client
$ mvn exec:java -Dexec.mainClass=io.grpc.examples.authentication.AuthClient -Dexec.args="localhost 50051 userA clientB"
```
84 changes: 84 additions & 0 deletions examples/example-jwt-auth/build.gradle
@@ -0,0 +1,84 @@
plugins {
// Provide convenience executables for trying out the examples.
id 'application'
// ASSUMES GRADLE 2.12 OR HIGHER. Use plugin version 0.7.5 with earlier gradle versions
id 'com.google.protobuf' version '0.8.8'
// Generate IntelliJ IDEA's .idea & .iml project files
id 'idea'
}

repositories {
maven { // The google mirror is less flaky than mavenCentral()
url "https://maven-central.storage-download.googleapis.com/repos/central/data/"
}
mavenLocal()
}

sourceCompatibility = 1.7
targetCompatibility = 1.7

// IMPORTANT: You probably want the non-SNAPSHOT version of gRPC. Make sure you
// are looking at a tagged version of the example and not "master"!

// Feel free to delete the comment at the next line. It is just for safely
// updating the version in our release process.
def grpcVersion = '1.29.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def protobufVersion = '3.11.0'
def protocVersion = protobufVersion

dependencies {
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
implementation "io.grpc:grpc-stub:${grpcVersion}"
implementation "io.jsonwebtoken:jjwt:0.9.1"
implementation "javax.xml.bind:jaxb-api:2.3.1"

compileOnly "javax.annotation:javax.annotation-api:1.2"

runtimeOnly "io.grpc:grpc-netty-shaded:${grpcVersion}"

testImplementation "io.grpc:grpc-testing:${grpcVersion}"
testImplementation "junit:junit:4.12"
testImplementation "org.mockito:mockito-core:2.28.2"
}

protobuf {
protoc { artifact = "com.google.protobuf:protoc:${protocVersion}" }
plugins {
grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" }
}
generateProtoTasks {
all()*.plugins { grpc {} }
}
}

// Inform IDEs like IntelliJ IDEA, Eclipse or NetBeans about the generated code.
sourceSets {
main {
java {
srcDirs 'build/generated/source/proto/main/grpc'
srcDirs 'build/generated/source/proto/main/java'
}
}
}

startScripts.enabled = false

task hellowWorldJwtAuthServer(type: CreateStartScripts) {
mainClassName = 'io.grpc.examples.jwtauth.AuthServer'
applicationName = 'auth-server'
outputDir = new File(project.buildDir, 'tmp')
classpath = startScripts.classpath
}

task hellowWorldJwtAuthClient(type: CreateStartScripts) {
mainClassName = 'io.grpc.examples.jwtauth.AuthClient'
applicationName = 'auth-client'
outputDir = new File(project.buildDir, 'tmp')
classpath = startScripts.classpath
}

applicationDistribution.into('bin') {
from(hellowWorldJwtAuthServer)
from(hellowWorldJwtAuthClient)
fileMode = 0755
}
136 changes: 136 additions & 0 deletions examples/example-jwt-auth/pom.xml
@@ -0,0 +1,136 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.grpc</groupId>
<artifactId>example-jwt-auth</artifactId>
<packaging>jar</packaging>
<!-- Feel free to delete the comment at the end of these lines. It is just
for safely updating the version in our release process. -->
<version>1.29.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
<name>example-jwt-auth</name>
<url>https://github.com/grpc/grpc-java</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.29.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
<protobuf.version>3.11.0</protobuf.version>
<protoc.version>3.11.0</protoc.version>
<!-- required for jdk9 -->
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-bom</artifactId>
<version>${grpc.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.2</version>
<scope>provided</scope> <!-- not needed at runtime -->
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-testing</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.28.2</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireUpperBoundDeps/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
8 changes: 8 additions & 0 deletions examples/example-jwt-auth/settings.gradle
@@ -0,0 +1,8 @@
pluginManagement {
repositories {
maven { // The google mirror is less flaky than mavenCentral()
url "https://maven-central.storage-download.googleapis.com/repos/central/data/"
}
gradlePluginPortal()
}
}

0 comments on commit 5c3d2be

Please sign in to comment.