【问题标题】:Need help adjusting ASP.NET that uses Azure AD to also allow SSO from third party需要帮助调整使用 Azure AD 的 ASP.NET 以允许来自第三方的 SSO
【发布时间】:2020-04-22 23:19:27
【问题描述】:

我们有一个 ASP.NET 应用程序,它使用 Microsoft 的通用登录来登录用户,然后它重定向回我们的 Web 应用程序(在 Azure 中)。身份验证连接到 Azure Active Directory。它是具有多个 Azure AD 的多租户应用程序。当 Microsoft 重定向回我们的网站时,我们会使用这些信息来创建用于网络调用的 cookie。此外,回调返回我们用来获取令牌的用户代码。这被用作针对我们的 API 控制器的身份验证。

这已经工作了很长时间。然而,现在我们需要与另一个将推出我们产品的第三方门户网站集成。他们将使用 SAML 进行 SSO。它们未与 Azure AD 集成。因此,我们的想法是通过 SAML 断言验证用户。这将包含我们想要“登录”的用户名。

我可以根据这些信息创建 cookie,并且可以很好地与我们的 Web 控制器调用配合使用。但是,由于我没有收到来自 Azure AD 的回调,因此我没有 API 调用的令牌。我曾尝试调用 Azure AD 对应用程序进行身份验证,但这似乎满足 API 控制器的授权。具体来说, RequestContext.Principal.Identity 似乎没有使用这种模式设置。

我已使用此代码设置 cookie 身份验证:

app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

var cookieOptions = new CookieAuthenticationOptions
{
    ExpireTimeSpan = TimeSpan.FromDays(14),
    SlidingExpiration = true,
    LoginPath = new PathString("/home/login"),
    AuthenticationType = "ApplicationCookie",
    AuthenticationMode = AuthenticationMode.Active,
    CookieHttpOnly = true,
    CookieSecure = CookieSecureOption.Always,
    CookieSameSite = SameSiteMode.Lax,
};

// Forms/Cookie Authentication
app.UseCookieAuthentication(cookieOptions);

我留下了持有者令牌认证代码,如下所示:

// Bearer Token Authentication used for API access
BearerAuthenticationOptions = new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
    Tenant = <application tenant id>,
    AuthenticationType = OAuthDefaults.AuthenticationType,
    // Disable Issuer validation. We'll validate the Isuuer in the ClaimsAuthorizationFilter.
    TokenValidationParameters = new TokenValidationParameters
    {
        ValidAudience = <resource id>,
        ValidateIssuer = false
    },

};

app.UseWindowsAzureActiveDirectoryBearerAuthentication(BearerAuthenticationOptions);

处理 Azure AD 身份验证(SAML 登录应替换)的代码是:

var openIdConnectOptions = new OpenIdConnectAuthenticationOptions {     ClientId = <ClientId>,  Authority = "https://login.windows.net/common/",    // setting this to false uses the cookie expiration instead     UseTokenLifetime = false,   TokenValidationParameters = new TokenValidationParameters   {       // we'll validate Issuer on the SecurityTokenValidated notification below       ValidateIssuer = false  },

    Notifications = new OpenIdConnectAuthenticationNotifications    {       // An AAD auth token is validated and we have a Claims Identity         SecurityTokenValidated = context =>         {           ... additional validation is performed here...

            return Task.FromResult(0);      },

        //the user has just signed in to the external auth provider (AAD) and then were redirected here         // with an access code that we can use to turn around and acquire an auth token         AuthorizationCodeReceived = context =>      {           var code = context.Code;            var identity = context.AuthenticationTicket.Identity;

            var appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;          // causes the retreived API token to be cached for later use            TokenService.GetUserLevelTokenFromAccessCode(new HttpUserSessionWithClaimsId(identity), code, <ApiResourceId>, new Uri(appBaseUrl));

            return Task.FromResult(0);      },      // We are about to redirect to the identity provider (AAD)      RedirectToIdentityProvider = context =>         {           // This ensures that the address used for sign in and sign out is picked up dynamically from the request            // Remember that the base URL of the address used here must be provisioned in Azure AD beforehand.          var appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;          context.ProtocolMessage.RedirectUri = appBaseUrl + "/";             context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;

            context.HandleResponse();

            return Task.FromResult(0);      },      // Something went wrong during this auth process        AuthenticationFailed = context =>       {           if (context.Exception is Microsoft.IdentityModel.Protocols.OpenIdConnect
                .OpenIdConnectProtocolInvalidNonceException)            {
                //This is a message we can't do anything about, so we want to ignore it.
                Log.Info("AuthenticationFailed in OpenIdConnectAuthentication middleware", context.Exception);          }           else            {
                Log.Error("AuthenticationFailed in OpenIdConnectAuthentication middleware",
                    context.Exception);             }

            // IDX10205 == Tenant validation failed             var message = (context.Exception.Message.StartsWith("IDX10205"))
                ? InvalidTenantMessage
                : GenericErrorMessage;

            context.OwinContext.Response.Redirect("/?Error=" + Uri.EscapeDataString(message));          context.HandleResponse(); // Suppress the exception             return Task.FromResult(0);      },      MessageReceived = context =>        {           if (!string.IsNullOrWhiteSpace(context.ProtocolMessage.Error))          {
                // AADSTS65004 == user did not grant access in OAuth flow
                Log.Error("MessageReceived containing error in OpenIdConnectAuthentication middleware. \nError: {0}\nDescription: {1}"
                        .FormatWith(context.ProtocolMessage.Error, context.ProtocolMessage.ErrorDescription));
                //context.OwinContext.Response.Redirect("/");
                //context.HandleResponse(); // Suppress the exception           }           return Task.FromResult(0);      }   } };

app.UseOpenIdConnectAuthentication(openIdConnectOptions);

任何帮助将不胜感激。

【问题讨论】:

    标签: c# asp.net azure


    【解决方案1】:

    原来我在 cookie 中设置的 AuthenticationType 值导致了断开连接。一旦我解决了这个问题,数据就通过了。所以结束他的问题。 谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-11
      • 2013-09-10
      • 2011-09-04
      • 2017-06-02
      相关资源
      最近更新 更多