Tyk Gateway provides multiple authentication mechanism (OAuth2, Auth Token, Basic Auth, OpenId Connect, JWT, etc) out of the box. However, you may have additional business logic that needs to be considered. You don’t have to rewrite your security infrastructure because you need to introduce an API gateway into your stack. Tyk allows you to extend the capabilities of its gateway with gRPC plugins.
The chain goes like this:
- Tyk receives a request
- Tyk asks the custom middleware server to authenticate it.
- The server returns the auth results back to the gateway.
- If the auth fails, the gateway will return an error response to the requestor. Otherwise, it will continue the request to the downstream
Optionally, you can choose to cache successful authentication responses in memory to improve performance, which will be covered in detail at the end.
The sample authentication server in this example is written in Java. However, you can use whatever gRPC supported language you wish.
Not a coder? No worries: you don’t need to write a single line of code today. Everything included in this guide has links to the code and content, hosted on our Tyk GitHub where you can easily fork, clone, (and star) it.
Prerequisites
- Gradle 5.4.1(https://gradle.org/install/)
- Java 9+
- Git
Let’s get Kraken
First we’re going to set up our Java server with our business logic and run it so it is ready to accept connections. Next, we’ll set up Tyk to use our Java server for custom authentication. Then we’ll see it all work!
1. Setup the gRPC server
Clone this repo. This code is ready to go, we don’t need to make any modifications.
https://github.com/TykTechnologies/tyk-plugin-coprocess-grpc-java-custom-auth/tree/master
Now, we can run the server by running gradle run
from command line. Give this a minute to come up:
$ gradle run
> Task :run
Initializing gRPC server.
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
2. Setup TYK to use the custom authentication plugin
First, we must enable coprocess middlewares at the gateway level. Edit the Tyk.conf to include these settings:
"coprocess_options" : {
"enable_coprocess": true,
"coprocess_grpc_server": "tcp://localhost:5555"
},
Notice the server port matches what we have in the gRPC server’s TykMiddleware.java port
public class TykMiddleware {
private static final Logger logger = Logger.getLogger(TykMiddleware.class.getName());
static Server server;
static int port = 5555;
…
}
Next, let’s set up our API to do custom authentication. Switch the API’s Authentication mode to Custom Authentication (Plugin):
Finally, at the top of the API designer page, select RAW API DEFINITION
and set driver
to grpc
under custom_middleware
:
"custom_middleware": {
"driver": "grpc"
...
},
Done! Now if we query our Tyk endpoint, Tyk will offload the authentication duties to our custom plugin!
So let’s see it all working. If we curl our upstream directly:
$ curl -X get httpbin.org/headers
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/7.54.0"
}
}
And if we curl through the gateway, which is reverse proxying to the same URL as above:
$ curl https://www.tyk-test.com:8080/custom-java-auth/headers -H "Authorization:notfoobar"
{
"error": "Not authorized"
}
$ curl https://www.tyk-test.com:8080/custom-java-auth/headers -H "Authorization:foobar"
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/7.54.0"
}
}
Note: “foobar” is hard-coded in the Java Auth server. That is the place where you’d place your business logic.
3. (Optional): Caching Authorisation using ID Extractor
Further reading: https://tyk.io/docs/customise-tyk/plugins/rich-plugins/id-extractor/
We can take advantage of Tyk’s built in ID extraction to cache the Authentication results of the gRPC plugin and avoid needing the (respectively slow) plugin to authenticate every API call. If you’ve followed along, it should already be working. Skip the setup instructions to see it in action.
How to set it up:
1) Set “id_extractor” in your API definition:
"custom_middleware": {
"id_extractor": {
"extract_from": "header",
"extract_with": "value",
"extractor_config": {
"header_name": "Authorization"
}
},
"driver": "grpc"
},
2) Set the id_extractor_deadline field in the session object
TykDispatcher.java
CoprocessSessionState.SessionState session = CoprocessSessionState.SessionState.newBuilder()
.setRate(1000.0)
.setPer(1.0)
.setIdExtractorDeadline(expiryTime)
.build();
Now watch the logs of the plugin server as you make requests to the Tyk gateway. It should only be printing request details every 5 seconds, which is the expiry time in the cache. This tells us that the gateway is only needing to authenticate through the plugin every 5 seconds because it has authentication details sitting in the cache as a result of the authentication server’s response.
Summary
And that’s it. In just a few steps we’ve enabled custom authentication middleware using gRPC and Java for the Tyk Gateway. Did you know that we can also use middleware in other phases of the request and response life cycle?
In addition to gRPC, Tyk can also run Javascript, Lua, Python, and coming soon, native Go plugins.
If you have questions, head to the Tyk Community or tweet us at @tyk_io
Want to learn more about Authentication and Tyk? Check out these resources:
https://tyk.io/blog/how-to-implement-single-sign-on-with-tyk-and-okta/
and