Итак, у меня есть решение со следующими проектами: - MVC для моего Сервера авторизации (Identity Server с Identity) - Клиент MVC - API MVC
Я пытаюсь добиться того, чтобы пользователь подключился кКлиент 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";
}
}
Поэтому, когда я запускаю свое решение и получаю доступ к / tenant в своем MVC-клиенте, он перенаправляет меня на сервер авторизации, где мне необходимо войти в систему, а затем я возвращаюсь в MVC-клиент.Эта часть работает нормально.
Но мой звонок в мой API возвращает мне 401 несанкционированный.
Я проверил, есть ли у меня токен доступа в контроллере клиента, и я его получил, дляпример:
1037 * eyJhbGciOiJSUzI1NiIsImtpZCI6IjJFMzdFNzQ5N0RCODI4QzRFNzdFQUI4NTE4MDU3OUZGQ0IwMDgwMTAiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJMamZuU1gyNEtNVG5mcXVGR0FWNV84c0FnQkEifQ.eyJuYmYiOjE1NDQ3MDQ1OTksImV4cCI6MTU0NDcwODE5OSwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzMzQiLCJhdWQiOlsiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzMzQvcmVzb3VyY2VzIiwiRWNoaW5vTWFuYWdlckFQSSJdLCJjbGllbnRfaWQiOiJFY2hpbm9NYW5hZ2VyTVZDIiwic3ViIjoiNWMxMjMyZTIzYWExODE3MGVjYTJmMjdlIiwiYXV0aF90aW1lIjoxNTQ0NzA0NTk5LCJpZHAiOiJsb2NhbCIsImVtYWlsIjoic3RlcGhhbmUubWFydGlnbmllcjFAd2l0Y2hsYWtlLmNoIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsImVjaGlub21hbmFnZXJhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhbXIiOlsicHdkIl19.g61xKFcROTDuw_rmFWLHKSoJIIhyzzil-hPK44PvCioKVeeKB3ZrKtmNvw0aa240e_6Y6X2r3QZ2CR0V3T-lZmAJeIm0oN8MznUNjKB-h5FxxVvwwnbBU3_HYS5fNIl6XhKeOZGsIU-ZNBYBZ3FrDwrLPm3uHXVYyCQ5X1ZAldjV1HJ_th6T-PEdQozHZn37EXcqakU4uY1RpiT_ZEMFnllXWZVFBYCEy3OsOmAv5NlD5jkUp2XeuCoQ5vsT1XhO2Qkj5HS398MmJp0wObs-V1dUz2iKVjbQzo3eHZo3lsEiqKfg5lpTxrQHm07sGuyB84utuPYrKFCI_4nkeHF9tM9SEF1Au0DbD2O2nWYUoxa7RjFlMLxOu1uH6FNLYzBlbhbPsB9rhLK0byySmZM5bAaVHC4e71iyI2ZHJJx_K7VuHkAmqoraJ5KtcJB-zAdkKserdUc7xcPI9scIQpGf28EdrWG_xKUc1OjjtvZApJmKiDc7REFGiAIRA6xm20PSaySEyrQjb2nQxDer9f04bBhignb02NRC_n8sLciw7cOM4yVBW5FKHj_7jCTzU6U1XY65-UX0z_pKkvrxtqJpRl8JexEU7c6XQ6FcCwXB6TKxhZ7NzjgS6vmSMRXrEBEgtnWqrZv5A_sA7yhVeLHbSfx94nPUc4ru6POWbSzFja8 1039 * (используйте JWT.io для просмотра содержимого) 1041 * Очевидно, у меня есть проблема с аудиторией валидации, потому что в моем журнале я могу найти.:
"Проверка аудитории не удалась.Аудитория: «https://localhost:44334/resources, EchinoManagerAPI».Не соответствует: validationParameters.ValidAudience: 'EchinoManagerMVC' или validationParameters.ValidAudiences: 'null'. "
Поэтому мой вопрос: чего мне не хватает в моей конфигурации, поэтому я могу использовать access_token, предоставленный сервером авторизациипозвонить по моему API?
Заранее спасибо