Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion AspnetIdentitySample/AspnetIdentitySample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,9 @@
<Content Include="Scripts\jquery.validate.unobtrusive.min.js" />
<Content Include="Scripts\modernizr-2.6.2.js" />
<Content Include="Scripts\_references.js" />
<Content Include="Web.config" />
<Content Include="Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Web.Debug.config">
<DependentUpon>Web.config</DependentUpon>
</Content>
Expand All @@ -276,6 +278,9 @@
<Content Include="Views\Account\Manage.cshtml" />
<Content Include="Views\Account\Register.cshtml" />
<Content Include="Views\Shared\_LoginPartial.cshtml" />
<Content Include="Views\Account\ForgotPassword.cshtml" />
<Content Include="Views\Account\PasswordResetCompleted.cshtml" />
<Content Include="Views\Account\PasswordReset.cshtml" />
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />
Expand Down
123 changes: 122 additions & 1 deletion AspnetIdentitySample/Controllers/AccountController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using AspnetIdentitySample.Models;
using System.Text;
using System.Security.Cryptography;

namespace AspnetIdentitySample.Controllers
{
Expand Down Expand Up @@ -91,6 +93,7 @@ public async Task<ActionResult> Register(RegisterViewModel model)
var user = new MyUser();
user.UserName = model.UserName;
user.HomeTown = model.HomeTown;
user.Email = model.Email;
var result = await IdentityManager.Users.CreateLocalUserAsync(user, model.Password);
if (result.Success)
{
Expand Down Expand Up @@ -252,6 +255,7 @@ public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmat
// Get the information about the user from the external login provider
var user = new MyUser();
user.UserName = model.UserName;
user.Email = model.Email;
IdentityResult result = await IdentityManager.Authentication.CreateAndSignInExternalUserAsync(AuthenticationManager,user);
if (result.Success)
{
Expand Down Expand Up @@ -304,6 +308,123 @@ public ActionResult RemoveAccountList()
}).Result;
}

//
// GET: /Account/BeforePasswordReset
[AllowAnonymous]
public ActionResult ForgotPassword()
{
return View();
}

//
// POST: /Account/BeforePasswordReset

//http://stackoverflow.com/a/698879/208922

[AllowAnonymous]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ForgotPassword(BeforePasswordResetViewModel model)
{
string message = null;
//the token is valid for one day
var until = DateTime.Now.AddDays(1);
//We find the user, as the token can not generate the e-mail address,
//but the name should be.
var db = new MyDbContext();
var user = db.Users.SingleOrDefault(x => x.Email == model.Email);

if (null != user)
{
var token = new StringBuilder();

//Prepare a 10-character random text
using (RNGCryptoServiceProvider
rngCsp = new RNGCryptoServiceProvider())
{
var data = new byte[4];
for (int i = 0; i < 10; i++)
{
//filled with an array of random numbers
rngCsp.GetBytes(data);
//this is converted into a character from A to Z
var randomchar = Convert.ToChar(
//produce a random number
//between 0 and 25
BitConverter.ToUInt32(data, 0) % 26
//Convert.ToInt32('A')==65
+ 65
);
token.Append(randomchar);
}
}
//This will be the password change identifier
//that the user will be sent out
var tokenid = token.ToString();

//Generating a token
var result = await IdentityManager
.Passwords
.GenerateResetPasswordTokenAsync(
tokenid,
user.UserName,
until
);

if (result.Success)
{
//send the email
//...
}
}
message = "We have sent a password reset request if the email is verified.";
return RedirectToAction("PasswordReset", new { token = string.Empty, message = message });
}

//
// GET: /Account/PasswordReset
[AllowAnonymous]
public ActionResult PasswordReset(string message)
{
ViewBag.StatusMessage = message ?? "";
return View();
}

//
// POST: /Account/PasswordReset
[AllowAnonymous]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> PasswordReset(PasswordResetViewModel model)
{
if (ModelState.IsValid)
{
string message = null;
//reset the password
var result = await IdentityManager.Passwords.ResetPasswordAsync(model.Token, model.Password);
if (result.Success)
{
message = "The password has been reset.";
return RedirectToAction("PasswordResetCompleted", new { message = message });
}
else
{
AddErrors(result);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}

//
// GET: /Account/PasswordResetCompleted
[AllowAnonymous]
public ActionResult PasswordResetCompleted(string message)
{
ViewBag.StatusMessage = message ?? "";
return View();
}

protected override void Dispose(bool disposing)
{
if (disposing && IdentityManager != null)
Expand Down Expand Up @@ -353,4 +474,4 @@ public override void ExecuteResult(ControllerContext context)
}
#endregion
}
}
}
39 changes: 39 additions & 0 deletions AspnetIdentitySample/Models/AccountViewModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ public class ExternalLoginConfirmationViewModel

