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

本文关键字:用于 授权 身份验证 AD Azure | 更新日期: 2023-09-27 18:03:41

这几天我一直在摆弄这个…

我想做的是用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))
            },
        });
    }

现在ASP。. NET身份接管时,我做一个HttpContext.Request.IsAuthenticated这是可以的,我只需要一种方法来检查OpenID部分是否经过身份验证或不,所以我可以把我的自定义逻辑自动登录用户

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

明白了!

我最大的问题是试图使用OWIN中间件为我做所有的事情。OpenID中间件不需要用于Azure AD的简单身份验证。我基本上在Account控制器中创建了一个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);
    }
}

最棒的部分是code变量,它将在用户成功登录时由Microsoft传递。我使用相同的控制器方法并检查它是否为null,但技术上可以使用两种不同的控制器方法(Microsoft将重定向回您为redirect_uri参数指定的url)。

在我得到授权码后,我可以使用Microsoft.IdentityModel.Clients.ActiveDirectory nuget包中的AuthorizationContext来调用:AcquireTokenByAuthorizationCode。最后一个参数是Resource URI。我正在使用图形资源,但你可以使用任何其他资源,你已经给你的应用程序访问Azure管理门户。

最后,我的ConfigureAuth方法回到了普通的老式ASP。. NET标识版本:

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