Search code examples
c#asp.net-coreidentityserver4ocelot

Why my Gateway returns with 403 status code?


I have a service called Catalog. When I make a request as follows to access this service normally and take courses through the service, the request is answered successfully.

localhost:5011/api/courses

When I make the following request to receive all courses through the gateway, it returns with a 403 status code. For this I make a request as follows:

http://localhost:5000/services/catalog/courses

As a result, the same request is not responded to via the gateway.

Program.cs File of my Gateway project:

using Ocelot.DependencyInjection;
using Ocelot.Middleware;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication().AddJwtBearer("GatewayAuthenticationScheme",options =>
{
    options.Authority = builder.Configuration["IdentityServerUrl"];
    options.Audience = "resource_gateway";
    options.RequireHttpsMetadata = false;
});

builder.Configuration.AddJsonFile($"configuration.{builder.Environment.EnvironmentName.ToString().ToLower()}.json");

builder.Services.AddOcelot();

var app = builder.Build();

app.UseAuthorization();
await app.UseOcelot();

app.Run();


Gateway is waiting for resource_gateway audience.

This audience is included in the token I sent.

The Config.cs file for the Identity server is as follows:


using System;
using IdentityServer4.Models;
using System.Collections.Generic;
using IdentityServer4;

namespace FreeCourse.IdentityServer
{
    public static class Config
    {
        public static IEnumerable<ApiResource> ApiResources =>
            new ApiResource[]
            {
                new ApiResource("resource_catalog") { Scopes = { "catalog_fullpermission" } },
                new ApiResource("resource_photo_stock") { Scopes = { "photo_stock_fullpermission" } },
                new ApiResource("resource_basket") { Scopes = { "basket_fullpermission" } },
                new ApiResource("resource_discount") { Scopes = { "discount_fullpermission" } },
                new ApiResource("resource_order") { Scopes = { "order_fullpermission" } },
                new ApiResource("resource_payment") { Scopes = { "payment_fullpermission" } },
                new ApiResource("resource_gateway") { Scopes = { "gateway_fullpermission" } },
                new ApiResource(IdentityServerConstants.LocalApi.ScopeName)
            };

        public static IEnumerable<IdentityResource> IdentityResources =>
            new IdentityResource[]
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Email(),
                new IdentityResources.Profile(),
                new IdentityResource()
                    { Name = "roles", DisplayName = "Roles", Description = "User roles", UserClaims = new[] { "role" } }
            };

        public static IEnumerable<ApiScope> ApiScopes =>
            new ApiScope[]
            {
                new ApiScope("catalog_fullpermission", "full access permission for Catalog API "),
                new ApiScope("photo_stock_fullpermission", "full access permission for PhotoStock API "),
                new ApiScope("basket_fullpermission", "full access permission for Basket API "),
                new ApiScope("discount_fullpermission", "full access permission for Discount API "),
                new ApiScope("order_fullpermission", "full access permission for Order API "),
                new ApiScope("payment_fullpermission", "full access permission for Payment API"),
                new ApiScope("gateway_fullpermission", "full access permission for Gateway API"),
                new ApiScope(IdentityServerConstants.LocalApi.ScopeName)
            };

        public static IEnumerable<Client> Clients =>
            new Client[]
            {
                new Client
                {
                    ClientName = "Asp.Net Core MVC",
                    ClientId = "WebMvcClient",
                    ClientSecrets = { new Secret("secret".Sha256()) },
                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    AllowedScopes =
                    {
                        "catalog_fullpermission", "photo_stock_fullpermission", "gateway_fullpermission",
                        IdentityServerConstants.LocalApi.ScopeName
                    }
                },

                new Client
                {
                    ClientName = "Asp.Net Core MVC",
                    ClientId = "WebMvcClientForUser",
                    AllowOfflineAccess = true,
                    ClientSecrets = { new Secret("secret".Sha256()) },
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                    AllowedScopes =
                    {
                        "gateway_fullpermission",
                        "basket_fullpermission",
                        "discount_fullpermission",
                        "order_fullpermission",
                        "payment_fullpermission",
                        "catalog_fullpermission",
                        "photo_stock_fullpermission",
                        "gateway_fullpermission",
                        IdentityServerConstants.StandardScopes.Email,
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes
                            .OfflineAccess,
                        IdentityServerConstants.LocalApi.ScopeName,
                        "roles"
                    },
                    AccessTokenLifetime = 1 * 60 * 60, 
                    RefreshTokenExpiration = TokenExpiration.Absolute,
                    AbsoluteRefreshTokenLifetime =
                        (int)(DateTime.Now.AddDays(60) - DateTime.Now).TotalSeconds, // 60 gun
                    RefreshTokenUsage = TokenUsage.ReUse, 
                }
            };
    }
}

Ocelot configuration file:

{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5011
        }
      ],
      "UpstreamPathTemplate": "/services/catalog/{everything}",
      "UpstreamHttpMethod": [
        "Get",
        "Post",
        "Put",
        "Delete"
      ],
      "UpstreamScheme": "http",
        "AuthenticationOptions": {
            "AuthenticationProviderKey": "GatewayAuthenticationScheme",
            "AllowedScopes": ["catalog_fullpermission"]
        }
    },
    {
      "DownstreamPathTemplate": "/api/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5012
        }
      ],
      "UpstreamPathTemplate": "/services/photostock/{everything}",
      "UpstreamHttpMethod": [
        "Get",
        "Post",
        "Put",
        "Delete"
      ],
      "UpstreamScheme": "http",
        "AuthenticationOptions": {
            "AuthenticationProviderKey": "GatewayAuthenticationScheme",
            "AllowedScopes": ["photostock_fullpermission"]
        }
    }, 
    {
      "DownstreamPathTemplate": "/api/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5013
        }
      ],
      "UpstreamPathTemplate": "/services/basket/{everything}",
      "UpstreamHttpMethod": [
        "Get",
        "Post",
        "Put",
        "Delete"
      ],
      "UpstreamScheme": "http",
        "AuthenticationOptions": {
            "AuthenticationProviderKey": "GatewayAuthenticationScheme",
            "AllowedScopes": ["basket_fullpermission"]
        }
    },
    {
      "DownstreamPathTemplate": "/api/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5014
        }
      ],
      "UpstreamPathTemplate": "/services/discount/{everything}",
      "UpstreamHttpMethod": [
        "Get",
        "Post",
        "Put",
        "Delete"
      ],
      "UpstreamScheme": "http",
        "AuthenticationOptions": {
            "AuthenticationProviderKey": "GatewayAuthenticationScheme",
            "AllowedScopes": ["discount_fullpermission"]
        }
    },
    {
      "DownstreamPathTemplate": "/api/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5015
        }
      ],
      "UpstreamPathTemplate": "/services/order/{everything}",
      "UpstreamHttpMethod": [
        "Get",
        "Post",
        "Put",
        "Delete"
      ],
      "UpstreamScheme": "http",
        "AuthenticationOptions": {
            "AuthenticationProviderKey": "GatewayAuthenticationScheme",
            "AllowedScopes": ["order_fullpermission"]
        }
    },
    {
      "DownstreamPathTemplate": "/api/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5016
        }
      ],
      "UpstreamPathTemplate": "/services/payment/{everything}",
      "UpstreamHttpMethod": [
        "Get",
        "Post",
        "Put",
        "Delete"
      ],
      "UpstreamScheme": "http",
        "AuthenticationOptions": {
            "AuthenticationProviderKey": "GatewayAuthenticationScheme",
            "AllowedScopes": ["payment_fullpermission"]
        }
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:5000"
  }
}

I checked the token I sent on jwt.io. The token contains "resource_gateway". I can't understand the problem.

Thank you very much.


Solution

  • The problem was caused by the identity server not being up to date. After updating, the problem went away.