Use two way to create bearer token for users in web api 2 with owin context

1.2k views Asked by At

I have a Asp.net web api 2 project. In this project I use OWIN authentication. I have two kinds of users.

One type of are those who logs in with user name and password, another type are those who logs in with mobile number and a four character word.

I want both of these users go the address /token to get their token, my implementation so far is like this :

This is start up class :

var provider = new AuthorizationServerProvider();
var options = new OAuthAuthorizationServerOptions()
{
    AllowInsecureHttp = true,
    TokenEndpointPath = new PathString("/token"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
    Provider = provider
};
public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        using (DbContext dbContext = new DbContext ())
        {
            var user = dbContext.User
                .Where(a => a.UserName == context.UserName)
                .Where(a => a.Password == context.Password)
                .Select(a => new UserClaim
                {
                    Id = a.Id,
                    UserName = a.UserName,
                    FirstName = a.FirstName,
                    LastName = a.LastName,
                    Roles = a.UserInRoles.Select(w => w.Role.Id).ToList()
                }).FirstOrDefault();

            if (user == null)
            {
                context.SetError("invalid grant", "Provided username and password is incorrect.");
                return;
            }
            identity.AddUserClaim(user);
            context.Validated(identity);
            return;
        }
    }
}

This solution is for users who want to log in with user name , but what about those users who want to log in with mobile number, what should I do ?

1

There are 1 answers

0
Kahbazi On BEST ANSWER

You need to provide two instance of OAuthAuthorizationServerOptions one for authorizing with username and password and one for mobileNumber and code, and then add this two options via authorization middleware to your owin pipeline.

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        // rest of your code

        var userAndPasswordOptions = new OAuthAuthorizationServerOptions(){ ... };
        var mobileAndCodeOptions = new OAuthAuthorizationServerOptions(){ ... };

        app.UseOAuthAuthorizationServer(userAndPasswordOptions);
        app.UseOAuthAuthorizationServer(mobileAndCodeOptions);

        // rest of your code
    }
} 

but you should know in this case these two providers answers to different request Endpoint.

If you need to have one endpoint to provide both type of authorization you can change your GrantResourceOwnerCredentials method in OAuthAuthorizationServerProvider.

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    var identity = new ClaimsIdentity(context.Options.AuthenticationType);

    var form = await context.Request.ReadFormAsync().Result;
    if (form["type"] == "mobile")
    {
        //validate mobileNumber and code
    }
    else
    {
        //validate username and password
    }

    identity.AddUserClaim(user);
    context.Validated(identity);
    return;

}