簡體   English   中英

IdentityServer調用API,其令牌已傳遞到MVC客戶端,並帶有混合流

[英]IdentityServer call API with token delivered to MVC client wit hybrid flow

因此,我有以下項目的解決方案:-用於授權服務器的MVC(具有身份的身份服務器)-MVC客戶端-MVC API

我想要實現的目標是讓用戶在授權服務器的幫助下在MVC客戶端中進行連接,然后使用提供的訪問令牌來調用我的API。

所以我有以下配置:

授權服務器:

在Startup.cs中:

            // Add Identity Server 4
        services.AddIdentityServer()
            .AddSigningCredential(cert)
            .AddInMemoryPersistedGrants()
            .AddClientStore<ClientStore>()
            .AddResourceStore<ResourceStore>()
            .AddAspNetIdentity<User>();

        services.AddAuthentication().AddMicrosoftAccount(microsoftOptions =>
        {
            microsoftOptions.ClientId = Configuration["Authentication:Microsoft:ApplicationId"];
            microsoftOptions.ClientSecret = Configuration["Authentication:Microsoft:Password"];
        });

客戶端配置:

new Client
            {
                ClientId = "EchinoManagerMVC",
                ClientName = "MVC for Echino Manager",
                AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

                ClientSecrets =
                {
                    new Secret("EchinoManagerMVCSecret".Sha256())
                },

                // where to redirect to after login
                RedirectUris = { "https://localhost:44380/signin-oidc" },

                // where to redirect to after logout
                PostLogoutRedirectUris = { "https://localhost:44380/signout-callback-oidc" },

                AllowedScopes = new List<string>
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    "echinomanagerapi"
                },
                AllowOfflineAccess = true,
                AlwaysIncludeUserClaimsInIdToken = true,
                AlwaysSendClientClaims = true,
                RequireConsent = false
            }

我的APIResource:

                new ApiResource
            {
                Name = "EchinoManagerAPI",
                ApiSecrets =
                {
                    new Secret("EchinoManagerAPISecret".Sha256())
                },

                UserClaims =
                {
                    JwtClaimTypes.Email
                },

                Scopes =
                {
                    new Scope()
                    {
                        Name = "echinomanagerapi",
                        DisplayName = "Access to the API of Echino Manager"
                    }
                }
            }

在我的MVC客戶端中:

Startup.cs:

public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = "Cookies";
            options.DefaultChallengeScheme = "oidc";
        })
        .AddCookie("Cookies")
        .AddOpenIdConnect("oidc", options =>
        {
            options.SignInScheme = "Cookies";

            options.Authority = Configuration["ApplicationOptions:AuthorizeServer"];

            options.ClientId = Configuration["ApplicationOptions:ClientId"];
            options.ClientSecret = Configuration["ApplicationOptions:ClientSecret"];
            options.ResponseType = "code id_token";
            options.SaveTokens = true;
            options.GetClaimsFromUserInfoEndpoint = true;

            options.Scope.Add("echinomanagerapi");
            options.Scope.Add("offline_access");
        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

在我的控制器中調用API:

    [Authorize]
public class TenantController : Controller
{
    public async Task<IActionResult> Index()
    {
        var accessToken = await HttpContext.GetTokenAsync("access_token");

        var client = new HttpClient();

        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        //var content = await client.GetStringAsync("https://loginservices.echino2.p.azurewebsites.net/echinoapi/tenant");
        //var content = await client.GetStringAsync("https://localhost:44366/echinoapi/tenant");
        var content = await client.GetStringAsync("https://localhost:44300/api/values");

        ViewBag.Json = JArray.Parse(content).ToString();
        return View();
    }
}

在我的MVC API中:

        public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        services.AddAuthorization();

        services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = Configuration["ApplicationOptions:AuthorizeServer"];
            options.ApiName = Configuration["ApplicationOptions:ApiName"];
            options.ApiSecret = Configuration["ApplicationOptions:ApiSecret"];
        });
    }

控制器:

    [Route("api/[controller]")]
[ApiController]
[Authorize(AuthenticationSchemes = "Bearer")]
public class ValuesController : ControllerBase
{
    // GET api/values
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        return new string[] { "value1", "value2" };
    }

    // GET api/values/5
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
        return "value";
    }
}

