C# 仅将Azure AD用于身份验证,而不用于授权

C# 仅将Azure AD用于身份验证,而不用于授权,c#,asp.net,azure,asp.net-identity,azure-active-directory,C#,Asp.net,Azure,Asp.net Identity,Azure Active Directory,这件事我已经搞了好几天了 我想做的是使用Azure AD对用户进行身份验证,成功后,使用ASP.NET身份自动登录以进行授权。如果他们没有帐户,我想自动创建一个 本质上,Azure AD只是确认他们是组织的一部分,ASP.NET标识部分是它自己的数据库,我可以使用[Authorize]属性在Azure AD之外设置自定义角色 这是我的ConfigureAuth()方法: public void ConfigureAuth(IAppBuilder app) { // Con

这件事我已经搞了好几天了

我想做的是使用Azure AD对用户进行身份验证,成功后,使用ASP.NET身份自动登录以进行授权。如果他们没有帐户,我想自动创建一个

本质上,Azure AD只是确认他们是组织的一部分,ASP.NET标识部分是它自己的数据库,我可以使用
[Authorize]
属性在Azure AD之外设置自定义角色

这是我的
ConfigureAuth()
方法:

public void ConfigureAuth(IAppBuilder app)
    {
        // Configure the db context, user manager and signin manager to use a single instance per request
        app.CreatePerOwinContext(IntranetApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = SettingsHelper.ClientId,
                Authority = SettingsHelper.Authority,

                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 = (context) =>
                    {
                        var code = context.Code;
                        ClientCredential credential = new ClientCredential(SettingsHelper.ClientId, SettingsHelper.AppKey);
                        String signInUserId = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;

                        AuthenticationContext authContext = new AuthenticationContext(SettingsHelper.Authority, new ADALTokenCache(signInUserId));
                        AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, SettingsHelper.AADGraphResourceId);

                        return Task.FromResult(0);
                    },
                    RedirectToIdentityProvider = (context) =>
                    {
                        // This ensures that the address used for sign in and sign out is picked up dynamically from the request
                        // this allows you to deploy your app (to Azure Web Sites, for example)without having to change settings
                        // Remember that the base URL of the address used here must be provisioned in Azure AD beforehand.
                        string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
                        context.ProtocolMessage.RedirectUri = appBaseUrl + "/";
                        context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;

                        return Task.FromResult(0);
                    },
                    AuthenticationFailed = (context) =>
                    {
                        // Suppress the exception if you don't want to see the error
                        context.HandleResponse();
                        return Task.FromResult(0);
                    }
                }

            });

        // Enable the application to use a cookie to store information for the signed in user
        // and to use a cookie to temporarily store information about a user logging in with a third party login provider
        // Configure the sign in cookie
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                // Enables the application to validate the security stamp when the user logs in.
                // This is a security feature which is used when you change a password or add an external login to your account.  
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            },
        });
    }
public void ConfigureAuth(IAppBuilder应用程序)
{
//将数据库上下文、用户管理器和登录管理器配置为每个请求使用一个实例
app.CreatePerOwinContext(IntranetApplicationDbContext.Create);
app.CreatePerOwinContext(ApplicationUserManager.Create);
app.CreatePerOwinContext(ApplicationSignInManager.Create);
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(新的CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
新的OpenIdConnectAuthenticationOptions
{
ClientId=设置shelper.ClientId,
权限=设置搁置权限,
通知=新的OpenIdConnectAuthenticationNotifications()
{
//如果OpenID Connect响应中有代码,请将其兑换为访问令牌和刷新令牌,并将其存储起来。
AuthorizationCodeReceived=(上下文)=>
{
var code=context.code;
ClientCredential credential=新的ClientCredential(SettingsHelper.ClientId,SettingsHelper.AppKey);
String signInUserId=context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
AuthenticationContext authContext=新的AuthenticationContext(SettingsHelper.Authority,新的ADALTokenCache(signInUserId));
AuthenticationResult=authContext.AcquireTokenByAuthorizationCode(代码,新Uri(HttpContext.Current.Request.Url.GetLeftPart(Uriplate.Path)),凭证,设置Shelper.AADGraphResourceId);
返回Task.FromResult(0);
},
RedirectToIdentityProvider=(上下文)=>
{
//这样可以确保从请求中动态提取用于登录和注销的地址
//这允许您部署应用程序(例如,部署到Azure网站),而无需更改设置
//请记住,此处使用的地址的基本URL必须事先在Azure AD中设置。
字符串appBaseUrl=context.Request.Scheme+“:/”+context.Request.Host+context.Request.PathBase;
context.ProtocolMessage.RedirectUri=appBaseUrl+“/”;
context.ProtocolMessage.PostLogoutRedirectUri=appBaseUrl;
返回Task.FromResult(0);
},
身份验证失败=(上下文)=>
{
//如果不想看到错误,请抑制异常
context.HandleResponse();
返回Task.FromResult(0);
}
}
});
//使应用程序能够使用cookie存储登录用户的信息
//以及使用cookie临时存储用户登录第三方登录提供商的信息
//配置登录cookie
app.UseCookieAuthentication(新的CookieAuthenticationOptions
{
AuthenticationType=DefaultAuthenticationTypes.ApplicationOkie,
LoginPath=新路径字符串(“/Account/Login”),
Provider=新CookieAuthenticationProvider
{
//允许应用程序在用户登录时验证安全戳。
//这是一种安全功能,在您更改密码或向帐户添加外部登录时使用。
OnValidateIdentity=SecurityStampValidator.OnValidateIdentity(
validateInterval:TimeSpan.FromMinutes(30),
regenerateIdentity:(管理器,用户)=>user.GenerateUserIdentityAsync(管理器))
},
});
}
现在,当我执行
HttpContext.Request.IsAuthenticated
时,ASP.NET身份正在接管。这没关系,我只需要一种方法来检查OpenID部分是否经过身份验证,这样我就可以输入自定义逻辑来自动登录用户。

明白了

我最大的问题是试图使用OWIN中间件为我做任何事情。对Azure AD的简单身份验证不需要OpenID中间件。我实际上在Account controller中创建了一个
OpenIdAuth
方法,它充当我的中间人,在用户访问该站点之前向Azure进行身份验证

[AllowAnonymous]
public ActionResult OpenIdAuth(string code)
{
    string clientId = "00000000-0000-0000-0000-000000000000"; // Client ID found in the Azure AD Application
    string appKey = "111111111112222222222223333333333AAABBBCCC="; // Key generated in the Azure AD Appliction

    if (code != null)
    {
        string commonAuthority = "https://login.windows.net/<TENANT_URL>";  // Eg. https://login.windows.net/MyDevSite.onmicrosoft.com
        var authContext = new AuthenticationContext(commonAuthority);
        ClientCredential credential = new ClientCredential(clientId, appKey);
        AuthenticationResult authenticationResult = authContext.AcquireTokenByAuthorizationCode(code, new Uri(HttpContext.Request.Url.GetLeftPart(UriPartial.Path)), credential, "https://graph.windows.net");

        var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        var signInManager = HttpContext.GetOwinContext().Get<ApplicationSignInManager>();

        var user = UserManager.FindByName(authenticationResult.UserInfo.UniqueId);
        if (user != null)
        {
            signInManager.SignIn(user, false, false);
        }
        else
        {
            var newUser = new ApplicationUser { UserName = authenticationResult.UserInfo.UniqueId, Email = authenticationResult.UserInfo.DisplayableId };
            var creationResult = UserManager.Create(newUser);

            if (creationResult.Succeeded)
            {
                user = UserManager.FindByName(newUser.UserName);
                signInManager.SignIn(user, false, false);
            }
            else
            {
                return new ViewResult { ViewName = "Error" };
            }
        }

        return Redirect("/");
    }
    else
    {
        var url = new Uri($"https://login.microsoftonline.com/<TENANT_URL>/oauth2/authorize?client_id={clientId}&response_type=code&redirect_uri=https://localhost/Account/OpenIdAuth");
        return Redirect(url.AbsoluteUri);
    }
}

我想说的是,你不应该寻找OpenID,而应该寻找并使用类似的东西。事实上,我昨天刚刚浏览了那篇文章,Azure广告组很笨重,不像ASP.NET身份角色那样流畅。我希望应用程序用户能够动态地更改角色,而无需在Active Directory中进行更改。您所指的应用程序密钥,这是Azure应用程序中生成的sescret吗?@NiAu-Yup!这个秘密来自于你在Azure广告中创建新的应用注册
public void ConfigureAuth(IAppBuilder app)
    {
        // Configure the db context, user manager and signin manager to use a single instance per request
        app.CreatePerOwinContext(IntranetApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

        // Enable the application to use a cookie to store information for the signed in user
        // and to use a cookie to temporarily store information about a user logging in with a third party login provider
        // Configure the sign in cookie
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                // Enables the application to validate the security stamp when the user logs in.
                // This is a security feature which is used when you change a password or add an external login to your account.  
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            },
        });
    }