首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Azure AD进行身份验证,但使用and成员资格角色和声明进行授权

使用Azure AD进行身份验证,但使用and成员资格角色和声明进行授权
EN

Stack Overflow用户
提问于 2021-10-27 20:39:24
回答 1查看 574关注 0票数 3

我正在尝试构建一个使用Azure进行身份验证的ASP.NET MVC 5应用程序。但是,一旦对用户进行了身份验证,我需要使用aspnet_membership Microsoft设置来获取经过身份验证的登录用户的声明。我们不想维护Azure AD设置中的角色和声明,我们也不想使用MS Graph。

我在VS 2017中使用单个用户帐户创建了一个MVC5.0项目,这反过来为我在我的Server数据库中创建了aspnet_membership数据库。

我还创建了一个单独的MVC 5.0项目,并在Azure中注册了该应用程序,我有ClientID等,该项目也运行良好。现在我正在尝试合并这两者,我有点迷茫,怀疑我是否认为这是正确的。

基本上,一旦用户登录到Microsoft Azure AD登录页面,我就会重定向到一个本地注册页面,当用户注册时,只需使用包含一些角色的最小信息,然后我将在AspNetUsers/Claims表中输入一个条目,并将这些声明附加到主体。在随后对该用户进行登录时,我必须加载验证过的蛤蜊。

请您帮助我指出这类场景的任何示例,因为我在这里读到的大部分建议都是关于如何使用MicrosoftGraph的。但是我们的角色太复杂了,我们决定只使用本地标识aspnet_membership数据库进行授权(角色作为声明)。

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-11 13:11:34

这对我有用。

代码语言:javascript
复制
public partial class Startup
    {       
        public void ConfigureAuth(IAppBuilder app)
        {
            string clientId = System.Configuration.ConfigurationManager.AppSettings["ClientId"];
            string redirectUri = System.Configuration.ConfigurationManager.AppSettings["RedirectUri"];
            string tenant = System.Configuration.ConfigurationManager.AppSettings["Tenant"];
            string authority = string.Format(System.Configuration.ConfigurationManager.AppSettings["Authority"], tenant);
            var cookieExpiryHours = Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["CookieExpiryHours"]);

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                CookieManager = new SystemWebCookieManager(),
                ExpireTimeSpan = TimeSpan.FromMinutes(cookieExpiryHours), 
                SlidingExpiration=true,             
            });

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {                   
                    ClientId = clientId,
                    Authority = authority,
                    RedirectUri = redirectUri,                   
                    PostLogoutRedirectUri = redirectUri,
                    Scope = OpenIdConnectScope.OpenIdProfile,
                    UseTokenLifetime = false,
                    // ResponseType is set to request the code id_token - which contains basic information about the signed-in user
                    ResponseType = OpenIdConnectResponseType.CodeIdToken,                    
                    TokenValidationParameters = new TokenValidationParameters()
                    { 
                        ValidateIssuer = true
                    },                  
                  
                    Notifications = new OpenIdConnectAuthenticationNotifications
                    {
                        AuthenticationFailed = OnAuthenticationFailed,
                        SecurityTokenValidated = OnSecurityTokenValidated,
                    }
                }

            );
         
        }

        private Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
        {
            var OIDClaimDesc = "http://schemas.microsoft.com/identity/claims/objectidentifier";
            var claims = context.AuthenticationTicket.Identity.Claims;
            var cookieExpiryHours = Int32.Parse(System.Configuration.ConfigurationManager.AppSettings["CookieExpiryHours"]);

            context.AuthenticationTicket.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddHours(cookieExpiryHours);
            context.AuthenticationTicket.Properties.IsPersistent = false;

            var owinContext = context.OwinContext;
            var userIdentity = context.AuthenticationTicket.Identity;
            var userClaims = userIdentity as ClaimsIdentity;
            
            var firstName = userClaims?.FindFirst(ClaimTypes.GivenName)?.Value ?? string.Empty;
            var lastName = userClaims?.FindFirst(ClaimTypes.Surname)?.Value ?? string.Empty;
            var email = userClaims?.FindFirst(ClaimTypes.Email)?.Value ?? string.Empty;
            var objID = Guid.Parse(userClaims.FindFirst(OIDClaimDesc).Value);
            var user = new UserService().GetUser(objID, email);

            if (user is null)//This user has just wandered in to the site or the admins have not added this user in the DB yet. Just redirect them back to log out
            {
                owinContext.Authentication.Challenge();
                return Task.FromResult(0);
            }

            if (userIdentity.IsAuthenticated)
            {
                userIdentity.AddClaim(new Claim(ClaimTypes.GivenName, firstName));
                userIdentity.AddClaim(new Claim(ClaimTypes.Surname, lastName));
                userIdentity.AddClaim(new Claim(ClaimTypes.Email, email));
                userIdentity.AddClaim(new Claim("AzureID", objID.ToString()));
                userIdentity.AddClaim(new Claim(ClaimTypes.Role, "user"));
            }

            new UserService().UpdateUser(objID, firstName, lastName, email);

            foreach (var claim in user.UserClaims)
            {
                if (!claim.ClaimType.Equals(ClaimTypes.GivenName, StringComparison.OrdinalIgnoreCase)
                    && !claim.ClaimType.Equals(ClaimTypes.Surname, StringComparison.OrdinalIgnoreCase))
                {
                    userIdentity.AddClaim(new Claim(ClaimTypes.Role, claim.ClaimValue));
                }
            }

            return Task.FromResult(0);
        }

        /// <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)
        {
            var code = "IDX21323";
            if (context.Exception.Message.Contains(code)) //I need this, as under certain conditions, the auth process was going on an infinite loop. 
            {
                context.HandleResponse();
                context.OwinContext.Authentication.Challenge();
            }

            return Task.FromResult(true);
        }
    }

public UserViewModel GetUser(Guid guid, string email)
        {
            var model = new UserViewModel();
            using (var ctxt = new DBContext())
            {
                var user = ctxt.Users.Where(x => (x.Email == email || x.OID==guid) && x.IsActive).FirstOrDefault();
                if (user == null)
                    return null;
                var claims = ctxt.UserClaims.Where(x => x.UserId==user.ID).ToList();
                model = Mapper.Map<UserViewModel>(user);
                model.UserClaims = Mapper.Map<List<ViewModels.UserClaimViewModel>>(claims);
            }


            return model;
        }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69745194

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档