[英]Getting 401 from custom Api when using Microsoft.Identity.platform to protect api
我正在按照 Microsfot.document 中的教程學習如何使用 Azure AD (Microsoft Identity) 保護 api。
我采取的步驟如下: 抱歉,我嘗試提供可能有用的信息,但大多數時候貢獻者要求提供屏幕截圖或代碼的信息太多,無法解決問題。
我遵循了幾個文檔和視頻教程,但這是其中一個的鏈接: https://learn.microsoft.com/en-us/learn/modules/identity-secure-custom-api/2-secure-api-microsoft -身份
WebAPI。
Webapp 使用 .net(classic) 創建的 webapp 請注意,webapi 是核心 5。
配置: 1.從Azure AD->Registration for Webapi->選擇application(web app created above)並給scope權限。
2.對於Azure AD->Registration for webapp->Access permission->delegate->selected the scope.
測試: 1.運行測試。 這一點; 我正在調用的 api 方法上沒有 [Authorization]。 2. Webapp 成功獲取了 api 返回的字符串。我有點覺得管道是正確的。
我已經多次檢查並查看了多個教程並重寫了我的代碼,觀看了幾個視頻並更新了我的代碼但我總是遇到 401 錯誤。
下面是代碼; Api controller:
namespace Utility.Controllers
{
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class AzAdUtility : ControllerBase
{
// GET: api/<AzAdUtility>
[HttpGet]
public string Get()
{
//HttpContext.VerifyUserHasAnyAcceptedScope(new string[] {"check"});
var name = "Vaqas";
return name;
}
}
}
Api 啟動:public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; }
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "GlobalNetApiUtility", Version = "v1" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Utility v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Api 應用設置:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "myorg.onmicrosoft.com",
"ClientId": "abcd.............................",
"TenantId": "dabcd.............................."
},
Webapp 啟動:只添加啟動頁面,因為起初我在 OnAuthorizationCodeReceived 中獲取一些用於測試目的的數據。
public class Startup
{
// The Client ID is used by the application to uniquely identify itself to Azure AD.
static string clientId = System.Configuration.ConfigurationManager.AppSettings["ClientId"];
// RedirectUri is the URL where the user will be redirected to after they sign in.
string redirectUri = System.Configuration.ConfigurationManager.AppSettings["RedirectUri"];
// Tenant is the tenant ID (e.g. contoso.onmicrosoft.com, or 'common' for multi-tenant)
static string tenant = System.Configuration.ConfigurationManager.AppSettings["Tenant"];
// Authority is the URL for authority, composed by Microsoft identity platform endpoint and the tenant name (e.g. https://login.microsoftonline.com/contoso.onmicrosoft.com/v2.0)
string authority = String.Format(System.Globalization.CultureInfo.InvariantCulture, System.Configuration.ConfigurationManager.AppSettings["Authority"], tenant);
//string authority = "https://login.microsoftonline.com/" + tenant + "/adminconsent?client_id=" + clientId;
string clientSecret = System.Configuration.ConfigurationManager.AppSettings["ClientSecret"];
/// <summary>
/// Configure OWIN to use OpenIdConnect
/// </summary>
/// <param name="app"></param>
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
// Sets the ClientId, authority, RedirectUri as obtained from web.config
ClientId = clientId,
Authority = authority,
RedirectUri = redirectUri,
// PostLogoutRedirectUri is the page that users will be redirected to after sign-out. In this case, it is using the home page
PostLogoutRedirectUri = redirectUri,
Scope = OpenIdConnectScope.OpenIdProfile,
// ResponseType is set to request the code id_token - which contains basic information about the signed-in user
//ResponseType = OpenIdConnectResponseType.CodeIdToken,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
// OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to OnAuthenticationFailed method
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
AuthenticationFailed = OnAuthenticationFailed
}
}
);
}
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
{
notification.HandleCodeRedemption();
var idClient = ConfidentialClientApplicationBuilder.Create(clientId)
.WithRedirectUri(redirectUri)
.WithClientSecret(clientSecret)
.WithAuthority(authority)
.Build();
try
{
var apiScope = "api://28......................../check2 api://28................/check api://28...........................1d/AzAdUtility.Get";
string[] scopes = apiScope.Split(' ');
//gettig the token no issues.
var result = await idClient.AcquireTokenByAuthorizationCode(
scopes, notification.Code).ExecuteAsync();
var myurl = "https://localhost:99356/api/AzAdUtility";
var client = new HttpClient();
// var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(Constants.ProductCatalogAPI.SCOPES);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken); //accessToken
var json = await client.GetStringAsync(myurl);
var serializerOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
//getting 401 response
var checkResponse = JsonSerializer.Deserialize(json, typeof(string), serializerOptions) as string;
}
catch (Exception ex)
{
string message = "AcquireTokenByAuthorizationCodeAsync threw an exception";
notification.HandleResponse();
notification.Response.Redirect($"/Home/Error?message={message}&debug={ex.Message}");
}
}
/// <summary>
/// Handle failed authentication requests by redirecting the user to the home page with an error in the query string
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
{
context.HandleResponse();
context.Response.Redirect("Error/AccessDenied/?errormessage=" + context.Exception.Message);
return Task.FromResult(0);
}
}
在 Api 啟動 class 中,我缺少app.UseAuthentication()
。
我從沒想過這會成為一個問題。 一旦我添加了這段代碼。 我得到了預期的響應,而不是 401 未經授權的錯誤
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.