1

I have a web API, which is used by a web application and a mobile application. Currently it uses the standard approach of username and password login. For the sake of simplicity we need to send a user a six digit code through SMS; this code combined with there phone number would grant them access to the API.

My question: Would it be possible to generate a six digit number and let the users login with a combination of this code and their phone number?

I was looking at the possibility of just adding it to the request headers and then handling this in the authentication provider, but I am not sure if there is a best practice I should be following here. Security is of high importance of course.

I could just check the headers in the provider and then have the code act accordingly. I have searched for other examples but have not found anything, so this is more a question for guidance and best approach. The code would have a one day expiration and be stored in database after being hashed.

Again, any suggestions would be most appreciated.

allenski
  • 1,652
  • 4
  • 23
  • 39
Tony_89
  • 797
  • 11
  • 39

2 Answers2

0

You will need to Set up SMS for Two-factor authentication with ASP.NET Identity and created a class that implements the interface IIdentityMessageService

public class SmsService : IIdentityMessageService
{
    public Task SendAsync(IdentityMessage message)
    {
        // Send SMS implementation using SMS provider 
    }
}

Then Enable two-factor authentication for the user to force entering generate six digits to complete login process.

ElasticCode
  • 7,311
  • 2
  • 34
  • 45
  • I thought two factor authentication requires you to enter the username and password and then use the code as an extra layer of security. Were as i do not want to enter the username and password at all. I just want to login with a single use code. My understanding of how it works may be wrong though. – Tony_89 Apr 17 '18 at 09:34
  • You will need also to customize `PasswordSignInAsync` in `SignInManager` but at least you need a username or any unique value to identify logged in user. – ElasticCode Apr 17 '18 at 11:24
  • Two factor authentication is not what i need, it still requires you to login with the username and password. I am using a web api so i need to hit the token endpoint and essentially use a custom grant instead of password or refresh_token – Tony_89 Apr 17 '18 at 15:07
  • So you don't need .Net Identity, you can implement custom [Authentication Filter](https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-filters#implementing-the-authenticateasync-method) to do that – ElasticCode Apr 17 '18 at 15:27
0

So the solution to this in my case is to use a custom grant type. In your OAuthProvider you can override the function GrantCustomExtension. You can see below how i handle this.

public override async Task GrantCustomExtension(OAuthGrantCustomExtensionContext context)
    {
        ApplicationUser currentUser = null;
        try
        {
            //custom grant_type
            if (context.GrantType != "sms")
            {
                context.SetError("invalid_grant", "unsupported grant_type");
                return;
            }

            var accessCode = context.Parameters.Get("access_code");
            var phoneNumber = context.Parameters.Get("phone_number");

            if (string.IsNullOrEmpty(accessCode))
            {
                context.SetError("invalid_grant", "Pin Code is required");
                return;
            }

            if (string.IsNullOrEmpty(phoneNumber))
            {
                context.SetError("invalid_grant", "Phone number is required");
                return;
            }

            // Do your authentication logic here.
        }
        catch (Exception ex)
        {
            context.SetError("invalid_grant", "Something went wrong. Please contact tech support.");
        }
    }

I got to this point with the help of this question. ASP.Net Identity 2 - custom response from OAuthAuthorizationServerProvider

You can implement you own grant type and auth logic using this approach. For myself i have a four digit code hashed and stored in the database. When the user logs in with grant type sms i compare the access code to the value in the database and then act accordingly. As for the sms side and sending the token out i use AWS simple notification service. Since the code and sms is sent via a button click it was simple to implement. Hope this helps.

Tony_89
  • 797
  • 11
  • 39