【问题标题】:CORS issue with UseOpenIdConnectAuthenticationUseOpenIdConnectAuthentication 的 CORS 问题
【发布时间】:2019-10-14 22:06:39
【问题描述】:

这里 Angularjs 是前端,Web API 是中间层。我们正在使用 AzureAD OpenID 连接进行身份验证。
我面临以下问题。因为我的着陆页没有加载

从源“https%3A%”访问“https://login.microsoftonline.com/xx-86f1-41af-91ab-xxx/oauth2/authorize?client_id=xxxx1&response_mode=form_post&response_type=code%20id_token&scope=openid%20profile&state=OpenIdConnect.AuthenticationPropertiesxxxxx&noncexxxxx&redirect_uri=https%3A%2F%2Flocalhost%3A44300%2F&x-client-SKU=ID_NET451&x-client-ver=5.2.1.0”处的 XMLHttpRequest(重定向自“https%3A%2F%2Flocalhost%3A44300%2F/api/Scorecard/GetServiceNameWithManagers?loginUser=xxx@microsoft.com”) 2F%2Flocalhost%3A44300%2F' 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。

我做了很多研究,并在请求和响应中应用了 Access-Control-Allow-Origin =*。还应用了 app.UseCors(Owin.Cors.CorsOptions.AllowAll); 但到目前为止还没有成功。

考虑以下代码,即使用户登录到 Microsoft 站点,AuthorizationCodeReceived 委托也不是第一次调用。

请注意,此代码不是第一次运行。单击几次按钮(回发)后它将起作用,然后如果我们运行应用程序几分钟后它会引发 CORS 预检问题。请帮忙。

这是我的startup.cs

    public void Configuration(IAppBuilder app)
    {
        app.UseCors(Owin.Cors.CorsOptions.AllowAll);
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "Cookies",
            CookieManager = new SystemWebChunkingCookieManager(),              
        });

        //// Bearer token authentication middleware.(Ex: request from web clients,ajax calls able to pass authenticated bearer info)
        app.UseWindowsAzureActiveDirectoryBearerAuthentication(
          new WindowsAzureActiveDirectoryBearerAuthenticationOptions
          {
              TokenValidationParameters = new TokenValidationParameters
              {
                  ValidAudience = ConfigurationManager.AppSettings["ida:Audience"],
                  TokenReplayCache = new TokenReplayCache(new MemoryCacheProvider())
              },
              Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
              Provider = new OAuthBearerAuthenticationProvider
              {
                  OnValidateIdentity = ctx =>
                  {
                      //// Retrieve user roles from the request.                                  
                      var authenticationTicket = ctx.Ticket;
                      if (authenticationTicket.Identity.IsAuthenticated)
                      {
                          ////Use the block when role/user specific authorization needs and to modify the user identity claims based on requirement
                      }

                      return Task.FromResult(0);
                  },
                  OnRequestToken = ctx => { return Task.FromResult(0); }
              }
          });

        //// Non Bearer authentication middleware. (Ex: request secured web api call directly from URL/Web API server scope it self)
        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = ClientId,
                ClientSecret = ConfigurationManager.AppSettings["ida:AppKey"],
                Authority = Authority,
                PostLogoutRedirectUri = PostLogoutRedirectUri,
                AuthenticationMode = AuthenticationMode.Active,
                ResponseType = "code id_token",
                CallbackPath = new PathString("/"),


                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    SecurityTokenValidated = context =>
                    {
                        if (context.AuthenticationTicket.Identity.IsAuthenticated)
                        {
                            ////Use the block when role/user specific authorization needs and to modify the user identity claims based on requirement
                        }

                        return Task.FromResult(0);
                    },
                    AuthorizationCodeReceived = async context =>
                    {
                        var code = context.Code;
                        ClientCredential credential = new ClientCredential(ClientId, Models.ConfigurationData.GraphSecret);
                        string userObjectID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
                        AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID));
                        Uri uri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));
                        AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, uri, credential, GraphResource);
                    },
                    RedirectToIdentityProvider = context =>
                    {

                        if (context.ProtocolMessage.RedirectUri == null)
                        {
                            ////To set the reply/redirect Url based on the request host environment. 
                            ////Hosting env details we get only through the owin context in startup and this is the delegate to set reply URL in OWincontext before the authentication. 
                            string ReplyAddress = context.Request.Scheme + "://" + context.Request.Host + "/";
                            context.ProtocolMessage.RedirectUri = ReplyAddress;
                        }
                        //context.OwinContext.Authentication.User.Identity.IsAuthenticated = true;
                        if (context.OwinContext.Authentication.User.Identity.IsAuthenticated && context.ProtocolMessage.RequestType != IdentityModel.Protocols.OpenIdConnect.OpenIdConnectRequestType.Logout)
                        {
                            ////To avoid infinite loop of redirections in request if user is authenticated and unauthorized.  
                            context.HandleResponse();
                            context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                        }

                        return Task.FromResult(0);
                    }
                },
                TokenValidationParameters = new TokenValidationParameters
                {
                    RoleClaimType = "roles",
                    TokenReplayCache = new TokenReplayCache(new MemoryCacheProvider())
                },
            });
        System.Web.Helpers.AntiForgeryConfig.UniqueClaimTypeIdentifier = System.IdentityModel.Claims.ClaimTypes.NameIdentifier;
    }

