Advertisement
Guest User

accountcontroller

a guest
Sep 22nd, 2014
553
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 16.25 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net.Http;
  4. using System.Security.Claims;
  5. using System.Security.Cryptography;
  6. using System.Threading.Tasks;
  7. using System.Web;
  8. using System.Web.Http;
  9. using Articles.Models;
  10. using Articles.Services.Models;
  11. using Articles.Services.Providers;
  12. using Articles.Services.Results;
  13. using Microsoft.AspNet.Identity;
  14. using Microsoft.AspNet.Identity.EntityFramework;
  15. using Microsoft.AspNet.Identity.Owin;
  16. using Microsoft.Owin.Security;
  17. using Microsoft.Owin.Security.Cookies;
  18. using Microsoft.Owin.Security.OAuth;
  19.  
  20. namespace Articles.Services.Controllers
  21. {
  22.     [Authorize]
  23.     [RoutePrefix("api/users")]
  24.     public class AccountController : ApiController
  25.     {
  26.         private const string LocalLoginProvider = "Local";
  27.         private ApplicationUserManager _userManager;
  28.  
  29.         public AccountController()
  30.         {
  31.         }
  32.  
  33.         public AccountController(ApplicationUserManager userManager,
  34.             ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
  35.         {
  36.             UserManager = userManager;
  37.             AccessTokenFormat = accessTokenFormat;
  38.         }
  39.  
  40.         public ApplicationUserManager UserManager
  41.         {
  42.             get
  43.             {
  44.                 return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
  45.             }
  46.             private set
  47.             {
  48.                 _userManager = value;
  49.             }
  50.         }
  51.  
  52.         public ISecureDataFormat<AuthenticationTicket> AccessTokenFormat { get; private set; }
  53.  
  54.         // GET api/Account/UserInfo
  55.         [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
  56.         [Route("UserInfo")]
  57.         public UserInfoViewModel GetUserInfo()
  58.         {
  59.             ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);
  60.  
  61.             return new UserInfoViewModel
  62.             {
  63.                 Email = User.Identity.GetUserName(),
  64.                 HasRegistered = externalLogin == null,
  65.                 LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null
  66.             };
  67.         }
  68.  
  69.         // POST api/Account/Logout
  70.         [Route("logout")]
  71.         public IHttpActionResult Logout()
  72.         {
  73.             Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType);
  74.             return Ok();
  75.         }
  76.  
  77.         // GET api/Account/ManageInfo?returnUrl=%2F&generateState=true
  78.         [Route("ManageInfo")]
  79.         public async Task<ManageInfoViewModel> GetManageInfo(string returnUrl, bool generateState = false)
  80.         {
  81.             IdentityUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
  82.  
  83.             if (user == null)
  84.             {
  85.                 return null;
  86.             }
  87.  
  88.             List<UserLoginInfoViewModel> logins = new List<UserLoginInfoViewModel>();
  89.  
  90.             foreach (IdentityUserLogin linkedAccount in user.Logins)
  91.             {
  92.                 logins.Add(new UserLoginInfoViewModel
  93.                 {
  94.                     LoginProvider = linkedAccount.LoginProvider,
  95.                     ProviderKey = linkedAccount.ProviderKey
  96.                 });
  97.             }
  98.  
  99.             if (user.PasswordHash != null)
  100.             {
  101.                 logins.Add(new UserLoginInfoViewModel
  102.                 {
  103.                     LoginProvider = LocalLoginProvider,
  104.                     ProviderKey = user.UserName,
  105.                 });
  106.             }
  107.  
  108.             return new ManageInfoViewModel
  109.             {
  110.                 LocalLoginProvider = LocalLoginProvider,
  111.                 Email = user.UserName,
  112.                 Logins = logins,
  113.                 ExternalLoginProviders = GetExternalLogins(returnUrl, generateState)
  114.             };
  115.         }
  116.  
  117.         // POST api/Account/ChangePassword
  118.         [Route("ChangePassword")]
  119.         public async Task<IHttpActionResult> ChangePassword(ChangePasswordBindingModel model)
  120.         {
  121.             if (!ModelState.IsValid)
  122.             {
  123.                 return BadRequest(ModelState);
  124.             }
  125.  
  126.             IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword,
  127.                 model.NewPassword);
  128.            
  129.             if (!result.Succeeded)
  130.             {
  131.                 return GetErrorResult(result);
  132.             }
  133.  
  134.             return Ok();
  135.         }
  136.  
  137.         // POST api/Account/SetPassword
  138.         [Route("SetPassword")]
  139.         public async Task<IHttpActionResult> SetPassword(SetPasswordBindingModel model)
  140.         {
  141.             if (!ModelState.IsValid)
  142.             {
  143.                 return BadRequest(ModelState);
  144.             }
  145.  
  146.             IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
  147.  
  148.             if (!result.Succeeded)
  149.             {
  150.                 return GetErrorResult(result);
  151.             }
  152.  
  153.             return Ok();
  154.         }
  155.  
  156.         // POST api/Account/AddExternalLogin
  157.         [Route("AddExternalLogin")]
  158.         public async Task<IHttpActionResult> AddExternalLogin(AddExternalLoginBindingModel model)
  159.         {
  160.             if (!ModelState.IsValid)
  161.             {
  162.                 return BadRequest(ModelState);
  163.             }
  164.  
  165.             Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
  166.  
  167.             AuthenticationTicket ticket = AccessTokenFormat.Unprotect(model.ExternalAccessToken);
  168.  
  169.             if (ticket == null || ticket.Identity == null || (ticket.Properties != null
  170.                 && ticket.Properties.ExpiresUtc.HasValue
  171.                 && ticket.Properties.ExpiresUtc.Value < DateTimeOffset.UtcNow))
  172.             {
  173.                 return BadRequest("External login failure.");
  174.             }
  175.  
  176.             ExternalLoginData externalData = ExternalLoginData.FromIdentity(ticket.Identity);
  177.  
  178.             if (externalData == null)
  179.             {
  180.                 return BadRequest("The external login is already associated with an account.");
  181.             }
  182.  
  183.             IdentityResult result = await UserManager.AddLoginAsync(User.Identity.GetUserId(),
  184.                 new UserLoginInfo(externalData.LoginProvider, externalData.ProviderKey));
  185.  
  186.             if (!result.Succeeded)
  187.             {
  188.                 return GetErrorResult(result);
  189.             }
  190.  
  191.             return Ok();
  192.         }
  193.  
  194.         // POST api/Account/RemoveLogin
  195.         [Route("RemoveLogin")]
  196.         public async Task<IHttpActionResult> RemoveLogin(RemoveLoginBindingModel model)
  197.         {
  198.             if (!ModelState.IsValid)
  199.             {
  200.                 return BadRequest(ModelState);
  201.             }
  202.  
  203.             IdentityResult result;
  204.  
  205.             if (model.LoginProvider == LocalLoginProvider)
  206.             {
  207.                 result = await UserManager.RemovePasswordAsync(User.Identity.GetUserId());
  208.             }
  209.             else
  210.             {
  211.                 result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(),
  212.                     new UserLoginInfo(model.LoginProvider, model.ProviderKey));
  213.             }
  214.  
  215.             if (!result.Succeeded)
  216.             {
  217.                 return GetErrorResult(result);
  218.             }
  219.  
  220.             return Ok();
  221.         }
  222.  
  223.         // GET api/Account/ExternalLogin
  224.         [OverrideAuthentication]
  225.         [HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
  226.         [AllowAnonymous]
  227.         [Route("ExternalLogin", Name = "ExternalLogin")]
  228.         public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)
  229.         {
  230.             if (error != null)
  231.             {
  232.                 return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error));
  233.             }
  234.  
  235.             if (!User.Identity.IsAuthenticated)
  236.             {
  237.                 return new ChallengeResult(provider, this);
  238.             }
  239.  
  240.             ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);
  241.  
  242.             if (externalLogin == null)
  243.             {
  244.                 return InternalServerError();
  245.             }
  246.  
  247.             if (externalLogin.LoginProvider != provider)
  248.             {
  249.                 Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
  250.                 return new ChallengeResult(provider, this);
  251.             }
  252.  
  253.             User user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider,
  254.                 externalLogin.ProviderKey));
  255.  
  256.             bool hasRegistered = user != null;
  257.  
  258.             if (hasRegistered)
  259.             {
  260.                 Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
  261.                
  262.                  ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
  263.                     OAuthDefaults.AuthenticationType);
  264.                 ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,
  265.                     CookieAuthenticationDefaults.AuthenticationType);
  266.  
  267.                 AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
  268.                 Authentication.SignIn(properties, oAuthIdentity, cookieIdentity);
  269.             }
  270.             else
  271.             {
  272.                 IEnumerable<Claim> claims = externalLogin.GetClaims();
  273.                 ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
  274.                 Authentication.SignIn(identity);
  275.             }
  276.  
  277.             return Ok();
  278.         }
  279.  
  280.         // GET api/Account/ExternalLogins?returnUrl=%2F&generateState=true
  281.         [AllowAnonymous]
  282.         [Route("ExternalLogins")]
  283.         public IEnumerable<ExternalLoginViewModel> GetExternalLogins(string returnUrl, bool generateState = false)
  284.         {
  285.             IEnumerable<AuthenticationDescription> descriptions = Authentication.GetExternalAuthenticationTypes();
  286.             List<ExternalLoginViewModel> logins = new List<ExternalLoginViewModel>();
  287.  
  288.             string state;
  289.  
  290.             if (generateState)
  291.             {
  292.                 const int strengthInBits = 256;
  293.                 state = RandomOAuthStateGenerator.Generate(strengthInBits);
  294.             }
  295.             else
  296.             {
  297.                 state = null;
  298.             }
  299.  
  300.             foreach (AuthenticationDescription description in descriptions)
  301.             {
  302.                 ExternalLoginViewModel login = new ExternalLoginViewModel
  303.                 {
  304.                     Name = description.Caption,
  305.                     Url = Url.Route("ExternalLogin", new
  306.                     {
  307.                         provider = description.AuthenticationType,
  308.                         response_type = "token",
  309.                         client_id = Startup.PublicClientId,
  310.                         redirect_uri = new Uri(Request.RequestUri, returnUrl).AbsoluteUri,
  311.                         state = state
  312.                     }),
  313.                     State = state
  314.                 };
  315.                 logins.Add(login);
  316.             }
  317.  
  318.             return logins;
  319.         }
  320.  
  321.         // POST api/Account/Register
  322.         [AllowAnonymous]
  323.         [Route("Register")]
  324.         public async Task<IHttpActionResult> Register(RegisterBindingModel model)
  325.         {
  326.             if (!ModelState.IsValid)
  327.             {
  328.                 return BadRequest(ModelState);
  329.             }
  330.  
  331.             var user = new User() { UserName = model.Email, Email = model.Email };
  332.  
  333.             IdentityResult result = await UserManager.CreateAsync(user, model.Password);
  334.  
  335.             if (!result.Succeeded)
  336.             {
  337.                 return GetErrorResult(result);
  338.             }
  339.  
  340.             return Ok();
  341.         }
  342.  
  343.         // POST api/Account/RegisterExternal
  344.         [OverrideAuthentication]
  345.         [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
  346.         [Route("RegisterExternal")]
  347.         public async Task<IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model)
  348.         {
  349.             if (!ModelState.IsValid)
  350.             {
  351.                 return BadRequest(ModelState);
  352.             }
  353.  
  354.             var info = await Authentication.GetExternalLoginInfoAsync();
  355.             if (info == null)
  356.             {
  357.                 return InternalServerError();
  358.             }
  359.  
  360.             var user = new User() { UserName = model.Email, Email = model.Email };
  361.  
  362.             IdentityResult result = await UserManager.CreateAsync(user);
  363.             if (!result.Succeeded)
  364.             {
  365.                 return GetErrorResult(result);
  366.             }
  367.  
  368.             result = await UserManager.AddLoginAsync(user.Id, info.Login);
  369.             if (!result.Succeeded)
  370.             {
  371.                 return GetErrorResult(result);
  372.             }
  373.             return Ok();
  374.         }
  375.  
  376.         protected override void Dispose(bool disposing)
  377.         {
  378.             if (disposing)
  379.             {
  380.                 UserManager.Dispose();
  381.             }
  382.  
  383.             base.Dispose(disposing);
  384.         }
  385.  
  386.         #region Helpers
  387.  
  388.         private IAuthenticationManager Authentication
  389.         {
  390.             get { return Request.GetOwinContext().Authentication; }
  391.         }
  392.  
  393.         private IHttpActionResult GetErrorResult(IdentityResult result)
  394.         {
  395.             if (result == null)
  396.             {
  397.                 return InternalServerError();
  398.             }
  399.  
  400.             if (!result.Succeeded)
  401.             {
  402.                 if (result.Errors != null)
  403.                 {
  404.                     foreach (string error in result.Errors)
  405.                     {
  406.                         ModelState.AddModelError("", error);
  407.                     }
  408.                 }
  409.  
  410.                 if (ModelState.IsValid)
  411.                 {
  412.                     // No ModelState errors are available to send, so just return an empty BadRequest.
  413.                     return BadRequest();
  414.                 }
  415.  
  416.                 return BadRequest(ModelState);
  417.             }
  418.  
  419.             return null;
  420.         }
  421.  
  422.         private class ExternalLoginData
  423.         {
  424.             public string LoginProvider { get; set; }
  425.             public string ProviderKey { get; set; }
  426.             public string UserName { get; set; }
  427.  
  428.             public IList<Claim> GetClaims()
  429.             {
  430.                 IList<Claim> claims = new List<Claim>();
  431.                 claims.Add(new Claim(ClaimTypes.NameIdentifier, ProviderKey, null, LoginProvider));
  432.  
  433.                 if (UserName != null)
  434.                 {
  435.                     claims.Add(new Claim(ClaimTypes.Name, UserName, null, LoginProvider));
  436.                 }
  437.  
  438.                 return claims;
  439.             }
  440.  
  441.             public static ExternalLoginData FromIdentity(ClaimsIdentity identity)
  442.             {
  443.                 if (identity == null)
  444.                 {
  445.                     return null;
  446.                 }
  447.  
  448.                 Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier);
  449.  
  450.                 if (providerKeyClaim == null || String.IsNullOrEmpty(providerKeyClaim.Issuer)
  451.                     || String.IsNullOrEmpty(providerKeyClaim.Value))
  452.                 {
  453.                     return null;
  454.                 }
  455.  
  456.                 if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer)
  457.                 {
  458.                     return null;
  459.                 }
  460.  
  461.                 return new ExternalLoginData
  462.                 {
  463.                     LoginProvider = providerKeyClaim.Issuer,
  464.                     ProviderKey = providerKeyClaim.Value,
  465.                     UserName = identity.FindFirstValue(ClaimTypes.Name)
  466.                 };
  467.             }
  468.         }
  469.  
  470.         private static class RandomOAuthStateGenerator
  471.         {
  472.             private static RandomNumberGenerator _random = new RNGCryptoServiceProvider();
  473.  
  474.             public static string Generate(int strengthInBits)
  475.             {
  476.                 const int bitsPerByte = 8;
  477.  
  478.                 if (strengthInBits % bitsPerByte != 0)
  479.                 {
  480.                     throw new ArgumentException("strengthInBits must be evenly divisible by 8.", "strengthInBits");
  481.                 }
  482.  
  483.                 int strengthInBytes = strengthInBits / bitsPerByte;
  484.  
  485.                 byte[] data = new byte[strengthInBytes];
  486.                 _random.GetBytes(data);
  487.                 return HttpServerUtility.UrlTokenEncode(data);
  488.             }
  489.         }
  490.  
  491.         #endregion
  492.     }
  493. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement