Exemple #1
0
        public async Task <IActionResult> RegisterUser(RegisterUserViewModel model)
        {
            if (ModelState.IsValid)
            {
                // create user + claims
                var userToCreate = new Galal.IDP.Entities.User();
                userToCreate.SubjectId = Guid.NewGuid().ToString();
                userToCreate.Password  = model.Password;
                userToCreate.Username  = model.Username;
                userToCreate.IsActive  = true;
                userToCreate.Claims.Add(new Galal.IDP.Entities.UserClaim("country", model.Country));
                userToCreate.Claims.Add(new Galal.IDP.Entities.UserClaim("address", model.Address));
                userToCreate.Claims.Add(new Galal.IDP.Entities.UserClaim("given_name", model.Firstname));
                userToCreate.Claims.Add(new Galal.IDP.Entities.UserClaim("family_name", model.Lastname));
                userToCreate.Claims.Add(new Galal.IDP.Entities.UserClaim("email", model.Email));
                userToCreate.Claims.Add(new Galal.IDP.Entities.UserClaim("subscriptionlevel", "FreeUser"));

                // if we're provisioning a user via external login, we must add the provider &
                // user id at the provider to this user's logins
                if (model.IsProvisioningFromExternal)
                {
                    userToCreate.Logins.Add(new Galal.IDP.Entities.UserLogin()
                    {
                        LoginProvider = model.Provider,
                        ProviderKey   = model.ProviderUserId
                    });
                }

                // add it through the repository
                _IDPUserRepository.AddUser(userToCreate);

                if (!_IDPUserRepository.Save())
                {
                    throw new Exception($"Creating a user failed.");
                }

                if (!model.IsProvisioningFromExternal)
                {
                    // log the user in
                    await HttpContext.SignInAsync(userToCreate.SubjectId, userToCreate.Username);
                }


                // continue with the flow
                if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl))
                {
                    return(Redirect(model.ReturnUrl));
                }

                return(Redirect("~/"));
            }

            // ModelState invalid, return the view with the passed-in model
            // so changes can be made
            return(View(model));
        }
Exemple #2
0
        public async Task <IActionResult> Callback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

            // retrieve return URL
            var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";

            if (result?.Succeeded != true)
            {
                throw new Exception("External authentication error");
            }

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
                _logger.LogDebug("External claims: {@claims}", externalClaims);
            }

            // lookup our user and external provider info
            var(user, provider, providerUserId, claims) = FindUserFromExternalProvider(result);
            //if (user == null)
            //{
            //    // this might be where you might initiate a custom workflow for user registration
            //    // in this sample we don't show how that would be done, as our sample implementation
            //    // simply auto-provisions new external user
            //    user = AutoProvisionUser(provider, providerUserId, claims);
            //}
            if (user == null)
            {
                // user wasn't found by provider, but maybe one exists with the same email address?
                if (provider == "Facebook")
                {
                    // email claim from Facebook
                    var email = claims.FirstOrDefault(c =>
                                                      c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress");
                    if (email != null)
                    {
                        var userByEmail = _IDPUserRepository.GetUserByEmail(email.Value);
                        if (userByEmail != null)
                        {
                            // add Facebook as a provider for this user
                            _IDPUserRepository.AddUserLogin(userByEmail.SubjectId, provider, result.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject).Value);

                            if (!_IDPUserRepository.Save())
                            {
                                throw new Exception($"Adding a login for a user failed.");
                            }

                            // redirect to ExternalLoginCallback
                            var continueWithUrlAfterAddingUserLogin =
                                Url.Action("ExternalLoginCallback", new { returnUrl = returnUrl });

                            return(Redirect(continueWithUrlAfterAddingUserLogin));
                        }
                    }
                }
                // retrieve return URL
                // var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";
                user = AutoProvisionUser(provider, providerUserId, claims);
                var returnUrlAfterRegisteration =
                    Url.Action("Callback", new { returnUrl = returnUrl });

                var continueWithUrl = Url.Action("RegisterUser", "UserRegisteration"
                                                 , new { returnUrl = returnUrlAfterRegisteration, provider = provider, providerUserId = result.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject).Value });

                return(Redirect(continueWithUrl));
            }

            // this allows us to collect any additonal claims or properties
            // for the specific prtotocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            await HttpContext.SignInAsync(user.SubjectId, user.Username, provider, localSignInProps, additionalLocalClaims.ToArray());

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);



            // check if external login is in the context of an OIDC request
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.ClientId));

            if (context != null)
            {
                if (await _clientStore.IsPkceClientAsync(context.ClientId))
                {
                    // if the client is PKCE then we assume it's native, so this change in how to
                    // return the response is for better UX for the end user.
                    return(View("Redirect", new RedirectViewModel {
                        RedirectUrl = returnUrl
                    }));
                }
            }

            return(Redirect(returnUrl));
        }