asp.net-mvc - 将参数传递给 Azure Active Directory 身份验证

标签 asp.net-mvc azure oauth owin azure-active-directory

我有一个 ASP.Net MVC 应用程序 Owin,并且我也在使用 Azure Active Directory 身份验证。

我想在用户重定向到 Azure AD 身份验证页面时传递参数。因此,当用户登录或注册时,我想将 ProjectId (int) 作为参数传递。

用户登录/注册并重定向到我的应用程序后,我希望接收作为参数传递的 ProjectId

我怎样才能实现这一目标?

编辑:添加代码

// The ACR claim is used to indicate which policy was executed
public const string AcrClaimType = "http://schemas.microsoft.com/claims/authnclassreference";
public const string PolicyKey = "b2cpolicy";
private const string OidcMetadataSuffix = "/.well-known/openid-configuration";

public void ConfigureAuth(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions());

    OpenIdConnectAuthenticationOptions options = new OpenIdConnectAuthenticationOptions
    {
        // These are standard OpenID Connect parameters, with values pulled from web.config
        ClientId = ClientId,
        RedirectUri = RedirectUri,
        PostLogoutRedirectUri = RedirectUri,
        UseTokenLifetime = false,
        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            AuthenticationFailed = AuthenticationFailed,
            RedirectToIdentityProvider = OnRedirectToIdentityProvider,
            SecurityTokenValidated = OnSecurityTokenValidated
        },
        Scope = "openid",
        ResponseType = "id_token",

        // The PolicyConfigurationManager takes care of getting the correct Azure AD authentication
        // endpoints from the OpenID Connect metadata endpoint.  It is included in the PolicyAuthHelpers folder.
        ConfigurationManager = new PolicyConfigurationManager(
            string.Format(CultureInfo.InvariantCulture, AadInstance, Tenant, "/v2.0", OidcMetadataSuffix),
            new[] { SignUpPolicyId, SignInPolicyId, ProfilePolicyId }),

        // This piece is optional - it is used for displaying the user's name in the navigation bar.
        TokenValidationParameters = new TokenValidationParameters
        {
            NameClaimType = "name"
        }
    };

    app.UseOpenIdConnectAuthentication(options);
}

private Task OnRedirectToIdentityProvider(
        RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
    if (notification.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
    {
        var currentPolicy =
            notification.OwinContext.Authentication.AuthenticationResponseRevoke.AuthenticationTypes
                .FirstOrDefault(x => x.StartsWith("b2c"));
        notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.Split('?')[0];
        notification.ProtocolMessage.Parameters.Add("p", currentPolicy);
    }
    else
    {
        **// The value right now for the state is sort of "hijacked" and assigned by Microsoft**
        //notification.ProtocolMessage.Parameters["state"] = "OpenIdConnect.AuthenticationProperties=sRt-teBcxsd239viWo...... ";

        var currentPolicy = notification.OwinContext.Authentication.AuthenticationResponseChallenge.Properties
            .Dictionary[PolicyKey];
        notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.Split('?')[0];
        notification.ProtocolMessage.Parameters.Add("p", currentPolicy);
    }

    return Task.FromResult(0);
}

private async Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
    await MyClass.CreatePrincipal(notification.AuthenticationTicket.Identity);
}

private Task AuthenticationFailed(
            AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
    notification.HandleResponse();
    notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message);
    return Task.FromResult(0);
}

最佳答案

与 Gaurav 的建议类似,但添加了一些特殊注意事项。基本上,状态由 Owin 中间件使用,因此虽然您可以注入(inject)自己的东西,但您需要确保在 Owin 中间件尝试使用它之前将其恢复,否则您将收到身份验证错误。

这实际上是我对一个非常相似的问题的回答:

Custom parameter with Microsoft.Owin.Security.OpenIdConnect and AzureAD v 2.0 endpoint

在 Startup.Auth.cs 中,当您设置 OpenIdConnectAuthenticationOptions 时,您需要添加以下内容:

app.UseOpenIdConnectAuthentication(
  new OpenIdConnectAuthenticationOptions
  {
    //...
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
      RedirectToIdentityProvider = OnRedirectToIdentityProvider,
      MessageReceived = OnMessageReceived
    },
  });

并使用 RedirectToIdentityProvider 注入(inject)您的参数,大致如下:

private static Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
  var stateQueryString = notification.ProtocolMessage.State.Split('=');
  var protectedState = stateQueryString[1];
  var state = notification.Options.StateDataFormat.Unprotect(protectedState);
  state.Dictionary.Add("mycustomparameter", "myvalue");
  notification.ProtocolMessage.State = stateQueryString[0] + "=" + notification.Options.StateDataFormat.Protect(state);
  return Task.FromResult(0);
}

然后使用 MessageReceived 来提取它,如下所示:

private static Task OnMessageReceived(MessageReceivedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
  string mycustomparameter;
  var protectedState = notification.ProtocolMessage.State.Split('=')[1];
  var state = notification.Options.StateDataFormat.Unprotect(protectedState);
  state.Dictionary.TryGetValue("mycustomparameter", out mycustomparameter);
  return Task.FromResult(0);
}

您显然需要改进/强化这一点,但这应该会让您继续前进。

关于asp.net-mvc - 将参数传递给 Azure Active Directory 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37770989/

相关文章:

c# - C# WebAPI 值得吗?我可以使用标准 MVC 4 来创建我的 API 吗?

asp.net-mvc - 属性级验证错误阻碍了类级验证的验证

c# - 从 Metro 应用程序访问 Azure 中受 ACS 保护的 Web API 站点

java - Spring 社交 Facebook 登录 - 抱歉,出了点问题

java - getUserTimeLine (Twitter4J) 仅适用于部分公众账号

c# - 查看从 View 到 Controller 的数据

c# - Asp.Net Web API 中小数的自定义模型绑定(bind)器

azure - 使用Microsoft Hive ODBC驱动程序在Azure文档数据库和HDInsight上的Hive集成方面的问题

powershell - 如何创建 Azure AD 应用程序 key ?

ruby-on-rails - OAuth2 和 Omniauth 的区别