private static string CreateToken(IEnumerable<Claim> claims, JwtTokenIssuerOptions options)
        {
            var jwtTokenFactory = new JwtTokenFactory(options.Issuer,
                                                      options.Audience,
                                                      options.TokenSigningKey);

            return jwtTokenFactory.GenerateToken(claims, options.TokenLifetime);
        }
        private static IEnumerable<Claim> Authenticate(JwtTokenIssuerOptions options, RequestPayload requestPayload)
        {
            var claims = options.Authenticate(requestPayload.Username, requestPayload.Password);

            // if no claims were created in the authenticate phase then replace with empty claims array
            claims = claims ?? new Claim[0];

            return claims;
        }
        public JwtTokenIssuerMiddleware(OwinMiddleware next, JwtTokenIssuerOptions options)
            : base(next)
        {
            if (options == null)
                throw new ArgumentNullException("options");

            ValidateOptions(options);

            _options = options;
        }
        public static void UseJwtTokenIssuer(this IAppBuilder appBuilder, JwtTokenIssuerOptions options)
        {
            if (appBuilder == null)
                throw new ArgumentNullException("appBuilder");

            if (options == null)
                throw new ArgumentNullException("options");

            appBuilder.Use<JwtTokenIssuerMiddleware>(options);
        }
        private static void ValidateOptions(JwtTokenIssuerOptions options)
        {
            if (options.Authenticate == null)
                throw new ArgumentException("The Authenticate property has no value set", "options");

            if (string.IsNullOrEmpty(options.Issuer))
                throw new ArgumentException("The Issuer property has no value set", "options");

            if (string.IsNullOrEmpty(options.Audience))
                throw new ArgumentException("The Audience property has no value set", "options");

            if (string.IsNullOrEmpty(options.TokenSigningKey))
                throw new ArgumentException("The TokenSigningKey property has no value set", "options");

            if (string.IsNullOrEmpty(options.IssuerPath))
                throw new ArgumentException("The IssuerPath property has no value set", "options");
        }
        internal static async Task Handle(IOwinContext context, JwtTokenIssuerOptions options)
        {
            if (!RequestValidator.HasValidHeaders(context.Request))
            {
                context.Response.StatusCode = 400; // bad request
                return;
            }

            // get request payload (a username/password object)
            var requestPayload = await RequestReader.ReadFrom(context.Request);
            if (requestPayload == null)
            {
                context.Response.StatusCode = 400; // bad request
                return;
            }

            // authenticate
            var claims = Authenticate(options, requestPayload).ToList();
            if (!claims.Any())
            {
                // no claims means not authenticated, return 400
                context.Response.StatusCode = 400; //todo: which status code to return?
                return;
            }

            // create JWT token
            var token = CreateToken(claims, options);

            // create response
            var responsePayload = new ResponsePayload
            {
                Token = token
            };

            await ResponseWriter.WriteTo(context.Response, responsePayload);
        }