public async Task <ActionResult> CreateLocalAccountPost(EducationRegisterViewModel model)
        {
            var tenantId           = User.GetTenantId();
            var graphServiceClient = await AuthenticationHelper.GetGraphServiceClientAsync();

            IGraphClient graphClient = new MSGraphClient(graphServiceClient);
            var          user        = await graphClient.GetCurrentUserAsync();

            var tenant = await graphClient.GetTenantAsync(tenantId);

            model.Email          = user.Mail ?? user.UserPrincipalName;
            model.FavoriteColors = Constants.FavoriteColors;

            // Create a new local user
            var localUser = new ApplicationUser
            {
                Email         = model.Email,
                UserName      = model.Email,
                FavoriteColor = model.FavoriteColor
            };
            var result = await userManager.CreateAsync(localUser);

            if (!result.Succeeded)
            {
                AddErrors(result);
                return(View(model));
            }

            // Update the local user
            await applicationService.UpdateLocalUserAsync(localUser, user, tenant);

            SetCookiesForO365User(user.GivenName + " " + user.Surname, user.Mail);
            return(RedirectToAction("Index", "Schools"));
        }
        //
        // GET: /Link/LoginLocal
        public async Task <ActionResult> LoginLocal(LoginViewModel model)
        {
            var graphServiceClient = await AuthenticationHelper.GetGraphServiceClientAsync();

            IGraphClient graphClient = new MSGraphClient(graphServiceClient);
            var          user        = await graphClient.GetCurrentUserAsync();

            var localUser = userManager.FindByEmail(string.IsNullOrEmpty(user.Mail)? user.UserPrincipalName:user.Mail);

            if (localUser == null)
            {
                foreach (var modelValue in ModelState.Values)
                {
                    modelValue.Errors.Clear();
                }
                return(View(model));
            }
            var tenantId = User.GetTenantId();

            if (localUser.O365UserId.IsNotNullAndEmpty())
            {
                ModelState.AddModelError("Email", "The local account has already been linked to another Office 365 account.");
                return(View(model));
            }

            var tenant = await graphClient.GetTenantAsync(tenantId);

            await applicationService.UpdateLocalUserAsync(localUser, user, tenant);

            SetCookiesForO365User(user.GivenName + " " + user.Surname, user.Mail);
            TempData["Message"] = Resources.LinkO365AccountSuccess;
            TempData[HandleAdalExceptionAttribute.ChallengeImmediatelyTempDataKey] = true;

            return(RedirectToAction("Index", "Schools"));
        }
        //
        // GET: /Link/Index
        public async Task <ActionResult> Index()
        {
            var userContext = await applicationService.GetUserContextAsync();

            if (userContext.IsO365Account && !userContext.AreAccountsLinked)
            {
                var graphServiceClient = await AuthenticationHelper.GetGraphServiceClientAsync();

                var graphClient = new MSGraphClient(graphServiceClient);
                var user        = await graphClient.GetCurrentUserAsync();

                var email = user.Mail ?? user.UserPrincipalName;

                if (await userManager.Users.AnyAsync(i => i.Email == email))
                {
                    ViewBag.LocalAccountExistedMessage = $"There is a local account: {email} matching your O365 account.";
                }
            }
            return(View(userContext));
        }
        //
        // GET: /Link/ProcessCode
        public async Task <ActionResult> ProcessCode(string code, string error, string error_description, string resource, string state)
        {
            if (TempData[StateKey] as string != state)
            {
                TempData["Error"] = "Invalid operation. Please try again";
                return(RedirectToAction("Index"));
            }

            var authResult = await AuthenticationHelper.GetAuthenticationResultAsync(code);

            var tenantId           = authResult.TenantId;
            var graphServiceClient = authResult.CreateGraphServiceClient();

            IGraphClient graphClient = new MSGraphClient(graphServiceClient);
            var          user        = await graphClient.GetCurrentUserAsync();

            var tenant = await graphClient.GetTenantAsync(tenantId);

            var isAccountLinked = await applicationService.IsO365AccountLinkedAsync(user.Id);

            if (isAccountLinked)
            {
                TempData["Error"] = $"Failed to link accounts. The Office 365 account '{ user.Mail ?? user.UserPrincipalName}' is already linked to another local account.";
                return(RedirectToAction("Index"));
            }

            // Link the AAD User with local user.
            var localUser = await applicationService.GetCurrentUserAsync();

            await applicationService.UpdateLocalUserAsync(localUser, user, tenant);

            // Re-sign in user. Required claims (roles, tenent id and user object id) will be added to current user's identity.
            await signInManager.SignInAsync(localUser, isPersistent : false, rememberBrowser : false);

            TempData["Message"] = Resources.LinkO365AccountSuccess;
            TempData[HandleAdalExceptionAttribute.ChallengeImmediatelyTempDataKey] = true;
            SetCookiesForO365User(user.GivenName + " " + user.Surname, user.UserPrincipalName);

            return(RedirectToAction("Index", "Home"));
        }
        public async Task <ActionResult> LoginLocalPost(LoginViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return(View(model));
            }

            var localUser = userManager.FindByEmail(model.Email);

            if (localUser == null)
            {
                ModelState.AddModelError("", "Invalid login attempt.");
                return(View(model));
            }
            if (localUser.O365UserId.IsNotNullAndEmpty())
            {
                ModelState.AddModelError("Email", "The local account has already been linked to another Office 365 account.");
                return(View(model));
            }
            if (!await userManager.CheckPasswordAsync(localUser, model.Password))
            {
                ModelState.AddModelError("", "Invalid login attempt.");
                return(View(model));
            }

            var tenantId           = User.GetTenantId();
            var graphServiceClient = await AuthenticationHelper.GetGraphServiceClientAsync();

            IGraphClient graphClient = new MSGraphClient(graphServiceClient);
            var          user        = await graphClient.GetCurrentUserAsync();

            var tenant = await graphClient.GetTenantAsync(tenantId);

            await applicationService.UpdateLocalUserAsync(localUser, user, tenant);

            SetCookiesForO365User(user.GivenName + " " + user.Surname, user.Mail);

            return(RedirectToAction("Index", "Schools"));
        }
