简体   繁体   English

使用 Microsoft.Identity.platform 保护 api 时从自定义 Api 获取 401

[英]Getting 401 from custom Api when using Microsoft.Identity.platform to protect api

I am following the tutorial from Microsfot.document for how to protect api using Azure AD (Microsoft Identity).我正在按照 Microsfot.document 中的教程学习如何使用 Azure AD (Microsoft Identity) 保护 api。

The steps I took are following: Sorry I tried to put information that might be helpful but too much to get to the issue most of the time contributors ask for screenshot or the code.我采取的步骤如下: 抱歉,我尝试提供可能有用的信息,但大多数时候贡献者要求提供屏幕截图或代码的信息太多,无法解决问题。

I followed several documents and video tutorials but here is the link for one of them: https://learn.microsoft.com/en-us/learn/modules/identity-secure-custom-api/2-secure-api-microsoft-identity我遵循了几个文档和视频教程,但这是其中一个的链接: https://learn.microsoft.com/en-us/learn/modules/identity-secure-custom-api/2-secure-api-microsoft -身份

WebApi. WebAPI。

  1. Created a webapi using core 5. Register it in Azure AD.使用核心 5 创建了一个 webapi。在 Azure AD 中注册它。
  2. Created single scope 'check' and allowed permission to user and admin.创建单个 scope 'check' 并授予用户和管理员权限。

Webapp Created webapp using .net(classic) Note that webapi is core 5. Webapp 使用 .net(classic) 创建的 webapp 请注意,webapi 是核心 5。

  1. Created a webapp and register it in Azure AD.创建了一个 webapp 并在公元 Azure 注册了它。
  2. Setup the authentication and created a OnAuthorizationCodeReceived to get the access token to call the api.设置身份验证并创建 OnAuthorizationCodeReceived 以获取访问令牌以调用 api。

Configuration: 1.From Azure AD->Registration for Webapi-> selected application(web app created above) and give permission to the scope.配置: 1.从Azure AD->Registration for Webapi->选择application(web app created above)并给scope权限。

在此处输入图像描述 2. For Azure AD->Registration for webapp-> Access permission->delegate->selected the scope. 2.对于Azure AD->Registration for webapp->Access permission->delegate->selected the scope. 在此处输入图像描述

Test: 1.Run the test.测试: 1.运行测试。 At this point;这一点; I do not have [Authorization] on the api method which I am calling.我正在调用的 api 方法上没有 [Authorization]。 2. Webapp successfully able to get the string which is returned by the api. Somewhat I get the idea that plumbing was right. 2. Webapp 成功获取了 api 返回的字符串。我有点觉得管道是正确的。

  1. Added [Authorize] filter on the app method.在 app 方法上添加了 [Authorize] 过滤器。
  2. Result 401 unauthorized.结果 401 未经授权。

I have checked multiple times and looked at multiple tutorial and rewrote my code, watched several videos and updated my code but I am always getting 401 error.我已经多次检查并查看了多个教程并重写了我的代码,观看了几个视频并更新了我的代码但我总是遇到 401 错误。

Below is the code;下面是代码; Api controller: 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 startup: public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; 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 Appsettings: Api 应用设置:

"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "myorg.onmicrosoft.com",
"ClientId": "abcd.............................",
"TenantId": "dabcd.............................."

}, },

Webapp startup: Only adding startup page because at first all I am doing getting some data for testing purpose in the OnAuthorizationCodeReceived. 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);
        }
    }

In Api startup class I was missing app.UseAuthentication() .在 Api 启动 class 中,我缺少app.UseAuthentication()
I never really thought that would be an issue.我从没想过这会成为一个问题。 Once I added this code.一旦我添加了这段代码。 I got the expected response rather than 401 Unauthorized error我得到了预期的响应,而不是 401 未经授权的错误

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Web API-使用CORS保护GET不受锚标记的影响 - Web API - Protect GET from anchor tag using CORS 使用身份服务器 4 保护 asp.net web api 2 项目 - protect asp.net web api 2 project with identity server 4 来自 Android 设备的大量请求时,WEB API 2 上的错误 401 - Error 401 on WEB API 2 when there is lot of request from Android device 使用HttpResponseMessage时,不会从Web API获得任何响应 - Getting absolutely no response from Web API when using HttpResponseMessage WEB API - 如何使用身份为用户中的自定义属性添加值 - WEB API - how to add value to custom property in User using identity .net 4.6 web api2 401 未经身份服务器授权 4 - .net 4.6 web api2 401 Unauthorized with identity server 4 是否可以将自定义加密应用于Microsoft Web API? - Is is possible to apply custom encryption to Microsoft Web API? 使用身份从 Web Api 2 中的数据库中删除用户 - Delete user from database in Web Api 2 using Identity MVC 5 Identity 2和Web API 2授权以及使用承载令牌的呼叫api - MVC 5 Identity 2 and Web API 2 authorization and call api using bearer token Web API Getting 401在IIS中未经授权但在IIS Express中有效 - Web API Getting 401 Unauthorized in IIS but works in IIS Express
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM