Example #1
0
        public string FindErrors(HttpContext context, ArgonautOptions options)
        {
            if (!context.Request.Method.Equals("POST"))
            {
                return("The request method must be POST.");
            }

            if (context.Request.Form == null)
            {
                return("The request content type must be application/x-www-form-urlencoded.");
            }

            if (!context.Request.HasFormContentType)
            {
                return("The request content type must be application/x-www-form-urlencoded.");
            }

            if (!context.Request.Form.ContainsKey("username"))
            {
                return("A username form field is required.");
            }

            if (!context.Request.Form.ContainsKey("password"))
            {
                return("A password form field is required.");
            }

            if (!context.Request.Form.ContainsKey("audience"))
            {
                return("An audience form field is required.");
            }

            return("");
        }
Example #2
0
        public async Task Execute(RequestDelegate next, HttpContext context, ArgonautOptions options)
        {
            var username   = context.Request.Form["username"];
            var password   = context.Request.Form["password"];
            var audienceId = context.Request.Form["audience"];

            var userValidation = options.ValidateUser.Invoke(username, password, audienceId); //Passback ArgonautUser, which should include audience.

            if (!userValidation.Validated)
            {
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;

                var msg = "";
                if (!string.IsNullOrEmpty(userValidation.ValidationFailureUserMessage))
                {
                    msg = userValidation.ValidationFailureUserMessage;
                }
                else
                {
                    msg = "Invalid username, password, or audience.";
                }

                await context.Response.WriteAsync(msg);

                return;
            }

            _jwtBuilder = JWTBuilder.New(userValidation.Audience);
            foreach (var c in userValidation.Claims)
            {
                _jwtBuilder.AddClaim(c);
            }

            await GenerateAccessToken(context, username, options);
        }
Example #3
0
        public PreflightPolicy(RequestDelegate next, IOptions <ArgonautOptions> options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(ArgonautOptions));
            }

            _next    = next;
            _options = options.Value;
        }
Example #4
0
        public FindRequestType(RequestDelegate next, IOptions <ArgonautOptions> options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(ArgonautOptions));
            }

            _options = options.Value;
            _next    = next;
        }
Example #5
0
        public string FindErrors(HttpContext context, ArgonautOptions options)
        {
            if (context.Request.Headers.ContainsKey("authorization") &&
                !context.Request.Headers["authorization"].ToString().Contains("Bearer "))
            {
                return("The authorization field needs to be formatted as Bearer [access_token].");
            }

            return("");
        }
        public string FindErrors(HttpContext context, ArgonautOptions options)
        {
            //Check to see if the user is attemping to request an access token by checking if the 'grant_type' parameter exists, even though the request type could not be found.
            if (!context.Request.HasFormContentType)
            {
                return("");
            }

            if (context.Request.Form.ContainsKey("grant_type"))
            {
                return("The request is not properly formatted.");
            }
            //End check

            return("");
        }
        public void Validate(HttpContext context, ArgonautOptions options)
        {
            var origin     = context.Request.Headers["Origin"].ToString().ToLower();
            var audienceId = context.Request.Form["audience"].ToString().ToLower();
            var audFound   = options.Audiences.Where(l => l.Id.ToLower() == audienceId).FirstOrDefault();

            if (audFound == null)
            {
                return;
            }

            var allowedOrigins = audFound.AllowedOrigins.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToArray();

            if (allowedOrigins.Contains("*") || allowedOrigins.Contains(origin))
            {
                context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { context.Request.Headers["Origin"].ToString() });
            }
        }
        public void Validate(HttpContext context, ArgonautOptions options)
        {
            var authHeader   = context.Request.Headers.Where(l => l.Key.ToLower() == "authorization").FirstOrDefault();
            var accessToken  = authHeader.Value.ToString().Replace("Bearer ", "");
            var audRequested = GetAudienceIdFromAccessToken(accessToken).ToLower();

            var audFound = options.Audiences.Where(l => l.Id.ToLower() == audRequested).FirstOrDefault();

            if (audFound == null)
            {
                return; //OR Return 404 - Audience not found?? Decided against this on the off chance it could be used to fish for allowed audiences.
            }
            var origin = context.Request.Headers["Origin"].ToString().ToLower();

            var allowedOrigins = audFound.AllowedOrigins.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToArray();

            if (allowedOrigins.Contains("*") || allowedOrigins.Contains(origin))
            {
                context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { context.Request.Headers["Origin"].ToString() });
            }
        }
Example #9
0
        private async Task GenerateAccessToken(HttpContext context, string subject, ArgonautOptions options) //,User user
        {
            _jwtBuilder.Subject         = subject;
            _jwtBuilder.Expiration      = TimeSpan.FromMinutes(options.AccessTokenLifetimeMinutes);
            _jwtBuilder.VisualiseClaims = options.VisualiseClaims;
            _jwtBuilder.Build();

            var response = _jwtBuilder.GetWebResponse();
            var rt       = _jwtBuilder.GetRefreshToken();

            rt.EncryptTicket(_encryptor);

            //Generate event for client to save refresh token to persistence
            options.RefreshTokenGenerated(
                new Internal.Model.RefreshToken(rt.Id, rt.Subject, rt.AudienceId, rt.IssuedUtc, rt.ExpiresUtc, rt.ProtectedTicket)
                );

            context.Response.ContentType = "application/json";
            await context.Response.WriteAsync(JsonConvert.SerializeObject(response, new JsonSerializerSettings {
                Formatting = Formatting.Indented
            }));
        }
        public string FindErrors(HttpContext context, ArgonautOptions options)
        {
            if (!context.Request.Method.Equals("POST"))
            {
                return("The request method must be POST.");
            }

            if (context.Request.Form == null)
            {
                return("The request content type must be application/x-www-form-urlencoded.");
            }

            if (!context.Request.HasFormContentType)
            {
                return("The request content type must be application/x-www-form-urlencoded.");
            }

            if (!context.Request.Form.ContainsKey("refresh_token"))
            {
                return("A refresh_token form field is required.");
            }

            return("");
        }
 public Task Execute(RequestDelegate next, HttpContext context, ArgonautOptions options)
 => next(context);
Example #12
0
        public async Task Execute(RequestDelegate next, HttpContext context, ArgonautOptions options)
        {
            var rtFromRequest        = context.Request.Form["refresh_token"];
            var hashedRefreshTokenId = Argonaut.Internal.Hashing.GetHash(rtFromRequest);

            var persistenceResponse = options.RefreshAccessToken(hashedRefreshTokenId); //Client returns refresh token model with encrpted ticket.

            if (persistenceResponse == null)
            {
                await RespondRefreshTokenInvalid(context);

                return;
            }

            if (persistenceResponse.RefreshToken == null)
            {
                await RespondRefreshTokenInvalid(context);

                return;
            }

            if (persistenceResponse.Audience == null)
            {
                await RespondRefreshTokenInvalid(context);

                return;
            }

            //Map to domain refresh token
            Domain.RefreshToken rt = Domain.RefreshToken.New(
                persistenceResponse.RefreshToken.Id,
                persistenceResponse.RefreshToken.Subject,
                persistenceResponse.RefreshToken.AudienceId,
                persistenceResponse.RefreshToken.ProtectedTicket,
                persistenceResponse.RefreshToken.IssuedUtc,
                persistenceResponse.RefreshToken.ExpiresUtc
                );

            var nowUtc = DateTime.UtcNow; //TODO: Could do with moving to interface

            if (nowUtc > rt.ExpiresUtc)
            {
                await RespondRefreshTokenInvalid(context);

                return;
            }

            try {
                rt.DecryptTicket(_encryptor, rtFromRequest.ToString());
            } catch {
                context.Response.StatusCode = 401;
                await context.Response.WriteAsync("Persisted refresh token failed decryption - Log in using username and password.");

                return;
            }

            if (rt.ProtectedTicket == null)
            {
                await RespondRefreshTokenInvalid(context);

                return;
            }

            var vp      = new JWTValidationParametersGenerator(persistenceResponse.Audience).SecretOnly();
            var handler = new JwtSecurityTokenHandler();

            Microsoft.IdentityModel.Tokens.SecurityToken validatedToken = null;
            try {
                handler.ValidateToken(rt.ProtectedTicket, vp, out validatedToken);
            } catch {
                await RespondRefreshTokenInvalid(context);

                return;
            }

            if (validatedToken == null)
            {
                await RespondRefreshTokenInvalid(context);

                return;
            }

            var jwt         = validatedToken as System.IdentityModel.Tokens.Jwt.JwtSecurityToken;
            var sub         = jwt.Claims.Where(l => l.Type == "sub").FirstOrDefault().Value;
            var claimsToUse = jwt.Claims.ExcludeDefaultAccessTokenClaims();

            _jwtBuilder = JWTBuilder.New(persistenceResponse.Audience);
            _jwtBuilder.AddClaims(claimsToUse);

            await GenerateAccessToken(context, sub, options);
        }
 public void Validate(HttpContext context, ArgonautOptions options) /*Do nothing*/ }
 /// <summary>
 /// Always allow origin for refresh token requests as the associated audience can only be found by a trip to the database.
 /// Origin still needed for access token and any data.
 /// </summary>
 public void Validate(HttpContext context, ArgonautOptions options)
 => context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { context.Request.Headers["Origin"].ToString() });