How to integrate Ocelot with Identity Server 4

Not so long ago I wrote an article on how we can create our own API gateways using the Ocelot open source library. Since then, I received some questions on how to integrate Ocelot with Identity Server 4 so I thought to share how I managed to achieve this using the Ocelot documentation and some basic Identity Server 4 knowledge. Please note that following these steps I was able to successfully build an API gateway using Ocelot, that used Identity Server 4 JWT tokens to authorize requests and redirect them to the desired downstream path.

To achieve this, the first thing we need is a working Identity Server 4 application. Since this is out of scope for  the current article I won’t spend any time on this topic. Please consult the Identity Server 4 documentation and use some code samples to create a working application as soon as possible.

The second thing you need is a working API application. You could use the default ASP.Net Core Web API template in Visual Studio to get starting. For testing purposes the standard ValuesController that you’ll get out of the box would do it.

Last but not least, what we need is a working and configured Ocelot application. If you want to get started fast please refer to the previous article, where you’ll find some instructions on how to configure Ocelot. You can configure a ReRoute in Ocelot for the Values API that I mentioned earlier and test if everything is working as expected.

Once everything is set up, integrating with Identity Server 4 is really easy. I’ve spent personally more time on configuring Ocelot and understanding how it works than on integrating with Identity Server 4. Since Ocelot is a library for ASP.Net Core 2.x applications, adding identity is really similar to how you would do it in all Asp.net Core applications. We just need to add the appropriate service in the ConfigureServices() method on Startup.cs. And it will look similar to this:

public void ConfigureServices(IServiceCollection services)
    {
        var authenticationProviderKey = "TestKey";
        var options = o =>
            {
                o.Authority = "https://whereyouridentityserverlives.com";
                o.ApiName = "api";
                o.SupportedTokens = SupportedTokens.Both;
                o.ApiSecret = "secret";
            };

        services.AddAuthentication()
            .AddIdentityServerAuthentication(authenticationProviderKey, options);

        services.AddOcelot();
    }

The authentication provider key is very important, since you’ll have to provide the key in the ReRoute configuration. Basically you have to add this provider key to each re-route on which you want to authenticate/authorize with Identity Server 4. The re-route configuration would look similar to this code:


{
    "DownstreamPathTemplate": "/api/values",
    "DownstreamScheme": "http",
    "UpstreamPathTemplate": "/values",
    "UpstreamHttpMethod": [ "Get", "Post" ],
    "DownstreamHostAndPorts": [
            {
                "Host": "localhost",
                "Port": 64548
            }

        ],
    "AuthenticationOptions": {
    "AuthenticationProviderKey": "TestKey",
    "AllowedScopes": []
    }

}

Further o.Authority, o.ApiName, o.ApiSecret are bits of information that you retrieve on your Identity Server 4 project. When you register an API with Identity Server 4 you basically get all these details. So you just have to provide them as authentication options for Identity Server 4.

And that’s basically it! If all components are wired up correctly, if you run all your projects and make a requeust to the API gate way, to the /values URI, Ocelot will authenticate/authorize the request by looking if an AuthenticationProviderKey is specified on the re-rout configuration. If one is present, it will look up the authentication services that matches with the key. If none is found, you will get an “Unauthorized” response. If everything is Ok, you will get the response from the values API.

Happy coding!

Leave a Reply

Your email address will not be published. Required fields are marked *