1

アプリケーション内には 4 つのクライアントがあります。

  1. angular.application -リソース所有者
  2. identity_ms.client - webapi アプリ (.net コア 2.1)
    • AspNetIdentity を使用した IdentityServer4
    • ユーザーの登録、パスワードのリセットなどの共有アクションを持つAccountController
    • セキュリティで保護されたアクションを持つUserController 。UserControllerDataアクションには属性があります[Authorize(Policy = "user.data")]
  3. ms_1.client - webapi アプリ (.net コア 2.1)
  4. request.client - ms_1.client から identity_ms.client の UserController に要求を送信してユーザー データを取得するために特別に追加されました。

Postman を使用してクライアントをリクエストしています。

  1. http://localhost:identity_ms_port/connect/tokenを取得してaccess_token
  2. http://localhost:ms_1_port/api/secured/actionで ms_1 から保護されたデータを取得する
  3. http://localhost:identity_ms_port/api/user/dataで、 identity_msから保護されたユーザー データを取得します。

すべてが正常に機能しています。

また、ms_1サービスには、 を使用してhttp://localhost:identity_ms_port/api/user/dataを要求する保護されたアクションがありますSystem.Net.Http.HttpClient

// identity_ms configuration
public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(/*cors options*/);

    services
        .AddMvc()
        .AddApplicationPart(/*Assembly*/)
        .AddJsonOptions(/*SerializerSettings*/)
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.Configure<IISOptions>(iis =>
    {
        iis.AuthenticationDisplayName = "Windows";
        iis.AutomaticAuthentication = false;
    });

    var clients = new List<Client>
    {
        new Client
    {
            ClientId = "angular.application",
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            AllowedScopes = { "user.data.scope", "ms_1.scope", "identity_ms.scope" },
            AllowedGrantTypes = GrantTypes.ResourceOwnerPassword
    },
        new Client
        {
            ClientId = "ms_1.client",
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            AllowedScopes = { "user.data.scope", "ms_1.scope" },
            AllowedGrantTypes = GrantTypes.ClientCredentials
        },
        new Client
        {
            ClientId = "identity_ms.client",
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            AllowedScopes =
            {
                "user.data.scope",
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile
            },
            AllowedGrantTypes = GrantTypes.Implicit
        },
        new Client
        {
            ClientId = "request.client",
            AllowedScopes = { "user.data.scope" },
            AllowedGrantTypes = GrantTypes.ClientCredentials,
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            }
        }
    };
    var apiResources = new List<ApiResource>
    {
        new ApiResource("ms_1.scope", "MS1 microservice scope"),
        new ApiResource("identity_ms.scope", "Identity microservice scope"),
        new ApiResource("user.data.scope", "Requests between microservices scope")
    };

    var identityResources = new List<IdentityResource>
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile()
    };

    services
        .AddAuthorization(options => options.AddPolicy("user.data", policy => policy.RequireScope("user.data.scope")))
        .AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddInMemoryIdentityResources(identityResources)
        .AddInMemoryApiResources(apiResources)
        .AddInMemoryClients(clients);

    services
        .AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(options =>
        {
            options.Audience = "identity_ms.scope";
            options.RequireHttpsMetadata = false;
            options.Authority = "http://localhost:identity_ms_port";
        });

    services.AddSwaggerGen(/*swagger options*/);
}

public void Configure(IApplicationBuilder app)
{
    app.UseMiddleware<CustomMiddleware>();
    app.UseIdentityServer();
    app.UseAuthentication();
    app.UseCors("Policy");
    app.UseHttpsRedirection();
    app.UseMvc(/*routes*/);
    app.UseSwagger();
}

// ms_1.client configuration
public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(/*cors options*/);

    services
        .AddMvc()
        .AddJsonOptions(/*SerializerSettings*/)
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
        {
            options.Audience = "ms_1.scope";
            options.RequireHttpsMetadata = false;
            options.Authority = "http://localhost:identity_ms_port";
        });
}

public void Configure(IApplicationBuilder app)
{
    app.UseMiddleware<CustomMiddleware>();
    app.UseAuthentication();
    app.UseCors("Policy");
    app.UseStaticFiles();
    app.UseHttpsRedirection();
    app.UseMvc(/*routes*/);
    app.UseSwagger();
}

// ms_1.client action using HttpClient
[HttpPost]
public async Task<IActionResult> Post(ViewModel model)
{
    //...
    using (var client = new TokenClient("http://localhost:identity_ms_port/connect/token", "ms_1.client", "secret"))
    {
        var response = await client.RequestClientCredentialsAsync("user.data.scope");

        if (response.IsError)
        {
            throw new Exception($"{response.Error}{(string.IsNullOrEmpty(response.ErrorDescription) ? string.Empty : $": {response.ErrorDescription}")}", response.Exception);
        }

        if (string.IsNullOrWhiteSpace(response.AccessToken))
        {
            throw new Exception("Access token is empty");
        }

        var udClient = new HttpClient();

        udClient.SetBearerToken(response.AccessToken);
        udClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        var result = await udClient.GetAsync("http://localhost:identity_ms_port/api/user/data");
    }
    //...
}

私は次のことを試しました:

  1. リクエストからms_1 Authorization ヘッダーへの access_token を取得し、それを使用して user/data にアクセスます
  2. それを使用してユーザー/データにアクセスするための新しいaccess_tokenを取得します。コード ブロック内のコードを参照してください。public async Task<IActionResult> Post(ViewModel model)

どちらの場合も、 Postman からセキュア/アクションユーザー/データアクションの両方を要求するために使用できる正しいトークンを取得しましたが、HttpClient は Unauthorized 応答 (401) を取得しています。

応答ヘッダーのスクリーンショット

私は何を間違っていますか?

4

1 に答える 1