public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
        {
            var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");
            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

            string hashedTokenId = Helper.GetHash(context.Token);

            using (AuthRepository _repo = new AuthRepository())
            {
                var refreshToken = await _repo.FindRefreshToken(hashedTokenId);

                if (refreshToken != null)
                { 
                    //Get protectedTicket from refreshToken class
                    context.DeserializeTicket(refreshToken.ProtectedTicket);
                    var result = await _repo.RemoveRefreshToken(hashedTokenId);
                }
            }
        }
        public async Task CreateAsync(AuthenticationTokenCreateContext context)
        {
            var clientid = context.Ticket.Properties.Dictionary["as:client_id"];

            if (string.IsNullOrEmpty(clientid))
            {
                return;
            }
            
            //we are generating a unique identifier for the refresh token
            var refreshTokenId = Guid.NewGuid().ToString("n");

            using (AuthRepository _repo = new AuthRepository())
            {
                //we are reading the token lifetime value from the OWIN context
                //this will determine how long will the refreshtoken will be valid
                var refreshTokenLifeTime = context.OwinContext.Get<string>("as:clientRefreshTokenLifeTime");

                var token = new RefreshToken() { 
                    Id = Helper.GetHash(refreshTokenId),
                    ClientId = clientid,
                    Subject = context.Ticket.Identity.Name,
                    IssuedUtc = DateTime.UtcNow,
                    ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime)) // we are setting the lifetime of the refresh token here
                };

                context.Ticket.Properties.IssuedUtc = token.IssuedUtc;
                context.Ticket.Properties.ExpiresUtc = token.ExpiresUtc;

                //responsible for serializing the contect and inserting it into the database
                token.ProtectedTicket = context.SerializeTicket();

                //Addrefreshtoken in the AuthRepo
                //This will add our refreshtoken in the DB
                var result = await _repo.AddRefreshToken(token);

                if (result)
                {
                    context.SetToken(refreshTokenId);
                }
                
            }
        }
        /// <summary>
        /// used to validate the username and password sent to the authorization server's token endpoint.
        /// we will use the AuthRepository.FindUser method to check the username and password in the DB.
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {

            var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");

            if (allowedOrigin == null) allowedOrigin = "*";
 
            ///This will allow CORS(Cross-origin resource sharing) in our token middleware provider
            /// if we forget to add this in our Owin context, generating the token will fail when you try to call it from the browser.
            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

            using(AuthRepository _repo = new AuthRepository())
            {
                //check for the user identity
                IdentityUser user = await _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(ClaimTypes.Name, context.UserName));
            identity.AddClaim(new Claim("sub", context.UserName));
            identity.AddClaim(new Claim("role","user"));

            var props = new AuthenticationProperties(new Dictionary<string,string>
                {
                    {
                        "as:client_id",(context.ClientId == null)? string.Empty : context.ClientId
                    },
                    {
                        "userName",context.UserName
                    }
                
                });

            var ticket = new AuthenticationTicket(identity, props);

            ///token genation happens here
            context.Validated(ticket);
        }
        /// <summary>
        /// used for validating client authentication.
        /// unfortunately we only have one client so we'll always return that its validated?
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            string clientId = string.Empty;
            string clientSecret = string.Empty;
            Client client = null;
            
            //we are supporting both Authorization header and form encoded to get the clientId and clientSecret
            if(!context.TryGetBasicCredentials(out clientId, out clientSecret))
            {
                //this is to get the x-www-form-urlencoded
                context.TryGetFormCredentials(out clientId, out clientSecret);
            }

            //we are checking if the consumer did not set any client information.
            if(context.ClientId == null)
            {
                context.Validated();
                //context.SetError("invalid_clientId","ClientId should be sent.");
                return Task.FromResult<object>(null);

            }

            /*after we receive the client id we need to check our database if the client is
            already registered with our back end API.*/
            using(AuthRepository _repo = new AuthRepository())
            {
                client = _repo.FindClient(context.ClientId);
            }

            /*if client_id is not registered then invalidate the context and reject the request*/
            if(client == null)
            {
                context.SetError("invalid_clientId", string.Format("Client '{0}' is not registered in the system.", context.ClientId));
                return Task.FromResult<object>(null);
            }

            //if the client is registered we need to check his application type.
            //if client is JavaScript - Non Confidential then we will not ask for the secret
            if(client.ApplicationType == Models.Enum.ApplicationTypes.NativeConfidential)
            {
                if(string.IsNullOrWhiteSpace(clientSecret))
                {
                    context.SetError("invalid_clientId","Client secret is invalid.");
                    return Task.FromResult<object>(null);
                }
                else
                {
                    //if Native - Confidential App then client secret will be validated against the secret stored in the DB
                    if(client.Secret != Helper.GetHash(clientSecret))
                    {
                        context.SetError("invalid_clientId","Client secret is invalid.");
                        return Task.FromResult<object>(null);
                    }
                }
            }

            //we will check if the client is active
            if(!client.Active)
            {
                context.SetError("invalid_clientId","Client is inactive.");
                return Task.FromResult<object>(null);
            }

            /*We will store the client allowed origin and refresh token life time on the Owin
             context so it will be available once we generate the refresh token and set expiry life time*/
            context.OwinContext.Set<string>("as:clientAllowedOrigin", client.AllowedOrigin);
            context.OwinContext.Set<string>("as:clientRefreshTokenLifeTime",client.RefreshTokenLifeTime.ToString());

            //if all is valid then we will mark the context as valid.
            context.Validated();
            return Task.FromResult<object>(null);
        }
 public AccountController()
 {
     _repo = new AuthRepository();
 }