[Required]
public string LoginProvider { get; set; }

[Required]
[Display(Name = "E-mail address")]
[EmailAddress]
public string Email { get; set; }

}

public class ManageUserViewModel
Expand Down Expand Up @@ -65,5 +71,38 @@ public class RegisterViewModel
public string ConfirmPassword { get; set; }

public string HomeTown { get; set; }

[Required]
[Display(Name = "E-mail address")]
[EmailAddress]
public string Email { get; set; }
}

public class BeforePasswordResetViewModel
{
[Required]
[Display(Name = "E-mail address")]
[EmailAddress]
public string Email { get; set; }

}

public class PasswordResetViewModel
{
[Required]
[Display(Name = "Token")]
public string Token { get; set; }

[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }

[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }

}
}
1 change: 1 addition & 0 deletions AspnetIdentitySample/Models/AppModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace AspnetIdentitySample.Models
public class MyUser : User
{
public string HomeTown { get; set; }
public string Email { get; set; }
}
public class MyDbContext : IdentityDbContextWithCustomUser<MyUser>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
@Html.TextBoxFor(m => m.UserName)
@Html.ValidationMessageFor(m => m.UserName)
<br />
@Html.LabelFor(m => m.Email)
@Html.TextBoxFor(m => m.Email)
@Html.ValidationMessageFor(m => m.Email)
<br />
@Html.HiddenFor(m => m.LoginProvider)
<input type="submit" class="btn" value="Register" />
</fieldset>
Expand Down
34 changes: 34 additions & 0 deletions AspnetIdentitySample/Views/Account/ForgotPassword.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@model AspnetIdentitySample.Models.BeforePasswordResetViewModel

@{
ViewBag.Title = "Forgot your password?";
}

<hgroup class="title">
<h1>@ViewBag.Title.</h1>
</hgroup>

@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)

<fieldset class="form-horizontal">
<legend>Forgot password</legend>

<div class="control-group">
@Html.LabelFor(model => model.Email, new { @class = "control-label" })
<div class="controls">
@Html.EditorFor(model => model.Email)
@Html.ValidationMessageFor(model => model.Email, null, new { @class = "help-inline" })
</div>
</div>

<div class="form-actions no-color">
<input type="submit" value="Submit" class="btn" />
</div>
</fieldset>
}

@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
3 changes: 3 additions & 0 deletions AspnetIdentitySample/Views/Account/Login.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
<p>
@Html.ActionLink("Register", "Register") if you don't have a local account.
</p>
<p>
@Html.ActionLink("Forgot password?", "ForgotPassword")
</p>
}
</section>
</div>
Expand Down
53 changes: 53 additions & 0 deletions AspnetIdentitySample/Views/Account/PasswordReset.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
@model AspnetIdentitySample.Models.PasswordResetViewModel

@{
ViewBag.Title = "PasswordReset";
}

<hgroup class="title">
<h1>@ViewBag.Title.</h1>
</hgroup>

<p class="text-success">@ViewBag.StatusMessage</p>

@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)

<fieldset class="form-horizontal">
<legend>PasswordResetViewModel</legend>

<div class="control-group">
@Html.LabelFor(model => model.Token, new { @class = "control-label" })
<div class="controls">
@Html.EditorFor(model => model.Token)
@Html.ValidationMessageFor(model => model.Token, null, new { @class = "help-inline" })
</div>
</div>

<div class="control-group">
@Html.LabelFor(model => model.Password, new { @class = "control-label" })
<div class="controls">
@Html.EditorFor(model => model.Password)
@Html.ValidationMessageFor(model => model.Password, null, new { @class = "help-inline" })
</div>
</div>

<div class="control-group">
@Html.LabelFor(model => model.ConfirmPassword, new { @class = "control-label" })
<div class="controls">
@Html.EditorFor(model => model.ConfirmPassword)
@Html.ValidationMessageFor(model => model.ConfirmPassword, null, new { @class = "help-inline" })
</div>
</div>

<div class="form-actions no-color">
<input type="submit" value="Change password" class="btn" />
</div>
</fieldset>
}

@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@{
ViewBag.Title = "Register";
}
<hgroup>
<h2>@ViewBag.Title.</h2>
</hgroup>
<p class="text-success">@ViewBag.StatusMessage</p>
7 changes: 7 additions & 0 deletions AspnetIdentitySample/Views/Account/Register.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@
@Html.PasswordFor(m => m.ConfirmPassword)
</div>
</div>

<div class="control-group">
@Html.LabelFor(m => m.Email, new { @class = "control-label" })
<div class="controls">
@Html.TextBoxFor(m => m.Email)
</div>
</div>

<div class="control-group">
@Html.LabelFor(m => m.HomeTown, new { @class = "control-label" })
Expand Down