paul sim
paul sim

Reputation: 453

Web Api OWIN - How to validate token on each request

I have two applications

  1. Client application build on ASP.NET MVC
  2. Authentication server build on Web API + OWIN

Have planned authentication as follow

  1. For user login client app will make a request to authication server with logged in credential.
  2. Authication server will generate a token and will send back to client application.
  3. Client application will store that token in local storage.
  4. for each subsequent request client app will attached token kept in local storage in request header.

NOW, ON SERVER SIDE OF CLEINT APP I NEED TO VALIDATE THAT TOKEN COMES WITH EACH REQUEST IS NOT TEMPERED.

  1. Please suggest me how to validate token in each request as i don't know the key the OWIN has used to generate the token.
  2. Is is right to write code to validate token on client app or it should be on authication server.
  3. I am planning to shift all user management code like register user, change password to authentication server so than we can re-use it for different client app- is it right design practice?

So far i have wrote below code to just to create a POC.

=========================OWIN configuration========

    [assembly: OwinStartup(typeof(WebApi.App_Start.Startup))]
    namespace WebApi.App_Start
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                HttpConfiguration config = new HttpConfiguration();

                ConfigureOAuth(app);

                WebApiConfig.Register(config);
                app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
                app.UseWebApi(config);
            }

            public void ConfigureOAuth(IAppBuilder app)
            {
                OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
                {
                    AllowInsecureHttp = false,
                    TokenEndpointPath = new PathString("/token"),
                    AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
                    Provider = new SimpleAuthorizationServerProvider(),

         };

         // Token Generation

                app.UseOAuthAuthorizationServer(OAuthServerOptions);
                app.UseOAuthBearerAuthentication(new 
 OAuthBearerAuthenticationOptions());

            }
        }
    }

==============================oAuth Provided========================

 public class SimpleAuthorizationServerProvider: OAuthAuthorizationServerProvider
    {
        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            context.Validated(); 
        }

        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {


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

            using (AuthRepository _repo = new AuthRepository())
            {
                IdentityUser user =  _repo.FindUser(context.UserName, context.Password);

                if (user == null)
                {
                    context.SetError("invalid_grant", "The user name or password is incorrect.");
                    return;
                }
            }

            var identity = new ClaimsIdentity(context.Options.AuthenticationType);
            identity.AddClaim(new Claim("sub", context.UserName));
            identity.AddClaim(new Claim("role", "user"));

            context.Validated(identity);

        }
    }

Please help,

Thanks,

@Paul

Upvotes: 11

Views: 18847

Answers (4)

AmirReza-Farahlagha
AmirReza-Farahlagha

Reputation: 1212

If you create, sendback, save in localStorage and every thing about JWT Token as correct, you have to know that many ways are in .Net that you can to controlling per request.

Server side controlling:

  1. If you are using Web API Core, in core you can create Middleware that runs as pipline in run time, and you can give context and check token that requested, for more infomation check: This.

  2. If you use of Asp.net MVC, you can use ActionFilter in MVC(Asp.Net-Core have more advance ActionFilter too), that each requests goes through on and you can check every thisng abount request, for more information check: This.

ClientSide Conftolling:

  1. After that you give Token after log in from server side, you have to save data in localstorage that your browser check per request that data, they advantage are the Expireation and every like this issue in token save in localstorage and you and browser can use of this for more information check: This.

GoodLuck.

Upvotes: 0

Efrain
Efrain

Reputation: 3364

Use JSON Web Tokens (JWT) and claims identities, not random tokens that require keeping track of the issued tokens.

A JWT is like a passport issued by a trusted authority. The passport is signed/stamped, and you can verify that it was issued by this trusted authority and that it has not been tampered with. That means, the integrity of the access-right claim present in the token can be verified without keeping state anywhere. The only communication that needs to happen between the trusting application and the authority is an initial (secure) download of the authority's public key (used for signing the tokens).

It's also advisable that you use a standard claims schema, like OpenID Connect ( http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims )

A good book on the topic, which helped me a lot getting an understanding of all these concepts, can be found here: A Guide to Claims-Based Identity and Access Control.

Upvotes: 3

MarkovskI
MarkovskI

Reputation: 1587

One way to verify a token has not been tampered is to sign it using an asymmetric key pair, Identity Server uses this approach as seen here.

In your case if you are rolling your own authentication you will need to implement this yourself, and check on every request probably in a custom middleware that the token is valid.

Upvotes: 0

Marcus Höglund
Marcus Höglund

Reputation: 16801

Please suggest me how to validate token in each request as i don't know the key the OWIN has used to generate the token.

Your current setup, were you have added the app.UseOAuthBearerAuthentication() to the owin pipeline, will authenticate the user from the bearer token which is passed on each request for you. The current user can then be found via HttpContext.Current.User.

Use the Authorize attribute to then decide which users are authorized on certain endpoints. Here's an example where users with the role "user" are allowed to access

[Authorize(Roles="user")]
public class ValuesController : ApiController
{
}

Is is right to write code to validate token on client app or it should be on authication server.

NO, you don't validate the token in client, if your user credentials are wrong you wont get a token at all. That's all you need to know. And also, why should you want to validate the token in the client?

I am planning to shift all user management code like register user, change password to authentication server so than we can re-use it for different client app- is it right design practice?

Reusing a token provider is common. Why invent the wheel for every application? Build one great, or use a third party, and reuse it across your applications.

Upvotes: 3

Related Questions