In this post we’ll complete on top of what we’ve already built, and we’ll cover the below topics:

Send Confirmation Emails after Account Creation.

Configure User (Username, Email) and Password policy.

Enable Changing Password and Deleting Account.

1 . Send Confirmation Emails after Account Creation

ASP.NET Identity 2.1 users table (AspNetUsers) comes by default with a Boolean column named “EmailConfirmed”, this column is used to flag if the email provided by the registered user is valid and belongs to this user in other words that user can access the email provided and he is not impersonating another identity. So our membership system should not allow users without valid email address to log into the system.

The scenario we want to implement that user will register in the system, then a confirmation email will be sent to the email provided upon the registration, this email will include an activation link and a token (code) which is tied to this user only and valid for certain period.

Once the user opens this email and clicks on the activation link, and if the token (code) is valid the field “EmailConfirmed” will be set to “true” and this proves that the email belongs to the registered user.

To do so we need to add a service which is responsible to send emails to users, in my case I’ll use Send Grid which is service provider for sending emails, but you can use any other service provider or your exchange change server to do this. If you want to follow along with this tutorial you can create a free account with Send Grid which provides you with 400 email per day, pretty good!

1.1 Install Send Grid

Now open Package Manager Console and type the below to install Send Grid package, this is not required step if you want to use another email service provider. This packages contains Send Grid APIs which makes sending emails very easy:

1

install-packageSendgrid

1.2 Add Email Service

Now add new folder named “Services” then add new class named “EmailService” and paste the code below:

What worth noting here that the class “EmailService” implements the interface “IIdentityMessageService”, this interface can be used to configure your service to send emails or SMS messages, all you need to do is to implement your email or SMS Service in method “SendAsync” and your are good to go.

In our case we want to send emails, so I’ve implemented the sending process using Send Grid in method “configSendGridasync”, all you need to do is to replace the sender name and address by yours, as well do not forget to add 2 new keys named “emailService:Account” and “emailService:Password” as AppSettings to store Send Grid credentials.

After we configured the “EmailService”, we need to hock it with our Identity system, and this is very simple step, open file “ApplicationUserManager” and inside method “Create” paste the code below:

As you see from the code above, the “appUserManager” instance contains property named “EmailService” which you set it the class we’ve just created “EmailService”.

Note: There is another property named “SmsService” if you would like to use it for sending SMS messages instead of emails.

Notice how we are setting the expiration time for the code (token) send by the email to 6 hours, so if the user tried to open the confirmation email after 6 hours from receiving it, the code will be invalid.

1.3 Send the Email after Account Creation

Now the email service is ready and we can start sending emails after successful account creation, to do so we need to modify the existing code in the method “CreateUser” in controller “AccountsController“, so open file “AccountsController” and paste the code below at the end of the method:

The implementation is straight forward, what we’ve done here is creating a unique code (token) which is valid for the next 6 hours and tied to this user Id only this happen when calling “GenerateEmailConfirmationTokenAsync” method, then we want to build an activation link to send it in the email body, this link will contain the user Id and the code created.

Eventually this link will be sent to the registered user to the email he used in registration, and the user needs to click on it to activate the account, the route “ConfirmEmailRoute” which maps to this activation link is not implemented yet, we’ll implement it the next step.

Lastly we need to send the email including the link we’ve built by calling the method “SendEmailAsync” where the constructor accepts the user Id, email subject, and email body.

1.4 Add the Confirm Email URL

The activation link which the user will receive will look as the below:

1

http://localhost/api/account/ConfirmEmail?userid=xxxx&code=xxxx

So we need to build a route in our API which receives this request when the user clicks on the activation link and issue HTTP GET request, to do so we need to implement the below method, so in class “AccountsController” as the new method as the below:

The implementation is simple, we only validate that the user Id and code is not not empty, then we depend on the method “ConfirmEmailAsync” to do the validation for the user Id and the code, so if the user Id is not tied to this code then it will fail, if the code is expired then it will fail too, if all is good this method will update the database field “EmailConfirmed” in table “AspNetUsers” and set it to “True”, and you are done, you have implemented email account activation!

Important Note: It is recommenced to validate the password before confirming the email account, in some cases the user might miss type the email during the registration, so you do not want end sending the confirmation email for someone else and he receives this email and activate the account on your behalf, so better way is to ask for the account password before activating it, if you want to do this you need to change the “ConfirmEmail” method to POST and send the Password along with user Id and code in the request body, you have the idea so you can implement it by yourself 🙂

2. Configure User (Username, Email) and Password policy

2.1 Change User Policy

In some cases you want to enforce certain rules on the username and password when users register into your system, so ASP.NET Identity 2.1 system offers this feature, for example if we want to enforce that our username only allows alphanumeric characters and the email associated with this user is unique then all we need to do is to set those properties in class “ApplicationUserManager”, to do so open file “ApplicationUserManager” and paste the code below inside method “Create”:

2.2 Change Password Policy

The same applies for the password policy, for example you can enforce that the password policy must match (minimum 6 characters, requires special character, requires at least one lower case and at least one upper case character), so to implement this policy all we need to do is to set those properties in the same class “ApplicationUserManager” inside method “Create” as the code below:

1

2

3

4

5

6

7

8

9

10

//Rest of code is removed for brevity

//Configure validation logic for passwords

appUserManager.PasswordValidator=newPasswordValidator

{

RequiredLength=6,

RequireNonLetterOrDigit=true,

RequireDigit=false,

RequireLowercase=true,

RequireUppercase=true,

};

2.3 Implement Custom Policy for User Email and Password

In some scenarios you want to apply your own custom policy for validating email, or password. This can be done easily by creating your own validation classes and hock it to “UserValidator” and “PasswordValidator” properties in class “ApplicationUserManager”.

For example if we want to enforce using only the following domains (“outlook.com”, “hotmail.com”, “gmail.com”, “yahoo.com”) when the user self registers then we need to create a class and derive it from “UserValidator<ApplicationUser>” class, to do so add new folder named “Validators” then add new class named “MyCustomUserValidator” and paste the code below:

errors.Add(String.Format("Email domain '{0}' is not allowed",emailDomain));

result=newIdentityResult(errors);

}

returnresult;

}

}

What we have implemented above that the default validation will take place then this custom validation in method “ValidateAsync” will be applied, if there is validation errors it will be added to the existing “Errors” list and returned in the response.

In order to fire this custom validation, we need to open class “ApplicationUserManager” again and hock this custom class to the property “UserValidator” as the code below:

1

2

3

4

5

6

7

//Rest of code is removed for brevity

//Configure validation logic for usernames

appUserManager.UserValidator=newMyCustomUserValidator(appUserManager)

{

AllowOnlyAlphanumericUserNames=true,

RequireUniqueEmail=true

};

Note: The tutorial code is not using the custom “MyCustomUserValidator” class, it exists in the source code for your reference.

Now the same applies for adding custom password policy, all you need to do is to create class named “MyCustomPasswordValidator” and derive it from class “PasswordValidator”, then you override the method “ValidateAsync” implementation as below, so add new file named “MyCustomPasswordValidator” in folder “Validators” and use the code below:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

publicclassMyCustomPasswordValidator:PasswordValidator

{

publicoverrideasyncTask<IdentityResult>ValidateAsync(stringpassword)

{

IdentityResult result=awaitbase.ValidateAsync(password);

if(password.Contains("abcdef")||password.Contains("123456"))

{

varerrors=result.Errors.ToList();

errors.Add("Password can not contain sequence of chars");

result=newIdentityResult(errors);

}

returnresult;

}

}

In this implementation we added some basic rule which checks if the password contains sequence of characters and reject this type of password by adding this validation result to the Errors list, it is exactly the same as the custom users policy.

Now to attach this class as the default password validator, all you need to do is to open class “ApplicationUserManager” and use the code below:

1

2

3

4

5

6

7

8

9

10

//Rest of code is removed for brevity

// Configure validation logic for passwords

appUserManager.PasswordValidator=newMyCustomPasswordValidator

{

RequiredLength=6,

RequireNonLetterOrDigit=true,

RequireDigit=false,

RequireLowercase=true,

RequireUppercase=true,

};

All other validation rules will take place (i.e checking minimum password length, checking for special characters) then it will apply the implementation in our “MyCustomPasswordValidator”.

3. Enable Changing Password and Deleting Account

Now we need to add other endpoints which allow the user to change the password, and allow a user in “Admin” role to delete other users account, but those end points should be accessed only if the user is authenticated, we need to know the identity of the user doing this action and in which role(s) the user belongs to. Until now all our endpoints are called anonymously, so lets add those endpoints and we’ll cover the authentication and authorization part next.

3.1 Add Change Password Endpoint

This is easy to implement, all you need to do is to open controller “AccountsController” and paste the code below:

Notice how we are calling the method “ChangePasswordAsync” and passing the authenticated User Id, old password and new password. If you tried to call this endpoint, the extension method “GetUserId” will not work because you are calling it as anonymous user and the system doesn’t know your identity, so hold on the testing until we implement authentication part.

The method “ChangePasswordAsync” will take care of validating your current password, as well validating your new password policy, and then updating your old password with new one.

Do not forget to add the “ChangePasswordBindingModel” to the class “AccountBindingModels” as the code below:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

publicclassChangePasswordBindingModel

{

[Required]

[DataType(DataType.Password)]

[Display(Name="Current password")]

publicstringOldPassword{get;set;}

[Required]

[StringLength(100,ErrorMessage="The {0} must be at least {2} characters long.",MinimumLength=6)]

[DataType(DataType.Password)]

[Display(Name="New password")]

publicstringNewPassword{get;set;}

[Required]

[DataType(DataType.Password)]

[Display(Name="Confirm new password")]

[Compare("NewPassword",ErrorMessage="The new password and confirmation password do not match.")]

publicstringConfirmPassword{get;set;}

}

3.2 Delete User Account

We want to add the feature which allows a user in “Admin” role to delete user account, until now we didn’t introduce Roles management or authorization, so we’ll add this end point now and later we’ll do slight modification on it, for now any anonymous user can invoke it and delete any user by passing the user Id.

To implement this we need add new method named “DeleteUser” to the “AccountsController” as the code below:

Been here in the past months and I am learning new things in every post you have.. –I’m just another kid who wants to be something great.. and I tell you.. when that happen.. I will put your name as one my “hero”… Thank you so much…

I’ve been following you for some time now, and I appreciate your approach to start with an empty project and add what you need with adequate explanation as you go. I find myself eager and watching for your next post as you are regular reading for me. Great job Taiseer!

Hi Miguel,
Thanks for your nice words,
Double check that you have created and named the route “ConfirmEmailRoute” correctly, as well you are passing the exact parameters. This is only what I can think of now.
Download the repo and compare the code, I’m sure there is simple glitch there.
Hope this helps!

Hi Taiseer,
What´s the point in creating an email confirmation api endpoint?
The user will see nothing else than a white screen in the browser.
The logical thing would be creating a web page to show a confirmation message, but I guess in this post you just wanted to focus on webapi.

Apart from that, please tell me what you think about this

In my case, I´m implementing all this from a mobile application and I´m trying to make things easy to the user. Imagine the situation: a user registers in the app and receives a message asking him/her to check the email. The email will redirect the user to a web page (confirmation page), and then, that user has to go back to the app. 4 step process (including registration form) is a bit overhead IMO.

So I was thinking about sending a short code (like the kind of sms confirmation codes) to the email so the user can just write it in a textbox (inside the mobile app) instead of using urls. I´m not sure if there is any way to modify the confirmation token asp.net generates to make for example, a 4 character number code. In that case you could see the code in the push notification of your email box and even no need to open it

Hi Diego,
As you suggested you need to build a GUI on your system where in contains a link for the “ConfirmEmailRoute” end point, once the user invokes this endpoint (click on that link) and you receive 200 OK status from the API, youir GUI needs to display confirmation message and maybe redirect him to the application as this SO question. Never tried it before 🙂
Regarding send SMS, as you suggested here you are going to send the SMS to the email so the user might need to open the email to read the SMS code there and then close the email and go back to application to enter it, so the same number of steps.
As well I’m not sure if you can generate friendly token (4 digits) and attach it to the user Id so the validation for this token happens seamlessly as it happens in method “AppUserManager.ConfirmEmailAsync”, I need to check this.

I´ve been reading about this in stack-overflow and many people agree that email confirmations on mobile applications are a no-go for many users. Of course that depends on your project needs but reasonable in many cases. So a nice way to go would be:

1. You send the welcome-confirmation email
2. The user can start using the app without confirming
3. After a time period you remind the user to confirm the account (by email)
4. After another time period, if the account has not been confirmed, you just delete it (this can be done in a background scheduled job)

That way, the users just trying to test your app will be able to do it quickly. And if they are interested after all, clicking a link shouldn´t be a problem.

This issue with the SendGrid service trying to send confirmation email, make sure you are using the same NuGet package I have used in the project by checking packages.config file and double check that SendGrid username and password are set correctly in web.config as you obtained them from SendGrid after creating a SendGrid account.

What is not clear about it? It interface used to separate the implementation of your SMS service or Email service from Web API logic, it has method named “SendAsync” in order to implement your sending logic in it

First off I would like to thank you for your post and all the information concerning JWT. I am currently doing an internship in a company where I was asked to do a small authentication and authorization using Identity + JWT. I ran into a small bug and I don’t know if its me that did not implement your explications properly but for some reason I cannot seem to be able to do any calls to Identity, for example User.Identity.GetUserId(); is always null. It feels like the data/information from my token does not get passed. Would you be able to give me any pointers or would you have any idea? I have been looking at your AngularJSAuthentication solution and all your other post and I can’t seem to be able to find out what it is.

Hi Simon, are you calling the method User.Identity.GetUserId(); inside a protected controller? A controller or action method attributed with [Authorize]? If yes then the Identity should be set, can you try checking the property User.Identity.Name too? Does it return the authenticated UserId?

I am also having the problem with User.Identity except User.Identity.Name = “”. Also for me IsAuthenticated = false. I can decode the JWT token and my username is contained therein. Not sure why Identity is not picking it up.

I had the same issue. My user was authorized, but the returned UserId was null. I guess, the name claim has the wrong scheme. It had “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name” instead of “nameidentity” at the end. Thus the method returnes null.

The callback URL is for a GET to the API, but how do you handle the case where the front end is solely Angular? How can I get the ConfirmEmail API function to, upon execution from the email link click event, redirect back to my front end Angular site after updating the EmailConfirmed flag?

Hi Taiseer,
I tried to create a free SendGrid account. They didn’t provide me an account since I do not have a website. Can you please show me how to use gmail or hotmail account instead SendGrid ? (even asp.net tutorials use sendGrid, it looks like they may have stoped the service for leaners, if you can provide a free email alternative it would be beneficial to new learners)

This is what SendGrid support said:

“Thank you for providing further information. Although to provision your account we’ll need to know what type of emails you’ll be sending using our service, the website provided during registration was not sufficient to help us determine this. Without a valid, working website upon which we can determine this, your account will not be provisioned. Please get back in touch with us when your website is nearing a state of completion.
Best,
IULIANA O.
Technical Support Engineer
SendGrid”

just an expansion on the comment:
“Notice how we are setting the expiration time for the code (token) send by the email to 6 hours”

so far, my testing on the Indentity 2.1 framework would indicate that the token contains datetime information on when it was sent, rather than any data on when it is to expire. The ConfirmEmailAsync method then seems to apply the TokenLifespan as part of validating the token. The relevance of this is that changing TokenLifespan (in testing or production) will be effective retrospectively on tokens previously sent.

Thank you for the good article! Although i followed your steps exactly, there seems to be an issue, at least for me: When i send a create-user request, the programme creates a new user, but does not call the EmailService class so no email is sent. Is this a known issue? Thanks in advance 🙂

Hi Michael, glad you liked it, I guess you are missing registering the service in AppUserManager as this LOC. If it is already there, check that your SendGrid ApiId and Secret are correct.
Hope this will help.

Hi, thank you for your quick response! I checked the registering of the EmailService in AppUserManager, that wasn’t the problem. The credentials for the SendGridAPI are fine aswell. But by inserting Debug.writeline commands i found out that the ApplicationUserManager class is not called. I tried your downloaded your version from github and there it worked just perfectly and the output-commands were shown in the console. Do you know anything else that could be the problem?

Hi Taiseer, Great article, all your articles have helped me a lot, thanks so much.
I’m still a bit confused about the emailservice, I followed your AngularJsAuthentication tutorials and so i dont have a ApplicationUserManager class or a “Create” method to plug in the the EmailService with Identity system, where should I place the body of code?

Hi Mazin,
If you need to use the email service to send emails, then you have to user the ASP.NET Identity system and create an instance of the UserManager, and assign the “EmailService” property to your email sending logic, hope this somehow clarifies your concern.

Hello Taiseer,
I have a quick question. May be simple however I’ve googled away and haven’t exactly found the answer I am looking for. SO I am building a web app that utilizes AngularJS for the Frontend. Specifically using the Ui,router rather than ngRoute. So I configured a state(route) that has the parameters of UserId and Code in order to use the parameters in my ConfirmEmailController.js . In the ConfirmEmailController.js I call to the Account controller which will then confirm the email. Upon failure or success the html will display the response message. My Issue is this… In the email that gets sent to the User, the link needs to be something like this Here
However, in the AccountController.cs under method Register() , I cannot get the callbackUrl to be correct. I mean it does output the link as I would expect, but when clicked I get this error “The request filtering module is configured to deny a request that contains a double escape sequence.” . So I ask you how can I build a link that will pass the UserId and Code in an email that doesn’t compromise the built in security that’s blocking double spacing, but handle the View and Controller in Angular. OR Am I putting much more work into it than I need to and there is a simpler way to accomplish this? Thank you for taking the time to read and respond to my question! Sorry for the long message but I wanted to be thorough.

I’m not sure if you need to URL encode the code generated then decode it once you receive it, this is the only thing that I’m suspecting now. As well you might try sending the activation code as a query string not part of the URI.

Hello! And thank you for your reply! I ended up sending it as query strings. Both userId and code. Just have to have the user login and it’ll call to the api/Account . My only issue is that the ‘+’ in the userId’s gets replaced by spaces. Its Angular. It used to be encoded as %2B which is what I need, however many people filed issues with it on github because they needed it to be treated as %20 ( a space ) for search query strings. Since then it has been updated and now creates a problem since I need the literal plus sign. I am going to see if there is a way to just replace its encoding back to %2B. If you’ve got any insight or a work around that would be much appreciated! . Thank you again!

SO It was an easy fix. Just do a string.replace on the spaces and put +’s there. However my final error is “Invalid Token” . The result.Succeeded from the ConfirmEmailAsync comes back false. I placed breakpoints in the Register method and the ConfirmEmail method to verify the userId and code generated at both spots. They are identical. I’m not exactly sure what is going on at this point.

FIXED! Sorry for the various replies but it’s been an interesting journey haha. SO seems like even if I do the string.replace in the frontend, when I do the $http call to the backend angular re-encodes and decodes it. Easy solution. Just do the code = code.replace(” “,”+”); right before calling ConfirmEmailAsync();
THANK YOU for all your help!

Hi Steven,
It is encoding issue as you suggested, I do not know why the ASP.NET team didn’t generate the confirmation code using safe URL characters, they know that those codes will be transmitted in URL.

Hi Taiseer,
I keep getting this error when I run it locally , could you please advise?
FYI I added the below keys which are valid:

exceptionMessage: “Bad Request Check `Errors` for a list of errors returned by the API.”
exceptionType: “Exceptions.InvalidApiRequestException”
stackTrace: ” at SendGrid.ErrorChecker.CheckForErrors(HttpResponseMessage response, Stream stream) at SendGrid.ErrorChecker.d__0.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SendGrid.Web.d__0.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at AspNetIdentity.Services.EmailService.d__1.MoveNext() in c:\users\armaghanbabak\documents\visual studio

I have followed your part 1 tutorial, so far it has worked awesome, but in this part 2, you said place the code in ApplicationUserManager class, which you have not specified when it was created. I am looking your project in the GitHub and seeing you have Infrastructure folder and there you have it already, so I am trying to copy the code from there and trying to understand each bit of code. Please advice if I missed something.
Thanks,
Hassan

For anyone who might run in to this kind of issue that if you are using different attributes than just [Route] or [HttpGet]… On confirmEmail action you must put the attribute [HttpGet] as well.. otherwise your link to confirm email won’t work ..

Not sure why, may be Taiseer could add something awesome here on this just like his articles 🙂

Hey Taiseer, Very useful articles, specially in a world where there aren’t much resources on the subject of identity … Hats off my dear !!!

Thanks for the way you have narrated the story. I stand at a little confused point and need your help in getting out of this. it is a bit lengthy one, request you to go through it patiently. Thanks for your time.

I work on an application where I have a separate MVC layer and Web API Layer, both have the same authentication mechanism, I have chosen the individual accounts authentication option while adding the projects. The web api service layer will be directly accessed by some other mobile clients also.

But when the user logs in through MVC he should be able to access Web Api seamlessly, but I don’t want to really pass the username and password fro MVC to the Web Api layer, I am told it is a bad practice. but i need to authenticate and authorize my user, so the only option i have thought of is to have a default account at Web API level to issue tokens, and this will be called from MVC post the authentication and a token will be returned which is written to a cookie in the client. Now the Ajax calls from the UI can use this bearer token and get the job done.

The only glitch I have here is that, because I am using a default account I need user details again for authorization at service level, though I am doing authorization at my UI level. The user can spoof the system. I was lost here and came up with a solution like, when the user logs in to MVC will send across user details also along with the call to get the WebAPI token and issue another token to the user so that the user uses both of the tokens to make a call to web api from MVC.

I am not sure if this works or if it is even the best way. I just wanted to check with you, how I should go from here. Any help on this will be really great.

Your proposed solution is good, you need to obtain an access token while you are authenticating the user for the MVC application, so you only send the username/password only once, once you obtain the access token you can store in a cookie for further use.

First of all, this article is AWESOME. I am able to get a clear view of OAuth Identity Services because of your articles. I created the confirm email functionality for new User. The confirm email link validity is set to 24 hours as shown in this article, but somehow the link expires after 50 mins. I am unable to figure out where the issue is. Could you please suggest something.
Regards,
Rashmi

I found the solution to this issue. I am posting it if somebody faced the same issue. In my case the services and web API were on different servers. Different machine keys caused this issue. So I generated the machine key for my Web application and posted the same machine key in web.config file of Identity service. After that it worked. For more information on generating machine key, following link is helpful.http://gunaatita.com/Blog/How-to-Generate-Machine-Key-using-IIS/1058

The confusion around ApplicationUserManager is because it was not created in Part 1. According to the Index at the top of this post, this is Part 2. And up until now, there has been no mention of an ApplicationUserManager. But, seeing that it is in the GIT repository, I’m not too worried. But it does kind of negatively impact the didactic flow of the articles.

Thank you for the great post. In my case I need to validate both email and phone number for one given account.
I can generate email token with GenerateEmailConfirmationTokenAsync and then ConfirmEmailAsync.
I didn’t find related methods for SMS.

Taiseer….awesome series. Everything working perfectly. Your tutorials are extremely clear and accurate. Very rare. I do have one issue….I am using SendGrid for my Email Confirmation. When I change EmailConfirmation to POST as you recommend for doing Password comparison, the link that arrives in the confirmation email is no longer functional since a link can’t generate HTTP POST without intervening JScript. I just get a ‘The requested resource does not support http method ‘GET” error. Can you give a little detail on how to implement the password check in the confirmation (including maybe some suggestions for encrypting it)?

I think you facing an issue with sending the validation token generated by asp.net identity, it contains unsafe url chars, so you should encode it before sending it, then decode it once you receive it.

Hi,
This is very deep implementation detail for your case, I really can not look at it right now but you could add any link you want in your response and the user will receive it in the email and click on it and get redirected to this URL.

Like others I have found your series on web api identity and token authorization very useful.

I have a question about using email/text to validate the user identity. I am writing an API for a mobile app; on registration user will need either to enter email or mobile number so that their identity can be verified. Since sending email/text message to user is not free, I want to protect from being attached by someone who tries to create many fake registrations. For example, if someone somehow knows my user registration url and since user post request has to allow anonymous (to allow real user to register through the mobile app); he/she can post many fake registrations each of which will trigger sending an email or a text message; which can be costly.

Do you have any advice on preventing such an attack? My idea is to add a custom header in my new user post request so that I can validate this header value in each post request and if the header value is not matching a secret then I will reject the post request. And since this is for a mobile app, it’s safe to include the secret in the header on the client side for real user registration. Does this make sense?
Thanks.

i really love your articles! They help me soooooo much, but i still got a problem 🙁

The Destination of IdentityMessage in my EmailService is always null. So i tried to get the email of the newly created user, and “UserManager.GetEmail” always returns null too, but the user is created as i can see in the database and his id is correct too. Do you have any idea what this can be, or do you had any issue like this before?

That is strange, did you try to download the repo and test it out and compare it to your code?
Really hard to troubleshoot the issue without seeing your code, so my recommendation is to download the repo and compare.

Hello,
I am very much enjoying this tutorial. It is helping me with the understanding i have needed, but then i run into this error which i still can’t solve. I am still on the first post “account management” and i get this error:
{“message”:”The request is invalid.”,”modelState”:{“”:[“Name cannot be null or empty.”]}}
I do not know where to find the error to fix it.
Please help me

Hi Vladimir,
Hope you already found the solution. If not, the problem is just that here Taiseer specifies the full namespace of the EmailService you created before. Just remove the “AspNetIdentity.WebApi.Services.” and it should work perfectly 😉

Im having problem with the username validation and UniqueEmail validation.

I have added as you mentioned the :

appUserManager.UserValidator = new MyCustomUserValidator(appUserManager)
{
AllowOnlyAlphanumericUserNames = true,
RequireUniqueEmail = true
};
to my ApplicationUserManager class, but when i try to create a new user, its not being used.

2 years later and this walk-through is still extremely helpful. Bravo and thank you!

I’m new to API access security, so a few questions for you:

1) When you mention changing the “ConfirmEmail” route to POST, could you elaborate on how this would be done? The only way I can fathom would be to send a link that leads to a webpage (something like http://www.mywebsite.com/validate?userid=xxxx&code=xxxx), where the user would then be prompted to enter the password that they just created for the account. This would effectively stop an unintended user from validating an account by accident, that they didn’t create.

2) Seeing as these posts ARE 2 years old now, are there any major differences in implementation that you would recommend given the current state of the .NET Identity Framework?

3) Would you still say that the .NET Identity Framework is one of the best ways to securely manage WebAPI access by today’s standards? I want to make sure I’m not implementing / familiarizing myself with something that has quickly fallen behind standard-wise.

Hello LK,
Thanks for your kind comment 🙂
Please find the answers below:
1. If you need to have ultimate security workflow, asking for the password is a better approach, so you need to include the password when you validate the code and userid/password.
2. If you are using ASP.NET 4.6 (Not ASP.NET Core) this post is very relevant, I believe I was using the latest version of ASP.NET Identity (2.1) which is used with ASP.NET 4.6
3. Well the Identity framework is used to store your users, roles, claims, etc.. the OWIN middlewares for Authorization are used to protect your WebAPI, I recommend always to take a look at the ThinkTecture Identity Server if you want to learn something which is built on OAuth and OpenId connect standards and provides you SSO, support for multiple clients, etc..