I have seen this link Two Factor Auth using goolgle authenticator on how to create a two factor authentication in web api, but my requirements are little different.
- I want to use two factor authentication for issuing an access token. (If the user has chosen to enable two factor authentication)
- I would like to create the OTP code using ASP.NET identity itself. (Like the way we do in MVC web application
SignInManager.SendTwoFactorCodeAsync("Phone Code")
The problem with my current implementation is, when I call SignInManager.SendTwoFactorCodeAsync("Phone Code")
I get the error user id not found.
To debug, I tried calling User.Identity.GetUserId();
and it returns the correct user id.
I checked the source code of Microsoft.AspNet.Identity.Owin assembly
public virtual async Task<bool> SendTwoFactorCodeAsync(string provider)
{
var userId = await GetVerifiedUserIdAsync().WithCurrentCulture();
if (userId == null)
{
return false;
}
var token = await UserManager.GenerateTwoFactorTokenAsync(userId, provider).WithCurrentCulture();
// See IdentityConfig.cs to plug in Email/SMS services to actually send the code
await UserManager.NotifyTwoFactorTokenAsync(userId, provider, token).WithCurrentCulture();
return true;
}
public async Task<TKey> GetVerifiedUserIdAsync()
{
var result = await AuthenticationManager.AuthenticateAsync(DefaultAuthenticationTypes.TwoFactorCookie).WithCurrentCulture();
if (result != null && result.Identity != null && !String.IsNullOrEmpty(result.Identity.GetUserId()))
{
return ConvertIdFromString(result.Identity.GetUserId());
}
return default(TKey);
}
As seen from the above code, SendTwoFactorCodeAsync
method internally calls GetVerifiedUserIdAsync
which checks the two factor authentication cookie. As this is a web api project, cookie isn't there and 0 is returned, resulting in user id not found error.
My question, how to correctly implement two factor authentication in web api using asp.net identity?
This is what i have implemented to get this working on an api. i assume you are using the default ASP.NET single user template.
1. ApplicationOAuthProvider
inside GrantResourceOwnerCredentials method you must add this code
Inside CreateProperties method replace the paramenter with userObject like this:
The above code with check if the user has TFA enable, if its enabled it will generate verification code and send it using SMSService of your choice.
2. Create TwoFactorAuthorize Attribute
create response class ResponseData
add TwoFactorAuthorizeAttribute
3. Use TwoFactorAuthorizeAttribute
in a controller use TwoFactorAuthorizeAttribute
4. Verify OTP In your AccountController you must add the api end-point to verify the OTP