简体   繁体   English

将参数传递给 Azure Active Directory 身份验证

[英]Passing parameters to Azure Active Directory authentication

I have an ASP.Net MVC Application, Owin, and I'm using Azure Active Directory authentication as well.我有一个 ASP.Net MVC 应用程序 Owin,我也在使用 Azure Active Directory 身份验证。

I want to pass a parameter when the user is redirected to the Azure AD authentication page.我想在用户重定向到 Azure AD 身份验证页面时传递一个参数。 So when the user signs in or signs up I want to pass ProjectId (int) as a parameter.因此,当用户登录或注册时,我想将ProjectId (int)作为参数传递。

After the user signs in/up and is redirected to my Application I want to receive the ProjectId I passed as a parameter.在用户登录/注册并重定向到我的应用程序后,我想接收我作为参数传递的ProjectId

How can I achieve that?我怎样才能做到这一点?

edit: Adding code编辑:添加代码

// 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);
}

Similar to what Gaurav is suggesting, but adding a few special considerations.类似于 Gaurav 的建议,但添加了一些特殊注意事项。 Basically, the state is used by the Owin middleware, so while you can inject your own stuff, you need to make sure you revert it back before the Owin middleware tries to use it otherwise you'll get auth errors.基本上,状态由 Owin 中间件使用,因此虽然您可以注入自己的东西,但您需要确保在 Owin 中间件尝试使用它之前将其还原,否则您将收到身份验证错误。

This is effectively what I replied to a very similar question:这实际上是我对一个非常相似的问题的回答:

Custom parameter with Microsoft.Owin.Security.OpenIdConnect and AzureAD v 2.0 endpoint 带有 Microsoft.Owin.Security.OpenIdConnect 和 AzureAD v 2.0 端点的自定义参数

In Startup.Auth.cs, when you setup the OpenIdConnectAuthenticationOptions you'd add the following:在 Startup.Auth.cs 中,当您设置 OpenIdConnectAuthenticationOptions 时,您将添加以下内容:

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

And use RedirectToIdentityProvider to inject your parameter, something along the lines of:并使用 RedirectToIdentityProvider 注入您的参数,大致如下:

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);
}

And then use MessageReceived to extract it, like so:然后使用 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);
}

You'd obviously need to improve/harden this but this should get you going.您显然需要改进/强化这一点,但这应该可以帮助您前进。

You could pass the ProjectId parameter as value for State parameter.您可以将ProjectId参数作为State参数的值传递。 See the sample code below:请参阅下面的示例代码:

            Notifications = new OpenIdConnectAuthenticationNotifications()
            {
                RedirectToIdentityProvider = context =>
                    {
                        redirectUri = string.Format("{0}/", System.Web.HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority));
                        postLogoutRedirectUri = redirectUri + "sign-out";
                        context.ProtocolMessage.RedirectUri = redirectUri;
                        context.ProtocolMessage.PostLogoutRedirectUri = postLogoutRedirectUri;
                        context.ProtocolMessage.State = "Your Project Id";
                        return Task.FromResult(0);
                    },
                AuthorizationCodeReceived = context =>
                    {
                        var projectId = context.ProtocolMessage.State;//Retrieve the state in AuthorizationCodeReceived event.
                        return Task.FromResult(0);
                    }
            }
        };

UPDATE更新

Essentially State accepts a string parameter.本质上State接受一个字符串参数。 In our project we needed to provide many values in the state.在我们的项目中,我们需要在状态中提供许多值。 What we did there is created a pipe delimited string and pass that as state.我们在那里做的是创建一个管道分隔的字符串并将其作为状态传递。 When we receive the state back, we simply convert that into an array and use appropriate elements.当我们收到返回的状态时,我们只需将其转换为一个数组并使用适当的元素。 Something like:类似的东西:

var state = "param1|param2|...|paramx";

Other thing you could do is create a state object (a simple class with some properties), serialize it as JSON, convert that in base64 string and pass that encoded string as state after properly url encoding it.您可以做的另一件事是创建一个状态对象(一个具有某些属性的简单类),将其序列化为 JSON,将其转换为 base64 字符串,并在正确 url 编码后将该编码字符串作为状态传递。 When you receive back the state, you could do the reverse process, get state object back and use it's properties values.当您收到状态时,您可以执行相反的过程,取回状态对象并使用它的属性值。

Just add context.ProtocolMessage.SetParameter(<ParameterName>, <value>);只需添加context.ProtocolMessage.SetParameter(<ParameterName>, <value>); in RedirectToIdentityProvider在 RedirectToIdentityProvider 中

Notifications = new OpenIdConnectAuthenticationNotifications()
            {
                RedirectToIdentityProvider = context =>
                    {
                        context.ProtocolMessage.SetParameter("prompt", "login");
                        return Task.FromResult(0);
                    },
                
            }
        };

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

相关问题 使用Azure Active Directory进行部分身份验证 - Partial Authentication with Azure Active Directory Azure Active Directory组织身份验证机制 - Azure Active Directory Organizational Authentication Mechasnim 使用Azure Active Directory进行身份验证的Web应用 - Web app using Azure active directory for Authentication 在本地和Azure上使用Active Directory进行身份验证 - Using Active Directory for Authentication locally and on Azure 开发环境的 Microsoft Azure Active Directory 身份验证登录 URL - Microsoft Azure Active Directory Authentication login URL for Dev environment Azure AD的Active Directory身份验证例外(AADSTS90027) - Active Directory Authentication Exception (AADSTS90027) with Azure AD Azure Active Directory -.Net Core 3 Web 应用程序 - 禁用 2 因素身份验证 - Azure Active Directory - .Net Core 3 Web Application - Disable 2 Factor Authentication 在测试环境中通过 Azure Active Directory 执行身份验证过程时出错 - Error when performing the authentication process by Azure Active Directory in test environment 如何将 Azure Active Directory 身份验证添加到 Razor Pages 应用程序? - How to add Azure Active Directory authentication to a Razor Pages app? Asp.net Identity使用密码和Azure Active Directory身份验证 - Asp.net Identity using password and Azure Active Directory authentication
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM