コード例 #1
0
ファイル: SessionManager.cs プロジェクト: bluesektor/Common
        /// <summary>
        /// TODO unit test this.
        /// </summary>
        /// <param name="jwt"></param>
        /// <param name="secretKey"></param>
        /// <returns></returns>
        public bool IsValidJwt(string jwt, string secretKey)
        {
            if (string.IsNullOrWhiteSpace(jwt))
            {
                return(false);
            }

            try
            {
                string jsonPayload = "";
                jsonPayload = JWT.JsonWebToken.Decode(jwt, secretKey, false); // JWT.SignatureVerificationException
                JwtClaims claims = JsonConvert.DeserializeObject <JwtClaims>(jsonPayload);

                TimeSpan ts = claims.expires - DateTime.UtcNow;

                if (ts.TotalSeconds <= 0)
                {
                    return(false);
                }

                if (claims.iss != _app.GetSetting("SiteDomain")?.Value)
                {
                    return(false);
                }
            }
            catch (Exception ex)
            {
                Debug.Assert(false, ex.Message);
                return(false);
            }
            return(true);
        }
コード例 #2
0
        public void TestReqeustParamsDeserialization()
        {
            var json = @"{""aud"":""svc:f8329e0e-dd7a-11e7-98b4-469158467b1a"",""iss"":""lka"",""cty"":""application/json"",""nbf"":1513716853,""jti"":""c70da9cf498049ff9fd465c87d233d36"",""exp"":1513716858,""iat"":1513716853,""request"":{""path"":""path"",""meth"":""POST"",""hash"":""7214a12199440f792227fc9310193a2267f364ee59bfe0495ea690c31033325b"",""func"":""S256""},""sub"":""svc:f8329e0e-dd7a-11e7-98b4-469158467b1a""}";

            var claims = JwtClaims.FromJson(json);

            Assert.AreEqual(claims.Audience, "svc:f8329e0e-dd7a-11e7-98b4-469158467b1a");
            Assert.AreEqual(claims.Issuer, "lka");
            Assert.AreEqual(claims.Subject, "svc:f8329e0e-dd7a-11e7-98b4-469158467b1a");

            Assert.IsNotNull(claims.NotBefore);
            Assert.IsNotNull(claims.IssuedAt);
            Assert.IsNotNull(claims.ExpiresAt);

            Assert.AreEqual(claims.NotBefore, DateTime.Parse("12/19/2017 8:54:13 PM"));
            Assert.AreEqual(claims.IssuedAt, DateTime.Parse("12/19/2017 8:54:13 PM"));
            Assert.AreEqual(claims.ExpiresAt, DateTime.Parse("12/19/2017 8:54:18 PM"));

            Assert.AreEqual(claims.TokenId, "c70da9cf498049ff9fd465c87d233d36");

            Assert.IsNotNull(claims.Request);

            Assert.AreEqual(claims.Request.Method, "POST");
            Assert.AreEqual(claims.Request.Path, "path");
            Assert.AreEqual(claims.Request.ContentHash, "7214a12199440f792227fc9310193a2267f364ee59bfe0495ea690c31033325b");
            Assert.AreEqual(claims.Request.ContentHashAlgorithm, "S256");
        }
コード例 #3
0
        public void TestSampleDeserializtion()
        {
            var json = "{\"aud\":\"svc:f8329e0e-dd7a-11e7-98b4-469158467b1a\",\"iss\":\"lka\",\"cty\":\"application/json\",\"nbf\":1513716853,\"jti\":\"c70da9cf498049ff9fd465c87d233d36\",\"exp\":1513716858,\"iat\":1513716853,\"response\":{\"status\":400,\"hash\":\"7214a12199440f792227fc9310193a2267f364ee59bfe0495ea690c31033325b\",\"func\":\"S256\"},\"sub\":\"svc:f8329e0e-dd7a-11e7-98b4-469158467b1a\"}";

            var claims = JwtClaims.FromJson(json);

            Assert.AreEqual(claims.Audience, "svc:f8329e0e-dd7a-11e7-98b4-469158467b1a");
            Assert.AreEqual(claims.Issuer, "lka");
            Assert.AreEqual(claims.Subject, "svc:f8329e0e-dd7a-11e7-98b4-469158467b1a");

            Assert.IsNotNull(claims.NotBefore);
            Assert.IsNotNull(claims.IssuedAt);
            Assert.IsNotNull(claims.ExpiresAt);

            Assert.AreEqual(claims.NotBefore, DateTime.Parse("12/19/2017 8:54:13 PM"));
            Assert.AreEqual(claims.IssuedAt, DateTime.Parse("12/19/2017 8:54:13 PM"));
            Assert.AreEqual(claims.ExpiresAt, DateTime.Parse("12/19/2017 8:54:18 PM"));

            Assert.AreEqual(claims.TokenId, "c70da9cf498049ff9fd465c87d233d36");

            Assert.IsNotNull(claims.Response);

            Assert.AreEqual(claims.Response.StatusCode, 400);
            Assert.AreEqual(claims.Response.ContentHash, "7214a12199440f792227fc9310193a2267f364ee59bfe0495ea690c31033325b");
            Assert.AreEqual(claims.Response.ContentHashAlgorithm, "S256");
        }
コード例 #4
0
        /// <summary>
        /// Get claims of user.
        /// </summary>
        /// <returns>User claims.</returns>
        protected JwtClaims GetUserClaims()
        {
            var claims    = this.User.Claims;
            var jwtClaims = new JwtClaims
            {
                FromId     = claims.Where(claim => claim.Type == "userObjectIdentifier").Select(claim => claim.Value).First(),
                ServiceUrl = claims.Where(claim => claim.Type == "serviceURL").Select(claim => claim.Value).First(),
            };

            return(jwtClaims);
        }
コード例 #5
0
        /// <summary>
        /// Get claims of user.
        /// </summary>
        /// <returns>User claims.</returns>
        private JwtClaims GetUserClaims()
        {
            var claims    = this.httpContextAccessor.HttpContext.User.Claims;
            var jwtClaims = new JwtClaims
            {
                FromId     = claims?.Where(claim => claim.Type == "fromId").Select(claim => claim.Value).FirstOrDefault(),
                ServiceUrl = claims?.Where(claim => claim.Type == "serviceURL").Select(claim => claim.Value).FirstOrDefault(),
            };

            return(jwtClaims);
        }
コード例 #6
0
        /// <summary>
        /// Get claims of user.
        /// </summary>
        /// <returns>User claims.</returns>
        protected JwtClaims GetUserClaims()
        {
            var claims    = this.User.Claims;
            var jwtClaims = new JwtClaims
            {
                FromId = claims.Where(claim => claim.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier").Select(claim => claim.Value).First(),
                Upn    = claims.Where(claim => claim.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn").Select(claim => claim.Value).First(),
            };

            return(jwtClaims);
        }
        /// <summary>
        /// Get claims of user.
        /// </summary>
        /// <returns>User claims.</returns>
        protected JwtClaims GetUserClaims()
        {
            var claims    = this.User.Claims;
            var jwtClaims = new JwtClaims
            {
                FromId     = claims.Where(claim => claim.Type == "fromId").Select(claim => claim.Value).First(),
                ServiceUrl = claims.Where(claim => claim.Type == "applicationBasePath").Select(claim => claim.Value).First(),
            };

            return(jwtClaims);
        }
コード例 #8
0
        public User GetUserFromToken(string authToken)
        {
            JwtClaims jwtClaims = ParseJwtToken(authToken);

            return(new User()
            {
                Id = jwtClaims.Id,
                Email = jwtClaims.Email,
                Role = jwtClaims.Role
            });
        }
コード例 #9
0
        public AuthenticationStatus Authenticate(string authToken, out User user)
        {
            var result = AuthenticationStatus.Success;

            user = null;

            if (string.IsNullOrWhiteSpace(authToken))
            {
                throw new AuthenticationException("Token is not provided");
            }

            try
            {
                IJsonSerializer   serializer = new JsonNetSerializer();
                IDateTimeProvider provider   = new UtcDateTimeProvider();
                IJwtValidator     validator  = new JwtValidator(serializer, provider);
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtDecoder       decoder    = new JwtDecoder(serializer, validator, urlEncoder);

                JwtClaims jwtClaims = decoder.DecodeToObject <JwtClaims>(authToken);

                user = new User()
                {
                    Id    = jwtClaims.Id,
                    Role  = jwtClaims.Role,
                    Email = jwtClaims.Email
                };

                if (_jwtSettings.IsEnabled)
                {
                    decoder.Decode(authToken, _jwtSettings.SignatureSecret, verify: true);
                }
                else
                {
                    result = AuthenticationStatus.ClientDisabled;
                }
            }
            catch (TokenExpiredException)
            {
                result = AuthenticationStatus.TokenExpired;
            }
            catch (SignatureVerificationException)
            {
                result = AuthenticationStatus.TokenVerificationFailed;
            }

            return(result);
        }
コード例 #10
0
        public string GetProfileUUID(string authToken)
        {
            if (string.IsNullOrWhiteSpace(authToken))
            {
                return(authToken);
            }

            _appManager = new AppManager(Globals.DBConnectionKey, "web", authToken);
            string appSecret = _appManager.GetSetting("AppKey")?.Value;

            JwtClaims requestorClaims = null;

            try
            {
                var payload = JWT.JsonWebToken.Decode(authToken, appSecret, false);
                requestorClaims = JsonConvert.DeserializeObject <JwtClaims>(payload);

                TimeSpan ts = requestorClaims.Expires - DateTime.UtcNow;

                if (ts.TotalSeconds <= 0)
                {
                    return(string.Empty);
                }

                string[] tokens = requestorClaims.aud.Replace(SystemFlag.Default.Account, "systemdefaultaccount").Split('.');
                if (tokens.Length == 0)
                {
                    return(string.Empty);
                }

                //string userUUID = tokens[0];
                //string accountUUID = tokens[1];
                //if ("systemdefaultaccount" == accountUUID) accountUUID = SystemFlag.Default.Account;

                string profileUUID = tokens[2];
                return(profileUUID);
            }
            catch (Exception ex)
            {
                return(string.Empty);
            }
        }
コード例 #11
0
        private void ValidatePrivateClaims(HttpResponse response, JwtClaims jwt)
        {
            // verify response information matches the JWT
            if (response.Headers[HttpResponseHeader.Location] != jwt.Response.LocationHeader)
            {
                throw new JwtError("Location header of response content does not match JWT response location");
            }

            string[] expectedCacheControlHeaders = new string[] { };

            if (jwt.Response.CacheControlHeader != null)
            {
                expectedCacheControlHeaders = jwt.Response.CacheControlHeader.Split(',').Select(x => x.Trim()).ToArray();
                Array.Sort(expectedCacheControlHeaders);
            }

            var actualCacheControlHeaders = response.Headers.GetValues("cache-control") ?? new string[] { };

            if (actualCacheControlHeaders != null)
            {
                Array.Sort(actualCacheControlHeaders);
            }

            if (!expectedCacheControlHeaders.SequenceEqual(actualCacheControlHeaders))
            {
                throw new JwtError("Cache-Control header of response content does not match JWT response cache");
            }

            if ((int)response.StatusCode != jwt.Response.StatusCode)
            {
                throw new JwtError("Status code of response content does not match JWT response status code");
            }

            // if the response has body content, we need to validate the hash
            if (!string.IsNullOrWhiteSpace(response.ResponseBody))
            {
                ValidateHash(response.ResponseBody, jwt.Response.ContentHashAlgorithm, jwt.Response.ContentHash);
            }
        }
コード例 #12
0
ファイル: SessionManager.cs プロジェクト: bluesektor/Common
        public string CreateJwt(string secretKey, User user, string issuer, DateTime expires)
        {
            if (user == null)
            {
                return(string.Empty);
            }

            string profileUUID = string.Empty;

            using (var context = new GreenWerxDbContext(this._connectionKey))
            {
                var profile = context.GetAll <Profile>()?.FirstOrDefault(sw => sw?.AccountUUID == user.AccountUUID && sw?.UserUUID == user.UUID);
                profileUUID = profile?.UUID;
            }

            var payload = new JwtClaims();

            if (string.IsNullOrWhiteSpace(profileUUID))
            {
                payload.aud = user.UUID + "." + user.AccountUUID;
            }
            else
            {
                payload.aud = user.UUID + "." + user.AccountUUID + "." + profileUUID;
            }

            payload.iss     = issuer;
            payload.jti     = Guid.NewGuid().ToString();
            payload.exp     = expires.ConvertToUnixTimestamp().ToString();
            payload.expires = expires;
            RoleManager roleManager  = new RoleManager(this._connectionKey);
            List <Role> userRoles    = roleManager.GetRolesForUser(user.UUID, user.AccountUUID);
            List <Role> profileRoles = roleManager.GetRolesForUser(profileUUID, user.AccountUUID);

            userRoles.AddRange(profileRoles);
            if (userRoles.Count > 0)
            {
                payload.roleWeights = userRoles.Select(s => s.RoleWeight.ToString()).Aggregate((current, next) => current + "," + next);
                payload.roleNames   = userRoles.Select(s => s.Name?.ToUpper()).Aggregate((current, next) => current + "," + next);
            }

            //NOTE: This uses bouncy castle portable, specifically version 1.8.1. Runtime error occures with other versions.
            string token = JWT.JsonWebToken.Encode(payload, secretKey, JWT.JwtHashAlgorithm.HS256);

            return(token);

            #region Unsecured jwt example

            ////var hmac = new HMACSHA256();
            ////var header = "{ \"alg\": \"HS256\",  \"typ\": \"JWT\"  }";
            //////Some PayLoad that contain information about the  customer
            ////var payload = "{ \"userUUID\": \"" + userUUID + "\",  \"scope\": \"http://test.com\"  }";
            ////var secToken = hmac.ComputeHash(Encoding.UTF8.GetBytes(header + payload));
            ////// Token to String so you can use it in your client

            ////Debug.Assert(false, "TODO NEED TO REMOVE THE END PADDING = OR == ");
            ////var tokenString = Convert.ToBase64String(Encoding.UTF8.GetBytes(header)) + "." +
            ////                    Convert.ToBase64String(Encoding.UTF8.GetBytes(payload)) + "." +
            ////                    Convert.ToBase64String(secToken);

            ////return tokenString;

            #endregion Unsecured jwt example
        }
コード例 #13
0
        private void LogRequest()
        {
            try
            {
                RequestLog req = new RequestLog();
                req.Timer            = new Stopwatch();
                req.DateCreated      = DateTime.UtcNow;
                req.RequestURL       = HttpContext.Current.Request.Url.AbsoluteUri;
                req.AbsolutePath     = HttpContext.Current.Request.Url.AbsolutePath;
                req.Referrer         = HttpContext.Current.Request.UrlReferrer.AbsoluteUri; // ?.DnsSafeHost;
                req.RequestComplete  = false;
                req.IPAddress        = new NetworkHelper().GetClientIpAddress(HttpContext.Current.Request);
                req.Method           = HttpContext.Current.Request.HttpMethod;
                req.RequestLocalPath = HttpContext.Current.Request.Path;
                req.RequestURL       = HttpContext.Current.Request.Url.ToString();
                var auth = HttpContext.Current.Request.Headers.GetValues("Authorization")?.ToString().Replace("Bearer ", "");
                auth = auth?.Trim();

                //IEnumerable<KeyValuePair<string, string>> kvp = actionContext.Request.GetQueryNameValuePairs();
                //KeyValuePair<string, string> apiKVP = kvp.FirstOrDefault(w => w.Key.EqualsIgnoreCase("KEY"));

                //if (Globals.AddRequestPermissions)
                //{
                //    //if we need to pass the user object in, move this down below after it gets the current user.
                //    RoleManager roleManager = new RoleManager(Globals.DBConnectionKey, null);
                //    string name = roleManager.NameFromPath(absolutePath);
                //    roleManager.CreatePermission(name, method, absolutePath, "api");
                //}

                if (!string.IsNullOrWhiteSpace(auth))
                {
                    JwtClaims requestorClaims = null;

                    try
                    {
                        _appManager = new AppManager(Globals.DBConnectionKey, "web", auth);
                        string appSecret = _appManager.GetSetting("AppKey")?.Value;

                        var payload = JWT.JsonWebToken.Decode(auth, appSecret, false);
                        requestorClaims = JsonConvert.DeserializeObject <JwtClaims>(payload);

                        string[] tokens = requestorClaims.aud.Replace(SystemFlag.Default.Account, "systemdefaultaccount").Split('.');
                        if (tokens.Length >= 2)
                        {
                            req.UserUUID    = tokens[0];
                            req.AccountUUID = tokens[1];
                        }
                    }
                    catch { }
                }
                HttpContext.Current.Items.Add("RequestIdentity", req.UUID); // so we can find the request in the array in the function

                if (requests.Count < 200)
                {
                    requests.Add(req);
                }
                else
                {
                    for (int i = 0; i < requests.Count; i++)
                    {
                        if (requests[i].RequestComplete)
                        {
                            requests.Remove(requests[i]);
                            continue;
                        }

                        TimeSpan elaps = DateTime.UtcNow - requests[i].DateCreated;

                        if (elaps.TotalMinutes > 10)
                        {
                            requests.Remove(requests[i]);
                        }
                    }
                }

                req.Timer.Start();
            }
            catch { }
        }
コード例 #14
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers()
            .AddNewtonsoftJson(options =>
                               options.SerializerSettings.ReferenceLoopHandling =
                                   Newtonsoft.Json.ReferenceLoopHandling.Ignore
                               );



            services.AddAuthentication(o =>
            {
                o.DefaultScheme          = JwtBearerDefaults.AuthenticationScheme;
                o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer();         // use separate options below to allow dependency injection with rsa key to work.

            // Dependency injection for RSA key -> the instance of the rsa key needs to be a singleton
            services.AddOptions <JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme)
            .Configure <RsaSecurityKey>((options, skey) =>
            {
                options.IncludeErrorDetails = true;

                // fix to map permissions as roles in .net mvc via event handling:
                options.Events = new JwtBearerEvents
                {
                    OnTokenValidated = async ctx =>
                    {
                        await Task.Run(() =>
                        {
                            var newClaims = new List <Claim>();

                            foreach (Claim claim in ctx.Principal.Claims)
                            {
                                if (claim.Type == "user_claims")     // we use this attribute chosen by the login service that contains the permissions to be converted to .net mvc identity roles.
                                {
                                    JwtClaims claims = JsonSerializer.Deserialize <JwtClaims>(claim.Value);

                                    foreach (String permission in claims.permissions)
                                    {
                                        // add each permission as .net identity role for use in MVC controllers role filtering
                                        newClaims.Add(new Claim(ClaimTypes.Role, permission));
                                    }
                                }
                            }
                            // build new Claims Identity
                            var appIdentity = new ClaimsIdentity(newClaims);

                            // add the claims to the principal identity
                            ctx.Principal.AddIdentity(appIdentity);
                        });
                    }
                };

                options.TokenValidationParameters.ValidateIssuer           = false;
                options.TokenValidationParameters.ValidateAudience         = false;
                options.TokenValidationParameters.ValidateIssuerSigningKey = true;
                options.TokenValidationParameters.IssuerSigningKey         = skey;
                options.TokenValidationParameters.ValidateLifetime         = false;
                options.TokenValidationParameters.RequireExpirationTime    = true;
                options.TokenValidationParameters.RequireSignedTokens      = true;
            });

            // needed in order for the rsa validation key to remain in memory (for some reason it does not work otherwise).
            services.AddSingleton <RsaSecurityKey>(provider => {
                RSA rsa = RSA.Create();
                rsa.ImportSubjectPublicKeyInfo(
                    source: Convert.FromBase64String(@"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvKZzT8MhSEHRRecmD1kM
oW8unUYufupt/4AV5Yd6YSR84uHjMuArp/lQx/ROrCvt5xSBB547L5oPeJECeS4h
p7Djlsd3VyIvs+yY+e9FM72MLnaoydQLCHKz8RQF2+mr8SeM/4va6vGSTTW3F5Ay
9LOYDsQa18yYJ+a7tc2PQJQGZYQvQ1YWerlScrcZQ1ChB5u+mALdg1VoKpW2n+bP
6ucjGidjqUbLMPKOHQRQBuoMNTXk2fzKQmhhML9lUKw5+2RZ2jtJKBVBNprV1EDP
yBTXutHUCV6D4esOqc35e1jZo6kQGGaWQ0rIpupv/qyXLHTz6Gi/mnvZuMQJIJZ+
iwIDAQAB"),
                    bytesRead: out int _);

                return(new RsaSecurityKey(rsa));
            });


            services.AddSingleton <ProductsFacade>();
            services.AddSingleton <TagsFacade>();
            services.AddSingleton <StocksFacade>();
            services.AddSingleton <IRepositoryFactory, RepositoryFactory>();
            services.AddSingleton <IEventBusPublisher, RabbitMessenger>();



            services.AddApiVersioning(x =>
            {
                x.DefaultApiVersion = new ApiVersion(0, 1);
                x.AssumeDefaultVersionWhenUnspecified = true;
                x.ReportApiVersions = true;
            });
            services.AddVersionedApiExplorer(options =>
            {
                options.GroupNameFormat           = "VVVV";
                options.SubstituteApiVersionInUrl = true;
                options.SubstitutionFormat        = "VVVV";
            });
            services.AddSwaggerDocument(config =>
            {
                config.DocumentName = "0.* (not for production)";
                //config.ApiGroupNames = new[] { "0.1" };

                config.SchemaNameGenerator = new SchemaNameGenerator();

                // Authentication
                config.OperationProcessors.Add(new OperationSecurityScopeProcessor("JWT token"));
                config.AddSecurity("JWT token", Enumerable.Empty <string>(),
                                   new OpenApiSecurityScheme()
                {
                    Type        = OpenApiSecuritySchemeType.ApiKey,
                    Name        = "Authorization",
                    In          = OpenApiSecurityApiKeyLocation.Header,
                    Description = "Copy this into the value field: \nBearer {my long token}"
                }
                                   );
                config.PostProcess = document =>
                {
                    document.Info.Version     = "0.1";
                    document.Info.Title       = "Inventory Microservice API";
                    document.Info.Description = "API Documentation";
                };
            });
        }