简体   繁体   中英

Asp.Net Web Api Token Based Authorization WITHOUT OWIN and AspNet.Identity

I am planning to use the codes below for my web api security but i am not sure that is enough safe and logical way. I don't want to use OWIN and AspNet.Identity because it's very complicated for me and i don't understand completely and I don't know how i customize db tables, user roles etc. But my way is simple and very customizable for me.

This is CustomAuthorizeAttribute;

public class CustomAuthorize : AuthorizeAttribute
{
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        if ((actionContext.Request.Headers.GetValues("Host").FirstOrDefault().Contains("localhost:15742")))
        {
            IEnumerable<string> access_token;
            if (actionContext.Request.Headers.TryGetValues("Authorization", out access_token))
            {
                var user = GetUserByToken(access_token);
                if (user!=null && !user.TokenIsExpired)
                {
                    HttpContext.Current.Response.AddHeader("WWW-Authenticate", "Custom " + access_token.FirstOrDefault());
                    return;
                }
                else
                {
                    actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                    HttpContext.Current.Response.AddHeader("WWW-Authenticate", "Custom");
                    return;
                }
            }
            else
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            }
        }
        else
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
        }
    }
}

And this is front end using

<script type="text/javascript">
    $(function () {
        var access_token = $.cookie('access_token');
        if (access_token == undefined) {
            $.cookie('access_token', 'test-token');
        }


        $.ajax({
            url: '/api/account',
            headers: { access_token: access_token },
            success: function (data) {
                document.write(data.name + " " + data.lastname);
            }
        });
    });
</script>

By the way i am sorry about for my English. I hope you understand my problem and i am waiting for your suggestions.

Necroreply for ones who looking to make custom auth attributes :)

First check is redundant, since HTTP request is just a string of text over TCP connection so anyone can connect to your server with TCP client and send whatever header he wants. actionContext.Request.Headers.GetValues("Host").FirstOrDefault().Contains("localhost:15742"))

According to https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

Authorization filters run before the controller action. If the request is not authorized, the filter returns an error response, and the action is not invoked.

the only way you attribute does not set Response is user!=null && !user.TokenIsExpired so this attribute will do the job and can be considered secure.

This header can be removed HttpContext.Current.Response.AddHeader("WWW-Authenticate", "Custom");

Also why would you send auth token again in case of success? HttpContext.Current.Response.AddHeader("WWW-Authenticate", "Custom " + access_token.FirstOrDefault());

Just reduce IF-s nesting level so the code will be easier to read:

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        IEnumerable<string> access_token;

        if (!actionContext.Request.Headers.TryGetValues("Authorization", out access_token))
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            return;
        }

        var user = GetUserByToken(access_token);

        if (user == null || user.TokenIsExpired)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);                
            return;
        }

        // OK
        return;
    }

A lot of ASP.NET code is seems overengineered (and sometimes is :) including OWIN. But it has a purpose – to declare a standard way of doing variuos things, like auth for example.

Imagine everyone will start building their custom attrbiutes, then it will be impossible to just install Google nuget package and do something like

public void ConfigureAuth(IAppBuilder app)
{
     app.UseGoogleAuthentication(
         clientId: "000-000.apps.googleusercontent.com",
         clientSecret: "00000000000");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM