kvuong
kvuong

Reputation: 505

How to check Claim value in array or any in Ocelot gateway?

Assume I have 2 endpoints like this

  1. Order creating: requires claim order_perm with value in array ["order_create", "order_edit"]
  2. Order searching: only requires claim order_perm exists

In case 1., I pass above array to RouteClaimsRequirement like below

"RouteClaimsRequirement": {
        "order_perm": ["order_create", "order_edit"]
      }

but it crashes when app starts, and in case 2. I setup like this

"RouteClaimsRequirement": {
            "order_perm": ""
          }

but user has claim "order_perm": "create_order" fails authorization.

Does RouteClaimsRequirement support these use cases? If so how can I do that?

Upvotes: 4

Views: 2828

Answers (1)

I know this an old question, I recently got stuck on the same thing, after a lot googling I found this solution on github. I changed a few things to make it work for me as I'm using Ocelot 16.0.1. ocelot.json file

{
  "DownstreamPathTemplate": "/api/{everything}/{everything}",
  "DownstreamScheme": "http",
  "DownstreamHostAndPorts": [
    {
      "Host": "localhost",
      "Port": "80"
    }
  ],
  "UpstreamPathTemplate": "/web/{everything}/{everything}",
  "UpstreamHttpMethod": [ "GET" ],
  "AuthenticationOptions": {
    "AuthenticationProviderKey": "Authkey",
    "AllowedScopes": []
  },
  "RouteClaimsRequirement": {
    "Role": "Admin , SuperAdmin"
  },
  "SwaggerKey": "myapi"

},

Configure method

public async void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        //your code here
        var configration = new OcelotPipelineConfiguration
        {
            AuthorisationMiddleware=async (ctx, next) =>
            {
                if (this.Authorize(ctx))
                {
                    await next.Invoke();
                }
                else
                {
                    ctx.Items.SetError(new UnauthorisedError($"Fail to authorize"));
                }
            }
        };
        //your code here
        await app.UseOcelot(configration);
    }

Authorize method

 private bool Authorize(HttpContext ctx)
    {
        if (ctx.Items.DownstreamRoute().AuthenticationOptions.AuthenticationProviderKey == null) return true;
        else
        {

            bool auth = false;
            Claim[] claims = ctx.User.Claims.ToArray<Claim>();
            Dictionary<string, string> required = ctx.Items.DownstreamRoute().RouteClaimsRequirement;
            Regex reor = new Regex(@"[^,\s+$ ][^\,]*[^,\s+$ ]");
            MatchCollection matches;

            Regex reand = new Regex(@"[^&\s+$ ][^\&]*[^&\s+$ ]");
            MatchCollection matchesand;
            int cont = 0;
            foreach (KeyValuePair<string, string> claim in required)
            {
                matches = reor.Matches(claim.Value);
                foreach (Match match in matches)
                {
                    matchesand = reand.Matches(match.Value);
                    cont = 0;
                    foreach (Match m in matchesand)
                    {
                        foreach (Claim cl in claims)
                        {
                            if (cl.Type == claim.Key)
                            {
                                if (cl.Value == m.Value)
                                {
                                    cont++;
                                }
                            }
                        }
                    }
                    if (cont == matchesand.Count)
                    {
                        auth = true;
                        break;
                    }
                }
            }
            return auth;
        }
    }

Upvotes: 5

Related Questions