如何通过 Microsoft 帐户使用 OWIN 身份验证?

How can I use OWIN Authentication with Microsoft account?

目前我正在我的应用程序中使用 OWIN 身份验证。我像普通人一样使用 Tenant。因此,它正在验证来自 Azure 活动目录和 Microsoft 帐户的任何用户。

我只想限制 Microsoft 帐户的用户。

下面是我的web.config文件

<add key="ClientId" value="<client id>" />
<add key="RedirectUri" value="https://localhost:44384/" />
<add key="Tenant" value="common" />
<add key="Authority" value="https://login.microsoftonline.com/{0}/v2.0" />

代码来自 Startup.cs

public class Startup
{
    // The Client ID is used by the application to uniquely identify itself 
    //to Azure AD.

    string clientId =  
System.Configuration.ConfigurationManager.AppSettings["ClientId"];

    // RedirectUri is the URL where the user will be redirected to after 
    //they sign in.
    string redirectUri = 
    System.Configuration.ConfigurationManager.AppSettings["RedirectUri"];

    // Tenant is the tenant ID (e.g. contoso.onmicrosoft.com, or 'common' 
    //for multi-tenant)
    static string tenant = 
    System.Configuration.ConfigurationManager.AppSettings["Tenant"];

    // Authority is the URL for authority, composed by Azure Active 
    //Directory v2 endpoint and the tenant name (e.g. 
    //https://login.microsoftonline.com/contoso.onmicrosoft.com/v2.0)

    string authority = 
    String.Format(System.Globalization.CultureInfo.InvariantCulture, 
    System.Configuration.ConfigurationManager.AppSettings["Authority"], 
    tenant);

    /// <summary>
    /// Configure OWIN to use OpenIdConnect 
    /// </summary>
    /// <param name="app"></param>
    public void Configuration(IAppBuilder app)
    {
    app.SetDefaultSignInAsAuthenticationType
    (CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        //app.UseMicrosoftAccountAuthentication(clientId: "", clientSecret: 
   "");

        app.UseOpenIdConnectAuthentication(
        new OpenIdConnectAuthenticationOptions
        {
                // Sets the ClientId, authority, RedirectUri as obtained 
                //from web.config
                ClientId = clientId,
            Authority = authority,
            RedirectUri = redirectUri,
                // PostLogoutRedirectUri is the page that users will be 
     //redirected to after sign-out. In this case, it is using the home page
                PostLogoutRedirectUri = redirectUri,
            Scope = OpenIdConnectScopes.OpenIdProfile,
                // ResponseType is set to request the id_token - which 
   //contains basic information about the signed-in user
                ResponseType = OpenIdConnectResponseTypes.IdToken,
                // ValidateIssuer set to false to allow personal and work accounts from any organization to sign in to your application
                // To only allow users from a single organizations, set ValidateIssuer to true and 'tenant' setting in web.config to the tenant name
                // To allow users from only a list of specific organizations, set ValidateIssuer to true and use ValidIssuers parameter 
                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters() { ValidateIssuer = false },
                // OpenIdConnectAuthenticationNotifications configures OWIN 
  //to send notification of failed authentications to OnAuthenticationFailed 
 //method
                Notifications = new OpenIdConnectAuthenticationNotifications
            {
                AuthenticationFailed = OnAuthenticationFailed
            }
        }
    );

    }

    /// <summary>
    /// Handle failed authentication requests by redirecting the user to the 
    //home page with an error in the query string
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>

 private Task OnAuthenticationFailed
 (AuthenticationFailedNotification<OpenIdConnectMessage, 
 OpenIdConnectAuthenticationOptions> context)
    {
        context.HandleResponse();
        context.Response.Redirect("/?errormessage=" + 
        context.Exception.Message);
        return Task.FromResult(0);
    }
}

如何限制仅用于 Microsoft 身份验证(对于用户 'user@outlook.com')?

为了仅允许拥有个人 Microsoft 帐户 (MSA) 的用户登录应用程序,我们需要使用 consumers 而不是 common 作为 tenant在权限里。

更详细的参数请参考下面的link:

v2.0 Protocols - OAuth 2.0 Authorization Code Flow

更新

app.UseOpenIdConnectAuthentication(
    new OpenIdConnectAuthenticationOptions
    {
        // The `Authority` represents the v2.0 endpoint - https://login.microsoftonline.com/common/v2.0
        // The `Scope` describes the initial permissions that your app will need.  See https://azure.microsoft.com/documentation/articles/active-directory-v2-scopes/                    
        ClientId = clientId,
        //Authority = String.Format(CultureInfo.InvariantCulture, aadInstance, "adnewfei.onmicrosoft.com", "/v2.0"),
        Authority = String.Format(CultureInfo.InvariantCulture, aadInstance, "common", "/v2.0"),
        RedirectUri = redirectUri,
        Scope = "openid email profile offline_access Mail.Read User.Read",
        PostLogoutRedirectUri = redirectUri,
        TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = false,

        },
        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
            AuthorizationCodeReceived = async (context) =>
            {
                var code = context.Code;
                string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
                ConfidentialClientApplication cca = new ConfidentialClientApplication(clientId, redirectUri,
                   new ClientCredential(appKey),
                   new MSALSessionCache(signedInUserID, context.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase));
                string[] scopes = { "Mail.Read User.Read" };
                try
                {
                    AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(scopes, code);
                }
                catch (Exception eee)
                {

                }
            },
            AuthenticationFailed = (notification) =>
            {
                notification.HandleResponse();
                notification.Response.Redirect("/Error?message=" + notification.Exception.Message);
                return Task.FromResult(0);
            },
            SecurityTokenValidated = (context) => {
                if (context.AuthenticationTicket.Identity.Claims.First(claim => claim.Type == "preferred_username").Value == "xxxx@hotmail.com")
                {

                }
                else
                {
                    throw new System.IdentityModel.Tokens.SecurityTokenValidationException();
                }
                return Task.FromResult(0);
            },
        },
    });