如何使用openid-Connect

时间:2017-06-05 13:33:07

标签: c# asp.net openid-connect azure-ad-b2c azure-ad-graph-api

我目前正在开发一个使用AD-B2C作为我的身份提供者的应用程序。这是使用他们在AD B2C graph的指南集成到解决方案中的,该指南使用openid-connect(至少我的理解)。

我需要使用一种电子邮件激活形式(在他们的注册政策之外),因此我需要能够通过电子邮件中的URL传递值,通过B2C的注册过程并返回到重定向网址。

我在某处读到了一个名为“state”的参数可用于此:

  

状态:请求中包含的值,也将在令牌响应中返回。它可以是您想要的任何内容的字符串。随机生成的唯一值通常用于防止跨站点请求伪造攻击。状态还用于在发生身份验证请求之前编码有关用户在应用程序中的状态的信息,例如他们所在的页面或正在执行的策略。

我试图将一个值附加到将用户转移到B2C时发生的重定向,但我不知道如何。

if (!Request.IsAuthenticated)
        { // go to login page
            HttpContext.GetOwinContext().Authentication.Challenge(
                  new AuthenticationProperties() { RedirectUri = "/" }, Startup.SignUpSignInPolicyId);
        }

该政策存储在 startup.auth.cs 文件中......

// B2C policy identifiers
    public static string SignUpPolicyId = ConfigurationManager.AppSettings["ida:SignUpPolicyId"];
    public static string SignInPolicyId = ConfigurationManager.AppSettings["ida:SignInPolicyId"];
    public static string SignUpSignInPolicyId = ConfigurationManager.AppSettings["ida:SignUpSignInPolicyId"];
    public static string ProfilePolicyId = ConfigurationManager.AppSettings["ida:UserProfilePolicyId"];
    public static string PasswordResetPolicyId = ConfigurationManager.AppSettings["ida:PasswordResetPolicyId"];

....并在 ConfigureAuth 方法中运行:

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

        app.UseCookieAuthentication(new CookieAuthenticationOptions()
        {
            CookieHttpOnly = true,
            ExpireTimeSpan = TimeSpan.FromHours(1),
        });

        // Configure OpenID Connect middleware for each policy
        app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignUpPolicyId));
        app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(ProfilePolicyId));
        app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignInPolicyId));
        app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignUpSignInPolicyId));
        app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(PasswordResetPolicyId));
    }

调用:

private OpenIdConnectAuthenticationOptions CreateOptionsFromPolicy(string policy)
    {
        return new OpenIdConnectAuthenticationOptions
        {
            // For each policy, give OWIN the policy-specific metadata address, and
            // set the authentication type to the id of the policy
            MetadataAddress = String.Format(aadInstance, tenant, policy),
            AuthenticationType = policy,

            // These are standard OpenID Connect parameters, with values pulled from web.config
            ClientId = clientId,
            RedirectUri = redirectUri,
            PostLogoutRedirectUri = redirectUri,
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                AuthenticationFailed = AuthenticationFailed,
            },
            Scope = "openid",
            ResponseType = "id_token",
            //// This piece is optional - it is used for displaying the user's name in the navigation bar.
            //TokenValidationParameters = new TokenValidationParameters
            //{
            //    NameClaimType = "name",
            //},
        };

    }

如何传递类似的值:(简化示例:)

if (!Request.IsAuthenticated)
        { // go to login page
            HttpContext.GetOwinContext().Authentication.Challenge(
                  new AuthenticationProperties() { RedirectUri = "/" }, Startup.SignUpSignInPolicyId, new { state = "value=uniquetoken&token=secrets" });
        } 

在运行时设置这些方法和策略? 此外,如果我朝着一个完全错误的方向前进,我将从哪里开始?

感谢任何帮助:)

最好的问候

1 个答案:

答案 0 :(得分:0)

要在使用OpenIdConnect协议时传递值,我们可以将值添加到您提到的状态。

我们可以在使用RedirectToIdentityProvider将其重定向到身份数据提供程序(Azure AD)之前传递此值。之后,我们可以在首次收到协议消息时使用MessageReceived提取我们添加的自定义值。

以下是供您参考的代码示例:

new OpenIdConnectAuthenticationOptions
{
    // For each policy, give OWIN the policy-specific metadata address, and
    // set the authentication type to the id of the policy
    MetadataAddress = String.Format(aadInstance, tenant, policy),
    AuthenticationType = policy,

    // These are standard OpenID Connect parameters, with values pulled from web.config
    ClientId = clientId,
    RedirectUri = redirectUri,
    PostLogoutRedirectUri = redirectUri,
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        AuthenticationFailed = AuthenticationFailed,
        RedirectToIdentityProvider= OnRedirectToIdentityProvider,
        MessageReceived= OnMessageReceived
    },
    Scope = "openid",
    ResponseType = "id_token",

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

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

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