umbraco / UmbracoIdentityExtensions

Code files & installation that enables easy extensibility points for ASP.Net Identity and the Umbraco back office
MIT License
38 stars 23 forks source link

`OnAutoLinking` and `OnExternalLogin` not executing Azure Ad #42

Closed qz2rg4 closed 3 years ago

qz2rg4 commented 3 years ago

@Shazwazza Good Morning,

Hopefully, you can assist me in this problem.

Looking at the code attached Following code gets executed in their callbacks SecurityTokenValidated AuthorizationCodeReceived MessageReceived

However

OnAutoLinking and OnExternalLogin does not

My return url is "umbraco/" is this correct ? for I see google and facebook is different.

I can manually link the account but not unlink. How will i do this? Where does the ProviderKey get stored ?

public static void ConfigureBackOfficeAzureActiveDirectoryAuth(this IAppBuilder app,
            string tenant, string clientId, string postLoginRedirectUri, Guid issuerId,
          )
        {
            var authority = string.Format(
                CultureInfo.InvariantCulture,
                "https://login.windows.net/{0}",
                tenant);
            var adOptions = new OpenIdConnectAuthenticationOptions();
            adOptions.SignInAsAuthenticationType = Constants.Security.BackOfficeExternalAuthenticationType;
            adOptions.ClientId = clientId;
            adOptions.Authority = authority;
            adOptions.RedirectUri = ConfigurationManager.AppSettings["azureAd:redirectUrl"];
            adOptions.AuthenticationMode = AuthenticationMode.Passive;
            adOptions.Notifications = new OpenIdConnectAuthenticationNotifications();
            adOptions.Notifications.SecurityTokenValidated = async notification =>
            {

                var id = notification.AuthenticationTicket.Identity;

                // we want to keep first name, last name, subject and roles
                var givenName = id.FindFirst(ClaimTypes.GivenName);
                if (givenName == null) givenName = id.FindFirst("name");
                var familyName = id.FindFirst(ClaimTypes.Surname);
                if (familyName == null) familyName = id.FindFirst("name");
                var email = id.FindFirst(ClaimTypes.Email);
                if (email == null) email = id.FindFirst(ClaimTypes.Upn);
                var roles = id.FindAll(ClaimTypes.Role);

                // create new identity and set name and role claim type
                var nid = new ClaimsIdentity(
                    id.AuthenticationType,
                    ClaimTypes.GivenName,
                    ClaimTypes.Role);

                nid.AddClaim(givenName);
                nid.AddClaim(familyName);
                nid.AddClaims(roles);
                nid.AddClaim(id.FindFirst(ClaimTypes.NameIdentifier));
                var emailclaim = new Claim(ClaimTypes.Email, email.Value);
                nid.AddClaim(emailclaim);

                notification.AuthenticationTicket = new AuthenticationTicket(
                    nid,
                    notification.AuthenticationTicket.Properties);

            };
            adOptions.Notifications.MessageReceived = async message =>
            {

            };
            adOptions.Notifications.AuthorizationCodeReceived = async context =>
            {

                var userService = Umbraco.Core.Composing.Current.Services.UserService;

                var email = context.JwtSecurityToken.Claims.First(x => x.Type == "upn" || x.Type == "email")
                    .Value;
                var issuer = context.JwtSecurityToken.Claims.First(x => x.Type == "iss").Value;
                var providerKey = context.JwtSecurityToken.Claims.First(x => x.Type == "sub").Value;
                var name = context.JwtSecurityToken.Claims.First(x => x.Type == "name").Value;

                var userManager = context.OwinContext.GetUserManager<BackOfficeUserManager>();

                var user = userService.GetByEmail(email);

                if (user == null)
                {

                    user = userService.CreateUserWithIdentity(email, email);
                    Debugger.Break();
                }

                var identity = await userManager.FindByEmailAsync(email);
                if (identity.Logins.All(x => x.ProviderKey != providerKey))
                {
                    identity.Logins.Add(new IdentityUserLogin(issuer, providerKey, user.Id));
                    identity.Name = name;
                    await userManager.UpdateAsync(identity);
                }

            };

            adOptions.ForUmbracoBackOffice(style, icon);
            adOptions.Caption = caption;

            var autoLinkOptions = new ExternalSignInAutoLinkOptions(autoLinkExternalAccount: true,
                defaultUserGroups: new[] {"editor"},
                defaultCulture: "en-US");
            autoLinkOptions.AllowManualLinking = false;
            autoLinkOptions.OnAutoLinking = (BackOfficeIdentityUser user, ExternalLoginInfo info) => 
                { Debugger.Break(); };
            autoLinkOptions.OnExternalLogin = (BackOfficeIdentityUser user, ExternalLoginInfo info) =>
            {
                Debugger.Break();
                return true;
            };

            var options = new BackOfficeExternalLoginProviderOptions();
            options.AutoRedirectLoginToExternalProvider = false;
            options.DenyLocalLogin = false;
            options.AutoLinkOptions = autoLinkOptions;
            adOptions.SetBackOfficeExternalLoginProviderOptions(options);
            //Need to set the auth tyep as the issuer path
            adOptions.AuthenticationType = string.Format(
                CultureInfo.InvariantCulture,
                "https://sts.windows.net/{0}",
                issuerId);
            app.UseOpenIdConnectAuthentication(adOptions);
        }

    }

}
nul800sebastiaan commented 3 years ago

Hi there @qz2rg4 - sorry for the late reply, had to do some asking around about this. Unfortunately this is not something we can directly help with. All I can tell you at this point is people are successfully using Azure AD so it is definitely possible. Might be a good idea to leave a question on our forums at https://our.umbraco.com/ for some help. You can also investigate the source code, OnAutoLinking and OnExternalLogin are part of the CMS source so you could have a dig in there to see how that works and what might be going wrong for you.