从源“https%3A%”访问“https://login.microsoftonline.com/xx-86f1-41af-91ab-xxx/oauth2/authorize?client_id=xxxx1&response_mode=form_post&response_type=code%20id_token&scope=openid%20profile&state=OpenIdConnect.AuthenticationPropertiesxxxxx&noncexxxxx&redirect_uri=https%3A%2F%2Flocalhost%3A44300%2F&x-client-SKU=ID_NET451&x-client-ver=5.2.1.0”处的 XMLHttpRequest(重定向自“https%3A%2F%2Flocalhost%3A44300%2F/api/Scorecard/GetServiceNamxxxManagers?loginUser=xxx@microsoft.com”) 2F%2Flocalhost%3A44300%2F' 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。

【问题讨论】:

  • VMK,你检查我的答案了吗?它有帮助还是您以其他方式解决了您的问题?
  • 感谢 cmets。在下面查看我的 cmets

标签: c# asp.net-web-api openid-connect


【解决方案1】:

我认为您误解了错误消息。它说您的 AngularJS 应用程序试图向 https://login.microsoftonline.com/xxx-xx-41af-91ab-xxx/oauth2/authorize 发出请求但失败了,因为它是一个跨域请求,并且服务器没有通过返回 Access-Control-Allow-Origin 标头来响应预检请求(HTTP方法选项)。

因此,您无法通过将 CORS 标头添加到后端来更改它。 authorize 并非设计为由 XMLHttpRequest 请求调用 - 您应该对该 URL 发出完整的浏览器请求。稍后,浏览器将被重定向到redirect_uri(请求参数值)以及验证码或错误。

【讨论】:

  • 暂时修复如下解决方案...如果触发了 Cors 起源问题的 catch 块(在 angularjs 处),则 window.open('login.microsoftonline.com/xxx-xx-41af-91ab-xxx/oauth2/…) 几秒钟然后关闭窗口并重定向到实际的 API .. 我已经在 web api 端应用了所有方法。在 angualrjs 也使用了 adal.js,但没有任何效果。这是我为解决此问题所做的唯一愚蠢的修复:(如果您有任何解决方案,请告诉我
  • @VMK 你能分享一下你是如何用代码解决这个问题的吗?
  • @Tassisto 它没有解决,它不经常发生,因此,作为一个临时修复,每当我遇到 CORS 问题时,只需重新加载登录页面
猜你喜欢
  • 2021-10-27
  • 2017-09-24
  • 1970-01-01
  • 2018-04-04
  • 2015-06-29
  • 2021-11-16
  • 2017-04-22
  • 2017-04-13
相关资源
最近更新 更多