Example #6
0
        public void ConfigureAADAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions {
            });

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                Caption   = "Microsoft Work or school account",
                ClientId  = Constants.AADClientId,
                Authority = Constants.Authority,
                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    // instead of using the default validation (validating against a single issuer value, as we do in line of business apps),
                    // we inject our own multitenant validation logic
                    ValidateIssuer = false,
                },
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    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;
                        CookieService cookieService = new CookieService();
                        string hint = cookieService.GetCookiesOfEmail();
                        if (!string.IsNullOrEmpty(hint))
                        {
                            context.ProtocolMessage.LoginHint = hint;
                        }
                        return(Task.FromResult(0));
                    },
                    AuthorizationCodeReceived = async(context) =>
                    {
                        var identity = context.AuthenticationTicket.Identity;

                        // Get token with authorization code
                        var redirectUri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));
                        var credential  = new ClientCredential(Constants.AADClientId, Constants.AADClientSecret);
                        var authContext = AuthenticationHelper.GetAuthenticationContext(identity, Permissions.Delegated);
                        var authResult  = await authContext.AcquireTokenByAuthorizationCodeAsync(context.Code, redirectUri, credential, Constants.Resources.MSGraph);

                        // Get user's roles and add them to claims
                        var graphServiceClient = authResult.CreateGraphServiceClient();
                        var graphClient        = new MSGraphClient(graphServiceClient);
                        var user = await graphClient.GetCurrentUserAsync();
                        foreach (var role in user.Roles)
                        {
                            identity.AddClaim(ClaimTypes.Role, role);
                        }
                    },
                    AuthenticationFailed = (context) =>
                    {
                        var redirectUrl = "/Error?message=" + Uri.EscapeDataString(context.Exception.Message);
                        context.OwinContext.Response.Redirect(redirectUrl);
                        context.HandleResponse();     // Suppress the exception
                        return(Task.FromResult(0));
                    }
                }
            });
        }