Webapi with multiple oauth tokens for different users

I am creating my own webapi in asp.net using oauth as my authorization provider. Api wil mainly serves as a provider for different modules as I call them. One of them might be an image gallery, the other might just be a login module with different types of users.

I have the oauth part working fine. Api users can register and then request a token by calling the / Token endpoint with login credentials.

However, now I want to create another separate custom module in the api that is only accessible by the registered user. I want this module to have a different registration and login functionality and have its own login endpoint (/ UserModuleToken or something like that). Users coming from custom module are different users than Api users. So the apiusers are the actual developers who want to call specific modules in my api, and the users from the custom module are the users who register on the site where that module is implemented.

All my apicontrollers have a [Authorize] attribute for the api user and I want some of them, like some function in a custom module, to be decorated with the [UserModuleAuthorize] attribute.

Below you can see my api user entity model:

public class ApiUserEntity : BaseEntity
{
    public string Username { get; set; }
    public string Password { get; set; }
    public string Email { get; set; }
    public string Salt { get; set; }
    public ApiUserLevel Level { get; set; }
}

      

Userervice function that can check the user api:

public UserLoginResult LoginUser(ApiUserEntityLoginForm userForm)
{
    // retrieve user from database
    var user = _userRepository.GetUser(userForm.UserName);

    if(user == null)
        return _modelStateWrapper.AddError(UserLoginResult.UserNotFound, "User does not exist");

    var passwordHash = PasswordHash.HashPassword(user.Salt, userForm.Password);

    // check if password matches with database.
    if (passwordHash != user.Password)
        return _modelStateWrapper.AddError(UserLoginResult.IncorrectPassword, "Incorrect password");

    return UserLoginResult.Success;
}

      

And calling the / Token endpoint in my webapi will call the following token provider function:

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{

    context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

    // create a userloginform object : 
    var loginForm = new ApiUserEntityLoginForm {UserName = context.UserName, Password = context.Password};

    // pass it into the login validation function of the userservice:
    var loginResult = _userService.LoginUser(loginForm);

    // if login result was not sucesful, return an error.
    if (loginResult != UserLoginResult.Success)
    {
        var jsonSerialiser = new JavaScriptSerializer();
        var json = jsonSerialiser.Serialize(_userService.Errors());

        context.SetError("invalid_grant", json);
        return;
    }

    // result was succesful, grant the token.
    var identity = new ClaimsIdentity(context.Options.AuthenticationType);
    identity.AddClaim(new Claim("sub", context.UserName));
    identity.AddClaim(new Claim("role", "user"));

    context.Validated(identity);

}

      

i configure my oauth provider and define / Token endpoint with the following function:

public static void ConfigureOAuth(IAppBuilder app, IUnityContainer container)
{

    var simpleAuthorizationServerProvider = container.Resolve<SimpleAuthorizationServerProvider>();

    var OAuthServerOptions = new OAuthAuthorizationServerOptions()
    {
        AllowInsecureHttp = true,
        TokenEndpointPath = new PathString("/token"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
        Provider = simpleAuthorizationServerProvider
    };

    // Token Generation
    app.UseOAuthAuthorizationServer(OAuthServerOptions);
    app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

}

      

Now I am wondering if it is possible to have multiple token endpoints so that I can have a token for apiusers and then another one for a user that uses a custom user module and protects certain functionality based on those two users.

I couldn't find any information on this after doing extensive internet searches. So I am beginning to believe that this is not a good practice or not possible. If anyone can point me in the right direction, that would be great!

+3


source to share


1 answer


Well I believe you need to set up user authorization based on roles, what you are trying to do is just complicating your decision. You can do the following, inside the method, GrantResourceOwnerCredentials

you need to get the correct role (s) for the authenticated user from the DB store, ie "Admin", and then add them as claims of type "Role" as below code

identity.AddClaim(new Claim(ClaimTypes.Role, "Admin"));
identity.AddClaim(new Claim(ClaimTypes.Role, "Supervisor"));

      

Now, on your controllers, you only need a user with the "Admin" role to access; you need to specify [Authorize(Roles="Admin")]

or possibly multiple roles[Authorize(Roles="Admin,User")]



This is the most direct way to achieve your goal.

Btw this code is from http://bitoftech.net , right? Glad to see my code samples have been used :) Let me know if you need further clarification.

+10


source







All Articles