0

We are wanting to implement an API to be used internally and externally and add it to our solutions.

Some environment notes:

We are currently using VS2013, .Net 4.5, EF5, SQL2008, MVC4, C#, and asp.net membership.

We looked into using the new Web Api 2.2 template that comes with VS2015 that uses OWIN.

This appeared to be pretty overkill for what we needed so I decided to roll my own simple token based auth.

The only hard requirements were that it be token-based and you only need an api "key" to login with.

So the first call is a GET to the login method where you will pass in your api key

/Login/Login?apikey=12345678

This will then generate a token based on your IP, apiKey and timestamp.

    private static string GenerateTokenHash(string apiKey)
    {
        var encoding = new System.Text.ASCIIEncoding();
        byte[] keyByte = encoding.GetBytes(apiKey);
        byte[] messageBytes = encoding.GetBytes(GetIP4Address() + DateTime.Now.ToString());

        HMACSHA256 sha = new HMACSHA256(keyByte);
        var hash = sha.ComputeHash(messageBytes);
        return Convert.ToBase64String(hash);
    }

I then store these logged in tokens in a static Dictionary to keep track of which tokens are valid instead of storing them in a DB.

The api end user then passes in this token to subsequent requests using a new http header called auth_token.

I also createg an AuthorizationFilterAttribute to determine which actions/controllers need to check for a valid token.

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        base.OnAuthorization(actionContext);

        // No auth_token header sent
        if (!actionContext.Request.Headers.Contains(_httpTokenHeaderName))
        {
            actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
            return;
        }

        // Token is not valid
        var token = actionContext.Request.Headers.GetValues(_httpTokenHeaderName).FirstOrDefault();
        if (!TokenManager.ValidateToken(token))
        {
            actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
            return;
        }

        // Token is valid, extend expiration.
        TokenManager.ExtendExpiration(token);
    }

This seems to fit our needs but I'd like to back up the why.

OWIN seems to be very bloated since we'll never need to decouple our backend from sql, or have someone authenticated via Facebook.

Just looking for some pros/cons on each implementation I guess.

  • 2
    I know nothing about OWIN, but the biggest "CON" for doing anything related to security yourself is that doing it wrong has bad consequences. – Steven Burnap Apr 19 '16 at 17:23
  • 2
    ... and that it's easy to get it wrong. – Robert Harvey Apr 19 '16 at 17:26
  • Anything concrete? I'm using the HMAC method to hash the token, not reinventing the wheel there. – user3953989 Apr 19 '16 at 17:34
2

Couple of things after a quick look:

  1. App domain reloads on your server will clear out your token dictionary and cause clients to be logged out. Also not possible to effectively scale this over different machines/load balanced.

  2. You login via a GET rather than a POST. Generally speaking, it is not good practice to send sensitive information via GET (gets stored in server logs, can be cached etc).

  3. If you ever run into an issue where your username is compromised, you need to change the username.

If you have used the username to key to other items (e.g. roles), then you need to update those to suit.

If you have username/password, then all you need to do is change the password - username remains the same.


Also, you don't show the code, but you need to be careful that your storing of tokens into the dictionary is properly thread safe.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.