因此,當我啟動解決方案並在MVC客戶端中訪問/ tenant時,它會將我重定向到必須登錄的授權服務器,然后又回到MVC客戶端中。 這部分工作正常。

但是我對API的調用返回了未經授權的401。

我檢查了我的租戶控制器中是否有訪問令牌,例如,我得到了一個:

eyJhbGciOiJSUzI1NiIsImtpZCI6IjJFMzdFNzQ5N0RCODI4QzRFNzdFQUI4NTE4MDU3OUZGQ0IwMDgwMTAiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJMamZuU1gyNEtNVG5mcXVGR0FWNV84c0FnQkEifQ.eyJuYmYiOjE1NDQ3MDQ1OTksImV4cCI6MTU0NDcwODE5OSwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzMzQiLCJhdWQiOlsiaH​​R0cHM6Ly9sb2NhbGhvc3Q6NDQzMzQvcmVzb3VyY2VzIiwiRWNoaW5vTWFuYWdlckFQSSJdLCJjbGllbnRfaWQiOiJFY2hpbm9NYW5hZ2VyTVZDIiwic3ViIjoiNWMxMjMyZTIzYWExODE3MGVjYTJmMjdlIiwiYXV0aF90aW1lIjoxNTQ0NzA0NTk5LCJpZHAiOiJsb2NhbCIsImVtYWlsIjoic3RlcGhhbmUubWFydGlnbmllcjFAd2l0Y2hsYWtlLmNoIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsImVjaGlub21hbmFnZXJhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhbXIiOlsicHdkIl19.g61xKFcROTDuw_rmFWLHKSoJIIhyzzil-hPK44PvCioKVeeKB3ZrKtmNvw0aa240e_6Y6X2r3QZ2CR0V3T-lZmAJeIm0oN8MznUNjKB-h5FxxVvwwnbBU3_HYS5fNIl6XhKeOZGsIU-ZNBYBZ3FrDwrLPm3uHXVYyCQ5X1ZAldjV1HJ_th6T-PEdQozHZn37EXcqakU4uY1RpiT_ZEMFnllXWZVFBYCEy3OsOmAv5NlD5jkUp2XeuCoQ5vsT1XhO2Qkj5HS398MmJp0wObs-V1dUz2iKVjbQzo3eHZo3lsEiqKfg5lpTxrQHm07sGuyB84utuPYrKFCI_4nkeHF9tM9SEF1Au0DbD2O2nWYUoxa7RjFlMLxOu1uH 6FNLYzBlbhbPsB9rhLK0byySmZM5bAaVHC4e71iyI2ZHJJx_K7VuHkAmqoraJ5KtcJB-zAdkKserdUc7xcPI9scIQpGf28EdrWG_xKUc1OjjtvZApJmKiDc7REFGiAIRA6xm20PSaySEyrQjb2nQxDer9f04bBhignb02NRC_n8sLciw7cOM4yVBW5FKHj_7jCTzU6U1XY65-UX0z_pKkvrxtqJpRl8JexEU7c6XQ6FcCwXB6TKxhZ7NzjgS6vmSMRXrEBEgtnWqrZv5A_sA7yhVeLHbSfx94nPUc4ru6POWbSzFja8

(使用JWT.io查看內容)。

顯然,驗證受眾存在問題,因為在我的日志中可以找到:

“聽眾驗證失敗。聽眾:' https:// localhost:44334 / resources ,EchinoManagerAPI'。不匹配:validationParameters.ValidAudience:'EchinoManagerMVC'或validationParameters.ValidAudiences:'null'。”

所以我的問題是:我的配置中缺少什么,因此我可以使用授權服務器提供的access_token來調用我的API?

提前致謝

這里同樣的問題,但你可以代替

.AddIdentityServerAuthentication(options =>
    {
        options.Authority = Configuration["ApplicationOptions:AuthorizeServer"];
        options.ApiName = Configuration["ApplicationOptions:ApiName"];
        options.ApiSecret = Configuration["ApplicationOptions:ApiSecret"];
    });

采用

     .AddJwtBearer(options =>
        {
            options.Authority = Configuration["ApplicationOptions:AuthorizeServer"];
            options.RequireHttpsMetadata = false;
            options.Audience = "api1";
        });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM