Asp .Net Mvc Facebook, Twitter ve Google OAuth2 Login İşlemleri

Merhabalar, bu yazımda Asp .Net Mvc de farklı uygulamalarla login işlemlerini gerçekleştireceğiz. Bu bölümdeki önemli nokta mesela benim user.create() adlı metodum olsun bu sizde hata verdi. Siz kendi login ve register işlemlerinizde kullandığınız yapıyı kullanarak değiştirin çünkü versiyon, yapı gibi etkenler bazen sorun çıkartabilmektedir. Çok uzatmadan hemen başlayalım.

İlk olarak gerekli paketleri nuget package manager yardımıyla yükleyelim.

  • Microsoft.Owin.Security.Google
  • Microsoft.Owin.Security.Facebook
  • Microsoft.Owin.Security.Twitter
  • Microsoft.Owin.Security.OAuth
  • Microsoft.Owin
  • Microsoft.AspNet.Identity

Sonra ViewModels klasörünün içine ExternalLoginConfirmationViewModel adlı bir class açıyoruz ve içine aşağıdaki yapıyı ekliyoruz.

 public class ExternalLoginConfirmationViewModel
    {
      [StringLength(60)]
        [DisplayName("Adı")]
        public string Name { get; set; }
        [StringLength(60)]
        [DisplayName("Soyadı")]
        public string Surname { get; set; }    
        public bool Role { get; set; }

    }
    public class ExternalLoginListViewModel
    {
        public string ReturnUrl { get; set; }
    }

Şimdi App_Start dosyasına IdentityConfig adlı bir class açıyoruz ve içine gerekli kodları yazıyoruz.

  public class IdentityConfig
    {      
  public class ApplicationUserManager : UserManager<AppUser>
        {
            public ApplicationUserManager(IUserStore<AppUser> store)
                : base(store)
            {
            }

            public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
            {
                var manager = new ApplicationUserManager(new UserStore<AppUser>(context.Get<BlogContext>()));
                // Configure validation logic for usernames
                manager.UserValidator = new UserValidator<AppUser>(manager)
                {
                    AllowOnlyAlphanumericUserNames = false,
                    RequireUniqueEmail = true
                };

                // Configure validation logic for passwords
                manager.PasswordValidator = new PasswordValidator
                {
                    RequiredLength = 6,
                    RequireNonLetterOrDigit = true,
                    RequireDigit = true,
                    RequireLowercase = true,
                    RequireUppercase = true,
                };

                // Configure user lockout defaults
                manager.UserLockoutEnabledByDefault = true;
                manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
                manager.MaxFailedAccessAttemptsBeforeLockout = 5;

                // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
                // You can write your own provider and plug it in here.
                manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<AppUser>
                {
                    MessageFormat = "Your security code is {0}"
                });
                manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<AppUser>
                {
                    Subject = "Security Code",
                    BodyFormat = "Your security code is {0}"
                });
                manager.EmailService = new EmailService();
                manager.SmsService = new SmsService();
                var dataProtectionProvider = options.DataProtectionProvider;
                if (dataProtectionProvider != null)
                {
                    manager.UserTokenProvider =
                        new DataProtectorTokenProvider<AppUser>(dataProtectionProvider.Create("ASP.NET Identity"));
                }
                return manager;
            }
        }
       
        public class ApplicationSignInManager : SignInManager<AppUser, string>
        {
            public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager)
                : base(userManager, authenticationManager)
            {
            }
     
            public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
            {
                return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
            }
        }
}

Şimdi context classına gelip aşağıdaki eklemeyi yapıyoruz.

 public class BlogContext : IdentityDbContext<AppUser>
    {
        public BlogContext() : base("name=connectionString")
        {

        }
                       //
        public static BlogContext Create()
        {
            return new BlogContext();
        }
                       //
    }

Daha sonra Startup.cs classına gelip gerekli eklemeleri yapıyoruz.

 public class Startup
    {
        public void Configuration(IAppBuilder app)
        {

         //
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
            app.CreatePerOwinContext(BlogContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

          
            app.UseTwitterAuthentication(
               consumerKey: "Bura aldığınız key ile doldurulacak",
               consumerSecret: "Bura aldığınız key ile doldurulacak");
            app.UseFacebookAuthentication(
               appId: "Bura aldığınız key ile doldurulacak",
               appSecret: "Bura aldığınız key ile doldurulacak");

            app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
            {
                ClientId = "Bura aldığınız key ile doldurulacak",
                ClientSecret = "Bura aldığınız key ile doldurulacak"
            });
        }
    }

Şimdi controller taraflı kodları yazalım.

  public class AccountController : Controller
    {
     
        private readonly BlogContext db;
        private readonly UserManager<AppUser> userManager;
        private readonly RoleManager<AppRole> roleManager;
        private readonly UserStore<AppUser> userStore;
        private ApplicationSignInManager _signInManager;
       
        public AccountController( ApplicationSignInManager signInManager)
        {
      db = new BlogContext();
      userStore = new UserStore<AppUser>(db);
      userManager = new UserManager<AppUser>(userStore);
      RoleStore<AppRole> roleStore = new RoleStore<AppRole>(db);
      roleManager = new RoleManager<AppRole>(roleStore);
      SignInManager = signInManager;
        }

        public ApplicationSignInManager SignInManager
        {
            get
            {
                return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
            }
            private set
            {
                _signInManager = value;
            }
        }

  public ActionResult Logout()
        {
    IAuthenticationManager auth = HttpContext.GetOwinContext().Authentication;
            auth.SignOut("ApplicationCookie");
            return RedirectToAction("Login", "Account");
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
   public ActionResult ExternalLogin(string provider, string returnUrl)
        {
            return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
        }

  [AllowAnonymous]
        public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
        {
            var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
            if (loginInfo == null)
            {
                return RedirectToAction("Login");
            }
            var uselected = await userManager.FindAsync(loginInfo.Login);
            if (uselected == null)
            {
                return View("ExternalLoginConfirmation");
            }
            else
            {

                IAuthenticationManager auth = HttpContext.GetOwinContext().Authentication;

                auth.SignIn(userManager.CreateIdentity(uselected, "ApplicationCookie"));
               
                    return RedirectToAction("Index", "Home");
               
            }
                  }

        [HttpPost]
        public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
        {
            string IsCompany = "";
            if (User.Identity.IsAuthenticated)
            {
                return RedirectToAction("Index", "Home");
            }
            if (ModelState.IsValid)
            {
          var info = await AuthenticationManager.GetExternalLoginInfoAsync();
                if (info == null)
                {
                    return View("ExternalLoginFailure");
                }

                if (model.Role == false)
                {
                    IsCompany = "Person";
                }
                if (model.Role == true)
                {
                    IsCompany = "Businness";
                }

                AppUser inserted = new AppUser()
                {
                    Email = info.Email,
                    Name = model.Name,
                    Surname = model.Surname,
                };

                IdentityResult iresult = userManager.Create(inserted);

                if (iresult.Succeeded)
                {
                    var result = await userManager.AddLoginAsync(inserted.Id, info.Login);

                    if (result.Succeeded)
                    {
              userManager.AddToRole(inserted.Id, IsCompany);


              IAuthenticationManager auth = HttpContext.GetOwinContext().Authentication;

                        
              auth.SignIn(userManager.CreateIdentity(inserted, "ApplicationCookie"));

                        return RedirectToAction("Index", "Home");
                    }
                    else
                    {
                        return View(model);
                    }
                }
                else
                {
                    return View(model);
                }
            }

            ViewBag.ReturnUrl = returnUrl;
            return View(model);
        }

 [AllowAnonymous]
        public ActionResult ExternalLoginFailure()
        {
            return View();
        }

//Birde yardımcı metodlarımız var 

        #region Helpers
   
        private const string XsrfKey = "XsrfId";

        private IAuthenticationManager AuthenticationManager
        {
            get
            {
                return HttpContext.GetOwinContext().Authentication;
            }
        }

        private void AddErrors(IdentityResult result)
        {
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError("", error);
            }
        }

        private ActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            return RedirectToAction("Index", "Home");
        }

        internal class ChallengeResult : HttpUnauthorizedResult
        {
            public ChallengeResult(string provider, string redirectUri)
                : this(provider, redirectUri, null)
            {
            }

            public ChallengeResult(string provider, string redirectUri, string userId)
            {
                LoginProvider = provider;
                RedirectUri = redirectUri;
                UserId = userId;
            }

            public string LoginProvider { get; set; }
            public string RedirectUri { get; set; }
            public string UserId { get; set; }

            public override void ExecuteResult(ControllerContext context)
            {
                var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
                if (UserId != null)
                {
                    properties.Dictionary[XsrfKey] = UserId;
                }
                context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
            }
        }
        #endregion

Biraz karmaşık gelebilir. Ama başka yöntem yok isterseniz direkt kodları kopyalayıp kullanın isterseniz debug ile nerede ne yapıyor öğrenerek kullanın bu size kalmış.

Şimdi oluşturuduğumuz view lerini oluşturup içini aşağıdakiler gibi dolduralım.

ExternalLoginConfirmation actionun view i

@model Blog.ViewModels.ExternalLoginConfirmationViewModel

<div>
    @using (Html.BeginForm("ExternalLoginConfirmation", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        <label>@Html.CheckBoxFor(model => model.Role )Şirketseniz Tıklayınız   </label>

        <div class="wrap-input100 validate-input m-b-23">
            @Html.ValidationMessageFor(model => model.Name, "", new { @class = "wrap-input100 validate-input m-b-23" })
            <span class="label-input100">Ad</span>
            @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "input100", @placeholder = "Type your name", @required = "required", @id = "name" } })

        </div>
        <div class="wrap-input100 validate-input m-b-23">
            @Html.ValidationMessageFor(model => model.Surname, "", new { @class = "wrap-input100 validate-input m-b-23" })
            <span class="label-input100">Soyad</span>
            @Html.EditorFor(model => model.Surname, new { htmlAttributes = new { @class = "input100", @placeholder = "Type your surname", @required = "required", @id = "surname" } })
        </div>

        <button>Kaydol</button>
    }
</div>

ExternalLoginFailure actionun view i

<hgroup>
    <h2>@ViewBag.Title.</h2>
    <h3 class="text-danger">Unsuccessful login with service.</h3>
</hgroup>

Şimdi partial page ihtiyacımız var. _ExternalLoginsListPartial adlı bir partial page açıyoruz ve içine aşağıdaki kodları yazıyoruz.

@model Blog.ViewModels.ExternalLoginListViewModel
@using Microsoft.Owin.Security
<hr />
@{
    var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes();
    if (loginProviders.Count() == 0)
    {
        <div>
            <p>
                There are no external authentication services configured. See <a href="https://go.microsoft.com/fwlink/?LinkId=403804">this article</a>
                for details on setting up this ASP.NET application to support logging in via external services.
            </p>
        </div>
    }
    else
    {
        using (Html.BeginForm("ExternalLogin", "Account", new { ReturnUrl = Model.ReturnUrl }))
        {
            @Html.AntiForgeryToken()
            <div id="socialLoginList">
                <p>
                    @foreach (AuthenticationDescription p in loginProviders)
                    {
                        <button type="submit" class="btn btn-default" id="@p.AuthenticationType" name="provider" value="@p.AuthenticationType" title="Log in using your @p.Caption account">@p.AuthenticationType</button>
                    }
                </p>
            </div>
        }
    }
}

Şimdi login sayfasına ekleme işlemimiz kaldı sadece.

@using Blog.ViewModels
@model ExternalLoginListViewModel

// Login işlem kodları 

 <div class="col-md-4">
                    <section id="socialLoginForm">
        @Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel { ReturnUrl = ViewBag.ReturnUrl })
                    </section>
                </div>

Evet işlemimiz bitti projeyi derleyip çalışmasını kontrol edebilirsiniz. Biraz kompleks ve detaylı bir konu umarım yardımcı olabilmişimdir.

Yazımın sonuna geldik. Bir sonraki yazımda görüşmek üzere. Sağlıcakla kalın.

Bir cevap yazın