Create Ocelot middleware in c#

81 Views Asked by At

Net core. I am trying to implement Authorization in Ocelot gateway but due to some oprn issues at ocelot side i am looking at alternatives mentioned at https://github.com/ThreeMammals/Ocelot/issues/679#issuecomment-662905004. I am building my solution as below.

Program.cs File

builder.Services.AddOcelot(builder.Configuration);
builder.Services.DecorateClaimAuthoriser();
var app = builder.Build();

ClaimAuthorizerDecorator.cs file

public class ClaimAuthorizerDecorator : IClaimsAuthoriser
{
    private readonly ClaimsAuthorizer _authoriser;

    public ClaimAuthorizerDecorator(ClaimsAuthorizer authoriser)
    {
        _authoriser = authoriser;
    }

    public Response<bool> Authorise(ClaimsPrincipal claimsPrincipal,
                                    Dictionary<string, string> routeClaimsRequirement,
                                    List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue> urlPathPlaceholderNameAndValues)
    {
        var newRouteClaimsRequirement = new Dictionary<string, string>();
        foreach (var kvp in routeClaimsRequirement)
        {
            if (kvp.Key.StartsWith("http///"))
            {
                var key = kvp.Key.Replace("http///", "http://");
                newRouteClaimsRequirement.Add(key, kvp.Value);
            }
            else
            {
                newRouteClaimsRequirement.Add(kvp.Key, kvp.Value);
            }
        }

        return _authoriser.Authorize(claimsPrincipal, newRouteClaimsRequirement, urlPathPlaceholderNameAndValues);
    }
}

public interface IClaimsAuthoriser
{
    Response<bool> Authorise(ClaimsPrincipal claimsPrincipal,
                                    Dictionary<string, string> routeClaimsRequirement,
                                    List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue> urlPathPlaceholderNameAndValues);
}

ServiceCollectionExtensions.cs file

 public static class ServiceCollectionExtensions
 {
     public static IServiceCollection DecorateClaimAuthoriser(this IServiceCollection services)
     {
         var serviceDescriptor = services.First(x => x.ServiceType == typeof(IClaimsAuthoriser));
         services.Remove(serviceDescriptor);

         var newServiceDescriptor = new ServiceDescriptor(serviceDescriptor.ImplementationType, serviceDescriptor.ImplementationType, serviceDescriptor.Lifetime);
         services.Add(newServiceDescriptor);

         services.AddTransient<IClaimsAuthoriser, ClaimAuthorizerDecorator>();

         return services;
     }
 }

When I run this solution I am getting error in the file ServiceCollectionExtensions at line

 var serviceDescriptor = services.First(x => x.ServiceType == typeof(IClaimsAuthoriser));

Below exception coming in the above line

-$exception {"Sequence contains no matching element"} System.InvalidOperationException

Can someone please help me to fix this error? Any help would be appreciated. Thanks

1

There are 1 best solutions below

0
Qing Guo On BEST ANSWER

Below exception coming in the above line

-$exception {"Sequence contains no matching element"} System.InvalidOperationException

  1. Install Ocelot and its dependencies in your ASP.NET Core project with Ocelot's NuGet package, from Visual Studio.

2.The interface IClaimsAuthorizer is in Ocelot.Authorization, it has Response<bool> Authorize ,

enter image description here

try to modify your ClaimAuthorizerDecorator like:

 public class ClaimAuthorizerDecorator : IClaimsAuthorizer
 {
     private readonly ClaimsAuthoriser _authoriser;

     public ClaimAuthorizerDecorator(ClaimsAuthoriser authoriser)
     {
         _authoriser = authoriser;
     }

     public Response<bool> Authorize(ClaimsPrincipal claimsPrincipal, Dictionary<string, string> routeClaimsRequirement, List<PlaceholderNameAndValue> urlPathPlaceholderNameAndValues)
     {
         var newRouteClaimsRequirement = new Dictionary<string, string>();
         foreach (var kvp in routeClaimsRequirement)
         {
             if (kvp.Key.StartsWith("http///"))
             {
                 var key = kvp.Key.Replace("http///", "http://");
                 newRouteClaimsRequirement.Add(key, kvp.Value);
             }
             else
             {
                 newRouteClaimsRequirement.Add(kvp.Key, kvp.Value);
             }
         }

         return _authoriser.Authorize(claimsPrincipal, newRouteClaimsRequirement, urlPathPlaceholderNameAndValues);
     }
 }

3.Result: enter image description here