Esempio n. 1
0
        private ClaimsPrincipal GetTokenClaimsPrincipal(string tokenString)
        {
            var tokenHandler = new JwtSecurityTokenHandler();

            // Set the validation params
            TokenValidationParameters validationParameters = new TokenValidationParameters()
            {
                ValidIssuer      = Config.Issuer,
                ValidAudience    = Config.Audience,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Config.SecretKey))
            };

            // Check the token is in a valid format
            if (!tokenHandler.CanReadToken(tokenString))
            {
                return(null);
            }

            // Check the token itself is valid
            ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(tokenString, validationParameters, out SecurityToken validatedToken);

            return(claimsPrincipal);
        }
Esempio n. 2
0
        public static string GetUserID(this HttpContext httpContext)
        {
            string authHeader = httpContext.Request.Headers["Authorization"];
            if (!string.IsNullOrEmpty(authHeader))
            {
                string[] authHeaderParts = authHeader.Split(' ');
                if (authHeaderParts?.Length == 2 && authHeaderParts[0].Equals("Bearer", StringComparison.InvariantCultureIgnoreCase))
                {
                    var jwtHandler = new JwtSecurityTokenHandler();
                    if (jwtHandler.CanReadToken(authHeaderParts[1]))
                    {
                        var jwtToken = jwtHandler.ReadJwtToken(authHeaderParts[1]);
                        var userNameIdentifier = jwtToken.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
                        if (userNameIdentifier != null)
                        {
                            return userNameIdentifier.Value;
                        }
                    }
                }
            }

            return null;
        }
Esempio n. 3
0
        public async Task TestLoginReturnJWTToken()
        {
            var client      = _testServer.CreateClient();
            var userManager = _testServer.Host.Services.GetService(typeof(UserManager <ApplicationUser>)) as UserManager <ApplicationUser>;
            var data        = new Dictionary <string, string>();

            var user = new ApplicationUser {
                Email    = "*****@*****.**",
                UserName = "******"
            };

            data.Add("email", user.Email);
            data.Add("password", "Aa@123456");
            data.Add("username", user.UserName);
            var formData = new FormUrlEncodedContent(data);


            var createdUser = await userManager.CreateAsync(user, data["password"]);

            if (!createdUser.Succeeded)
            {
                throw new Exception("error on create user");
            }
            // var responseRegister = await client.PostAsync("/register", formData);
            // responseRegister.EnsureSuccessStatusCode();

            var responseLogin = await client.PostAsync("/login", formData);

            responseLogin.EnsureSuccessStatusCode();

            var validator = new JwtSecurityTokenHandler();
            var resText   = await responseLogin.Content.ReadAsStringAsync();

            var read = validator.CanReadToken(resText);

            Assert.True(read);
        }
        private void btnDecodeJwt_Click(object sender, EventArgs e)
        {
            var jwtHandler = new JwtSecurityTokenHandler();
            var jwtInput   = txtJwtIn.Text;

            //Check if readable token (string is in a JWT format)
            var readableToken = jwtHandler.CanReadToken(jwtInput);

            if (readableToken != true)
            {
                txtJwtOut.Text = "The token doesn't seem to be in a proper JWT format.";
            }
            if (readableToken == true)
            {
                var token = jwtHandler.ReadJwtToken(jwtInput);

                //Extract the headers of the JWT
                var headers   = token.Header;
                var jwtHeader = "{";
                foreach (var h in headers)
                {
                    jwtHeader += '"' + h.Key + "\":\"" + h.Value + "\",";
                }
                jwtHeader     += "}";
                txtJwtOut.Text = "Header:\r\n" + JToken.Parse(jwtHeader).ToString(Formatting.Indented);

                //Extract the payload of the JWT
                var claims     = token.Claims;
                var jwtPayload = "{";
                foreach (Claim c in claims)
                {
                    jwtPayload += '"' + c.Type + "\":\"" + c.Value + "\",";
                }
                jwtPayload     += "}";
                txtJwtOut.Text += "\r\nPayload:\r\n" + JToken.Parse(jwtPayload).ToString(Formatting.Indented);
            }
        }
        public async Task Invoke(HttpContext context, CurrentUser currentUser, IOptions <ConfigSettingsBase> configSettingsBase)
        {
            var token = context.Request.Headers["Authorization"];

            if (!token.IsNullOrEmpaty())
            {
                var tokenClear = token.ToString().Replace("Bearer ", "");
                var jwt        = new JwtSecurityTokenHandler();
                var canRead    = jwt.CanReadToken(tokenClear);
                if (canRead)
                {
                    //var claims = await GetClaimsFromServer(configSettingsBase, tokenClear);
                    var claims = GetClaimsFromUserPrincipal(context);
                    //var claims = GetClaimsFromReadToken(tokenClear, jwt);
                    this.ConfigClaims(currentUser, tokenClear, claims.ConvertToDictionary());
                }
            }
            else
            {
                var claims = GetClaimsFromUserPrincipal(context);
                ConfigClaims(currentUser, string.Empty, claims.ConvertToDictionary());
            }
            await this._next.Invoke(context);
        }
Esempio n. 6
0
        public static TokenDetails ReadJwtToken(string jwtToken) //, out string userClaims, out string sessionId, out string userName, out DateTime validTo)
        {
            var jwtHandler = new JwtSecurityTokenHandler();

            if (jwtHandler.CanReadToken(jwtToken))
            {
                var tokenValue = jwtHandler.ReadJwtToken(jwtToken);

                var claims = tokenValue.Claims;

                var result = new TokenDetails
                {
                    ClaimsJson = claims.First(c => c.Type == "claims").Value,

                    SessionId = claims.First(c => c.Type == "sessionid").Value,

                    ValidTo = tokenValue.ValidTo,

                    Username = claims.First(c => c.Type == JwtRegisteredClaimNames.NameId).Value
                };
                return(result);
            }
            return(null);
        }
Esempio n. 7
0
        /// <inheritdoc/>
        public async Task <bool> Validate(string token)
        {
            JwtSecurityTokenHandler validator = new JwtSecurityTokenHandler();

            if (!validator.CanReadToken(token))
            {
                return(false);
            }

            JwtSecurityToken          jwt = validator.ReadJwtToken(token);
            TokenValidationParameters validationParameters = await GetTokenValidationParameters(jwt.Issuer);

            try
            {
                validator.ValidateToken(token, validationParameters, out _);
                return(true);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to validate token from issuer {Issuer}.", jwt.Issuer);
            }

            return(false);
        }
Esempio n. 8
0
        private long GetLoggedInUserIdMockUp()
        {
            string jwtInput = Context.GetHttpContext().Request.Query["token"];

            var jwtHandler = new JwtSecurityTokenHandler();

            if (!jwtHandler.CanReadToken(jwtInput))
            {
                throw new Exception("The token doesn't seem to be in a proper JWT format.");
            }

            var token = jwtHandler.ReadJwtToken(jwtInput);

            var jwtPayload = JsonConvert.SerializeObject(token.Claims.Select(c => new { c.Type, c.Value }));

            JArray rss        = JArray.Parse(jwtPayload);
            var    firstChild = rss.First;
            var    lastChild  = firstChild.Last;
            var    idString   = lastChild.Last.ToString();

            long.TryParse(idString, out long id);

            return(id);
        }
Esempio n. 9
0
        public AuthenticationTicket Unprotect(string protectedText)
        {
            var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();

            var validationParameters = new TokenValidationParameters
            {
                ValidAudience            = _authConfiguration.JwtAudience,
                ValidIssuer              = _authConfiguration.JwtIssuer,
                IssuerSigningToken       = new BinarySecretSecurityToken(Convert.FromBase64String(_authConfiguration.JwtKey)),
                ValidateAudience         = true,
                ValidateIssuer           = true,
                ValidateIssuerSigningKey = true
            };

            if (!jwtSecurityTokenHandler.CanReadToken(protectedText))
            {
                return(null);
            }
            SecurityToken securityToken;

            var claimsPrincipal = jwtSecurityTokenHandler.ValidateToken(protectedText, validationParameters, out securityToken);

            return(new AuthenticationTicket(new ClaimsIdentity(claimsPrincipal.Identity), new AuthenticationProperties()));
        }
Esempio n. 10
0
        private async Task <Dictionary <string, string> > SetRequestHeader()
        {
            var response = await _engineEnvironment.GetEnvironmentVariables().ConfigureAwait(false);

            if (response.Error.HasValue && response.Error.Value)
            {
                _logger.LogError(response.Message);
                throw new Exception("Can't get environment variables.");
            }
            var clientId         = _engineEnvironment.EngineFlowConfig.ConfiggenClientId;
            var clientSecret     = Helper.GetSecretFromKeyvaultIfNeeded(_engineEnvironment.EngineFlowConfig.ConfiggenClientSecret);
            var clientResourceId = Helper.GetSecretFromKeyvaultIfNeeded(_engineEnvironment.EngineFlowConfig.ConfiggenClientResourceId);
            var tenantId         = _engineEnvironment.EngineFlowConfig.ConfiggenTenantId;

            var authenticationContext = new AuthenticationContext($"https://login.windows.net/{tenantId}");
            var credential            = new ClientCredential(clientId, clientSecret);
            var apiToken = authenticationContext.AcquireTokenAsync(clientResourceId, credential).Result.AccessToken;

            var jwtHandler    = new JwtSecurityTokenHandler();
            var readableToken = jwtHandler.CanReadToken(apiToken);

            Dictionary <string, string> headers = new Dictionary <string, string>();

            if (readableToken == true)
            {
                var token = jwtHandler.ReadJwtToken(apiToken);

                var roleValue = token.Claims.FirstOrDefault(c => c.Type == "roles")?.Value;
                if (!string.IsNullOrEmpty(roleValue))
                {
                    headers.Add(Constants.UserRolesHeader, roleValue);
                }
            }

            return(headers);
        }
Esempio n. 11
0
        private async Task ValidateAsyncTokenAsync(IOwinContext context, string accessToken, string expiresIn)
        {
            var store = new X509Store(StoreLocation.CurrentUser);

            store.Open(OpenFlags.ReadOnly);
            var certCollection   = store.Certificates.Find(X509FindType.FindByThumbprint, ConfigurationManager.AppSettings["CertificateValue"], false);
            var issuerSigningKey = new X509SecurityKey(new X509Certificate2(new X509Certificate(certCollection[0])));

            var validationParameters = new TokenValidationParameters
            {
                ValidateIssuer   = false,
                ValidateAudience = false,
                ValidateLifetime = false,
                IssuerSigningKey = issuerSigningKey
            };

            var validator = new JwtSecurityTokenHandler();

            if (!validator.CanReadToken(accessToken))
            {
                throw new UnauthorizedAccessException("token is not readable");
            }

            var validate = validator.ValidateToken(accessToken, validationParameters, out var validatedToken);

            var claimsIdentity = new ClaimsIdentity(validate.Claims, DefaultAuthenticationTypes.ApplicationCookie);

            AuthenticationManager.SignIn(new AuthenticationProperties()
            {
                AllowRefresh = true,
                IsPersistent = true,
                ExpiresUtc   = DateTimeOffset.UtcNow.AddSeconds(double.Parse(expiresIn))
            }, claimsIdentity);

            await Next.Invoke(context);
        }
Esempio n. 12
0
        public Nullable <Int32> verifyJWT(String token)
        {
            try
            {
                var jwtHandler    = new JwtSecurityTokenHandler();
                var readableToken = jwtHandler.CanReadToken(token);
                if (readableToken == true)
                {
                    var validationParameters = new TokenValidationParameters()
                    {
                        RequireExpirationTime = true,
                        ValidateIssuer        = false,
                        ValidateAudience      = false,
                        IssuerSigningKey      = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key))
                    };

                    SecurityToken securityToken;
                    var           principal = jwtHandler.ValidateToken(token, validationParameters, out securityToken);

                    var tk     = jwtHandler.ReadJwtToken(token);
                    var claims = tk.Claims;
                    foreach (Claim c in principal.Claims)
                    {
                        if (c.Type == "id")
                        {
                            return(Convert.ToInt32(c.Value));
                        }
                    }
                }
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine("M:" + e.StackTrace);
            }
            return(null);
        }
Esempio n. 13
0
        public Task <bool> ValidateTokenAsync(string token)
        {
            var isValid = true;

            var validator = new JwtSecurityTokenHandler();

            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidAudience            = _configuration.GetSection("BearerTokens")["Audience"],
                ValidateAudience         = true,
                ValidIssuer              = _configuration.GetSection("BearerTokens")["Issuer"],
                ValidateIssuer           = true,
                ValidateIssuerSigningKey = true,
                IssuerSigningKey         = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration.GetSection("BearerTokens")["Key"])),
                ValidateLifetime         = true
            };

            if (validator.CanReadToken(token))
            {
                try
                {
                    SecurityToken securityToken;
                    var           principal = validator.ValidateToken(token, tokenValidationParameters, out securityToken);
                }
                catch (Exception)
                {
                    isValid = false;
                }
            }
            else
            {
                isValid = false;
            }

            return(Task.FromResult(isValid));
        }
Esempio n. 14
0
        /// <summary>
        /// Handle the LTI POST request from the Authorization Server.
        /// </summary>
        /// <returns></returns>
        public async Task <IActionResult> OnPostAsync(
            string platformId,
            [FromForm(Name = "id_token")] string idToken,
            [FromForm(Name = "scope")] string scope = null,
            [FromForm(Name = "state")] string state = null,
            [FromForm(Name = "session_state")] string sessionState = null)
        {
            // Authenticate the request starting at step 5 in the OpenId Implicit Flow
            // See https://www.imsglobal.org/spec/security/v1p0/#platform-originating-messages
            // See https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowSteps

            // The Platform MUST send the id_token via the OAuth 2 Form Post
            // See https://www.imsglobal.org/spec/security/v1p0/#successful-authentication
            // See http://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html

            if (string.IsNullOrEmpty(idToken))
            {
                Error = "id_token is missing or empty";
                return(Page());
            }

            var handler = new JwtSecurityTokenHandler();

            if (!handler.CanReadToken(idToken))
            {
                Error = "Cannot read id_token";
                return(Page());
            }

            var jwt = handler.ReadJwtToken(idToken);

            JwtHeader = jwt.Header;

            var messageType = jwt.Claims.SingleOrDefault(c => c.Type == Constants.LtiClaims.MessageType)?.Value;

            if (messageType.IsMissing())
            {
                Error = $"{Constants.LtiClaims.MessageType} claim is missing.";
                return(Page());
            }

            // Authentication Response Validation
            // See https://www.imsglobal.org/spec/security/v1p0/#authentication-response-validation

            // The ID Token MUST contain a nonce Claim.
            var nonce = jwt.Claims.SingleOrDefault(c => c.Type == "nonce")?.Value;

            if (string.IsNullOrEmpty(nonce))
            {
                Error = "Nonce is missing from request.";
                return(Page());
            }

            // If the launch was initiated with a 3rd party login, then there will be a state
            // entry for the nonce.
            var memorizedState = _stateContext.GetState(nonce);

            if (memorizedState == null)
            {
                Error = "Invalid nonce. Possible request replay.";
                return(Page());
            }

            // The state should be echoed back by the AS without modification
            if (memorizedState.Value != state)
            {
                Error = "Invalid state.";
                return(Page());
            }

            // Look for the platform with platformId in the redirect URI
            var platform = await _context.GetPlatformByPlatformId(platformId);

            if (platform == null)
            {
                Error = "Unknown platform.";
                return(Page());
            }

            // Using the JwtSecurityTokenHandler.ValidateToken method, validate four things:
            //
            // 1. The Issuer Identifier for the Platform MUST exactly match the value of the iss
            //    (Issuer) Claim (therefore the Tool MUST previously have been made aware of this
            //    identifier.
            // 2. The Tool MUST Validate the signature of the ID Token according to JSON Web Signature
            //    RFC 7515, Section 5; using the Public Key for the Platform which collected offline.
            // 3. The Tool MUST validate that the aud (audience) Claim contains its client_id value
            //    registered as an audience with the Issuer identified by the iss (Issuer) Claim. The
            //    aud (audience) Claim MAY contain an array with more than one element. The Tool MUST
            //    reject the ID Token if it does not list the client_id as a valid audience, or if it
            //    contains additional audiences not trusted by the Tool.
            // 4. The current time MUST be before the time represented by the exp Claim;

            RSAParameters rsaParameters;

            try
            {
                var httpClient = _httpClientFactory.CreateClient();
                var keySetJson = await httpClient.GetStringAsync(platform.JwkSetUrl);

                var keySet = JsonConvert.DeserializeObject <JsonWebKeySet>(keySetJson);
                var key    = keySet.Keys.SingleOrDefault(k => k.Kid == jwt.Header.Kid);
                if (key == null)
                {
                    Error = "No matching key found.";
                    return(Page());
                }

                rsaParameters = new RSAParameters
                {
                    Modulus  = Base64UrlEncoder.DecodeBytes(key.N),
                    Exponent = Base64UrlEncoder.DecodeBytes(key.E)
                };
            }
            catch (Exception e)
            {
                Error = e.Message;
                return(Page());
            }

            var validationParameters = new TokenValidationParameters
            {
                ValidateTokenReplay      = true,
                ValidateAudience         = true,
                ValidateIssuer           = true,
                RequireSignedTokens      = true,
                ValidateIssuerSigningKey = true,

                ValidAudience    = Request.GetUri().GetLeftPart(UriPartial.Authority),
                ValidIssuer      = platform.Issuer,
                IssuerSigningKey = new RsaSecurityKey(rsaParameters),

                ValidateLifetime = true,
                ClockSkew        = TimeSpan.FromMinutes(5.0)
            };

            try
            {
                handler.ValidateToken(idToken, validationParameters, out _);
            }
            catch (Exception e)
            {
                Error = e.Message;
                return(Page());
            }

            if (messageType == Constants.Lti.LtiDeepLinkingRequestMessageType)
            {
                return(Post("/Catalog", new { idToken }));
            }

            IdToken    = idToken;
            LtiRequest = new LtiResourceLinkRequest(jwt.Payload);

            if (LtiRequest.ResourceLink.Id.Contains("YT="))
            {
                return(Post("/ResourcePresenters/YoutubePresenter", new { LtiRequest = JsonConvert.SerializeObject(LtiRequest) }));
            }
            else if (LtiRequest.ResourceLink.Id.Contains("VI="))
            {
                return(Post("/ResourcePresenters/VimeoPresenter", new { LtiRequest = JsonConvert.SerializeObject(LtiRequest) }));
            }
            else if (LtiRequest.Custom.ContainsKey("videoId"))
            {
                var video = _context.Videos.FirstOrDefault(v => v.Id == int.Parse(LtiRequest.Custom["videoId"]));

                if (video != null && video.VideoType == VideoType.Youtube)
                {
                    return(Post("/ResourcePresenters/YoutubePresenter", new { LtiRequest = JsonConvert.SerializeObject(LtiRequest) }));
                }
                else if (video != null && video.VideoType == VideoType.Vimeo)
                {
                    return(Post("/ResourcePresenters/VimeoPresenter", new { LtiRequest = JsonConvert.SerializeObject(LtiRequest) }));
                }
            }

            return(Page());
        }
        public static void AddAuthentication_JWTSetup(this IServiceCollection services)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }


            var symmetricKeyAsBase64 = AppSecretConfig.Audience_Secret_String;
            var keyByteArray         = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
            var signingKey           = new SymmetricSecurityKey(keyByteArray);
            var Issuer   = Appsettings.app(new string[] { "Audience", "Issuer" });
            var Audience = Appsettings.app(new string[] { "Audience", "Audience" });

            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

            // 令牌验证参数
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey         = signingKey,
                ValidateIssuer           = true,
                ValidIssuer           = Issuer,   //发行人
                ValidateAudience      = true,
                ValidAudience         = Audience, //订阅人
                ValidateLifetime      = true,
                ClockSkew             = TimeSpan.FromSeconds(30),
                RequireExpirationTime = true,
            };

            // 开启Bearer认证
            services.AddAuthentication(o =>
            {
                o.DefaultScheme          = JwtBearerDefaults.AuthenticationScheme;
                o.DefaultChallengeScheme = nameof(ApiResponseHandler);
                o.DefaultForbidScheme    = nameof(ApiResponseHandler);
            })
            // 添加JwtBearer服务
            .AddJwtBearer(o =>
            {
                o.TokenValidationParameters = tokenValidationParameters;
                o.Events = new JwtBearerEvents
                {
                    OnChallenge = context =>
                    {
                        context.Response.Headers.Add("Token-Error", context.ErrorDescription);
                        return(Task.CompletedTask);
                    },
                    OnAuthenticationFailed = context =>
                    {
                        var jwtHandler = new JwtSecurityTokenHandler();
                        var token      = context.Request.Headers["Authorization"].ObjToString().Replace("Bearer ", "");

                        if (token.IsNotEmptyOrNull() && jwtHandler.CanReadToken(token))
                        {
                            var jwtToken = jwtHandler.ReadJwtToken(token);

                            if (jwtToken.Issuer != Issuer)
                            {
                                context.Response.Headers.Add("Token-Error-Iss", "issuer is wrong!");
                            }

                            if (jwtToken.Audiences.FirstOrDefault() != Audience)
                            {
                                context.Response.Headers.Add("Token-Error-Aud", "Audience is wrong!");
                            }
                        }


                        // 如果过期,则把<是否过期>添加到,返回头信息中
                        if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                        {
                            context.Response.Headers.Add("Token-Expired", "true");
                        }
                        return(Task.CompletedTask);
                    }
                };
            })
            .AddScheme <AuthenticationSchemeOptions, ApiResponseHandler>(nameof(ApiResponseHandler), o => { });
        }
        private static bool IsAccessTokenJwtToken(string accessToken)
        {
            var handler = new JwtSecurityTokenHandler();

            return(handler.CanReadToken(accessToken));
        }
Esempio n. 17
0
        public async Task Invoke(HttpContext context, DataContext dataContext)
        {
            string authorize = context.Request.Headers["Authorization"];
            string route     = context.Request.Path;

            // Validate
            if (!route.StartsWith("/api"))
            {
                context.Session.SetInt32(SessionConstant.NeedAuthorize, 0);
                await next(context);

                return;
            }

            route = route.Substring("/api/".Length);

            var isAuthorize = needAuthorize(route);

            if (isAuthorize == false)
            {
                context.Session.SetInt32(SessionConstant.NeedAuthorize, 0);
                await next(context);
            }
            else
            {
                context.Session.SetInt32(SessionConstant.NeedAuthorize, 1);

                if (authorize != null && authorize.StartsWith("Bearer"))
                {
                    string token = authorize.Substring("Bearer ".Length).Trim();

                    var handler = new JwtSecurityTokenHandler();
                    if (handler.CanReadToken(token))
                    {
                        var decodeToken = handler.ReadJwtToken(token);

                        if (route.StartsWith("admin/"))
                        {
                            context.Session.SetString(SessionConstant.Site, SessionConstant.Admin);

                            var userId = decodeToken.Claims.FirstOrDefault(c => c.Type == "nameid") != null?
                                         decodeToken.Claims.FirstOrDefault(c => c.Type == "nameid").Value : null;

                            var username = decodeToken.Claims.FirstOrDefault(c => c.Type == "unique_name") != null?
                                           decodeToken.Claims.FirstOrDefault(c => c.Type == "unique_name").Value : null;

                            var role = decodeToken.Claims.FirstOrDefault(c => c.Type == "role") != null?
                                       decodeToken.Claims.FirstOrDefault(c => c.Type == "role").Value : null;

                            var user = await dataContext.Users.FirstOrDefaultAsync(u => u.Id.ToString() == userId);

                            if (user == null || user.Username != username || userId == null)
                            {
                                await MiddlewareHelper.AccessDenied(context);

                                return;
                            }

                            context.Session.SetString(SessionConstant.Route, route);
                            context.Session.SetString(SessionConstant.Role, role);
                            context.Session.SetString(SessionConstant.Username, username);
                        }
                        else if (route.StartsWith("client/"))
                        {
                            context.Session.SetString(SessionConstant.Site, SessionConstant.Client);

                            var username = decodeToken.Claims.FirstOrDefault(c => c.Type == "sub") != null?
                                           decodeToken.Claims.FirstOrDefault(c => c.Type == "sub").Value : null;

                            //
                            // var customer = await dataContext.Customers.FirstOrDefaultAsync(c => c.Username == username);

                            if (username == null)
                            {
                                await MiddlewareHelper.AccessDenied(context);

                                return;
                            }

                            context.Session.SetString(SessionConstant.Username, username);
                        }

                        await next(context);
                    }
                    else
                    {
                        await MiddlewareHelper.AccessDenied(context);

                        return;
                    }
                }
                else
                {
                    await MiddlewareHelper.AccessDenied(context);

                    return;
                }
            }
        }
 public bool CanReadToken(string securityToken)
 {
     return(_tokenHandler.CanReadToken(securityToken));
 }
Esempio n. 19
0
        public async Task GivenPatientIdAndSmartAppUrl_WhenLaunchingApp_LaunchSequenceAndSignIn()
        {
            // There is no remote FHIR server. Skip test
            if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TestEnvironmentUrl")))
            {
                return;
            }

            var options = new ChromeOptions();

            options.AddArgument("--headless");
            options.AddArgument("--disable-gpu");
            options.AddArgument("--incognito");

            // TODO: We are accepting insecure certs to make it practical to run on build systems. A valid cert should be on the build system.
            options.AcceptInsecureCertificates = true;

            FhirResponse <Patient> response = await _fixture.FhirClient.CreateAsync(Samples.GetDefaultPatient());

            Assert.Equal(HttpStatusCode.Created, response.StatusCode);
            Patient patient = response.Resource;

            // VSTS Hosted agents set the ChromeWebDriver Env, locally that is not the case
            // https://docs.microsoft.com/en-us/azure/devops/pipelines/test/continuous-test-selenium?view=vsts#decide-how-you-will-deploy-and-test-your-app
            if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("ChromeWebDriver")))
            {
                Environment.SetEnvironmentVariable("ChromeWebDriver", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
            }

            using (var driver = new ChromeDriver(Environment.GetEnvironmentVariable("ChromeWebDriver"), options))
            {
                // TODO: This parameter has been set (too) conservatively to ensure that content
                //       loads on build machines. Investigate if one could be less sensitive to that.
                driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);

                void Advance()
                {
                    while (true)
                    {
                        try
                        {
                            var button = driver.FindElementById("idSIButton9");
                            if (button.Enabled)
                            {
                                button.Click();
                                return;
                            }
                        }
                        catch (StaleElementReferenceException)
                        {
                        }
                    }
                }

                driver.Navigate().GoToUrl(_fixture.SmartLauncherUrl);

                var patientElement = driver.FindElement(By.Id("patient"));
                patientElement.SendKeys(patient.Id);

                var launchButton = driver.FindElement(By.Id("launchButton"));
                if (launchButton.Enabled)
                {
                    launchButton.Click();
                }

                var testUserName     = TestUsers.AdminUser.UserId;
                var testUserPassword = TestUsers.AdminUser.Password;

                // Launcher opens a new tab, switch to it
                driver.SwitchTo().Window(driver.WindowHandles[1]);

                int waitCount = 0;
                while (!driver.Url.StartsWith($"https://login.microsoftonline.com"))
                {
                    Thread.Sleep(TimeSpan.FromMilliseconds(1000));
                    Assert.InRange(waitCount++, 0, 10);
                }

                driver.FindElementByName("loginfmt").SendKeys(testUserName);
                Advance();

                driver.FindElementByName("passwd").SendKeys(testUserPassword);
                Advance();

                // Consent, should only be done if we can find the button
                try
                {
                    var button = driver.FindElementById("idSIButton9");
                    Advance();
                }
                catch (NoSuchElementException)
                {
                    // Nothing to do, we are assuming that we are at the SMART App screen.
                }

                var tokenResponseElement = driver.FindElement(By.Id("tokenresponsefield"));
                var tokenResponseText    = tokenResponseElement.GetAttribute("value");

                // It can take some time for the token to appear, we will wait
                waitCount = 0;
                while (string.IsNullOrWhiteSpace(tokenResponseText))
                {
                    Thread.Sleep(TimeSpan.FromMilliseconds(1000));
                    tokenResponseText = tokenResponseElement.GetAttribute("value");
                    Assert.InRange(waitCount++, 0, 10);
                }

                // Check the token response, should have right audience
                var tokenResponse = JObject.Parse(tokenResponseElement.GetAttribute("value"));
                var jwtHandler    = new JwtSecurityTokenHandler();
                Assert.True(jwtHandler.CanReadToken(tokenResponse["access_token"].ToString()));
                var token = jwtHandler.ReadJwtToken(tokenResponse["access_token"].ToString());
                var aud   = token.Claims.Where(c => c.Type == "aud").ToList();
                Assert.Single(aud);
                var tokenAudience = aud.First().Value;
                Assert.Equal(Environment.GetEnvironmentVariable("TestEnvironmentUrl"), tokenAudience);

                // Check the patient
                var patientResponseElement = driver.FindElement(By.Id("patientfield"));
                var patientResource        = JObject.Parse(patientResponseElement.GetAttribute("value"));
                Assert.Equal(patient.Id, patientResource["id"].ToString());
            }
        }
        public void GetHlsKeyDeliveryUrlAndFetchKeyWithADJWTAuthUsingADOpenConnectDiscovery()
        {
            //
            // The Client ID is used by the application to uniquely identify itself to Azure AD.
            // The App Key is a credential used by the application to authenticate to Azure AD.
            // The Tenant is the name of the Azure AD tenant in which this application is registered.
            // The AAD Instance is the instance of Azure, for example public Azure or Azure China.
            // The Authority is the sign-in URL of the tenant.
            //
            string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
            string tenant      = ConfigurationManager.AppSettings["ida:Tenant"];
            string clientId    = ConfigurationManager.AppSettings["ida:ClientId"];
            string appKey      = ConfigurationManager.AppSettings["ida:AppKey"];

            string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);

            //
            // To authenticate to the To Do list service, the client needs to know the service's App ID URI.
            // To contact the To Do list service we need it's URL as well.
            //
            string appResourceId = ConfigurationManager.AppSettings["app:AppResourceId"];

            IContentKey contentKey = null;
            IContentKeyAuthorizationPolicy       contentKeyAuthorizationPolicy = null;
            IContentKeyAuthorizationPolicyOption policyOption = null;

            var authContext      = new AuthenticationContext(authority);
            var clientCredential = new ClientCredential(clientId, appKey);

            try
            {
                byte[] expectedKey = null;
                contentKey = CreateTestKey(_mediaContext, ContentKeyType.EnvelopeEncryption, out expectedKey, "GetHlsKeyDeliveryUrlAndFetchKeyWithADJWTAuthUsingADOpenConnectDiscovery" + Guid.NewGuid().ToString());

                TokenRestrictionTemplate tokenRestrictionTemplate = new TokenRestrictionTemplate(TokenType.JWT);
                tokenRestrictionTemplate.OpenIdConnectDiscoveryDocument = new OpenIdConnectDiscoveryDocument("https://login.windows.net/common/.well-known/openid-configuration");
                var    result         = authContext.AcquireTokenAsync(appResourceId, clientCredential).Result;
                string jwtTokenString = result.AccessToken;

                JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
                Assert.IsTrue(handler.CanReadToken(jwtTokenString));
                JwtSecurityToken token = handler.ReadToken(jwtTokenString) as JwtSecurityToken;
                Assert.IsNotNull(token);

                tokenRestrictionTemplate.Audience = token.Audiences.First();
                tokenRestrictionTemplate.Issuer   = token.Issuer;

                string optionName   = "GetHlsKeyDeliveryUrlAndFetchKeyWithJWTAuthentication";
                string requirements = TokenRestrictionTemplateSerializer.Serialize(tokenRestrictionTemplate);
                policyOption = ContentKeyAuthorizationPolicyOptionTests.CreateOption(_mediaContext, optionName, ContentKeyDeliveryType.BaselineHttp, requirements, null, ContentKeyRestrictionType.TokenRestricted);

                List <IContentKeyAuthorizationPolicyOption> options = new List <IContentKeyAuthorizationPolicyOption>
                {
                    policyOption
                };

                contentKeyAuthorizationPolicy = CreateTestPolicy(_mediaContext, String.Empty, options, ref contentKey);

                Uri keyDeliveryServiceUri = contentKey.GetKeyDeliveryUrl(ContentKeyDeliveryType.BaselineHttp);
                Assert.IsNotNull(keyDeliveryServiceUri);

                // Enable once all accounts are enabled for per customer Key Delivery Urls
                //Assert.IsTrue(keyDeliveryServiceUri.Host.StartsWith(_mediaContext.Credentials.ClientId));

                KeyDeliveryServiceClient keyClient = new KeyDeliveryServiceClient(RetryPolicy.DefaultFixed);
                byte[] key = keyClient.AcquireHlsKeyWithBearerHeader(keyDeliveryServiceUri, jwtTokenString);

                string expectedString = GetString(expectedKey);
                string fetchedString  = GetString(key);
                Assert.AreEqual(expectedString, fetchedString);
            }
            finally
            {
                CleanupKeyAndPolicy(contentKey, contentKeyAuthorizationPolicy, policyOption);
            }
        }
 public bool CanReadToken(string securityToken) => tokenHandler.CanReadToken(securityToken);
Esempio n. 22
0
        /// <summary>
        /// Check access
        /// </summary>
        public override bool CheckAccess(OperationContext operationContext)
        {
            RemoteEndpointMessageProperty remoteEndpoint = (RemoteEndpointMessageProperty)operationContext.IncomingMessageProperties[RemoteEndpointMessageProperty.Name];

            try
            {
                this.m_traceSource.TraceInformation("CheckAccess");

                // Http message inbound
                HttpRequestMessageProperty httpMessage = (HttpRequestMessageProperty)operationContext.IncomingMessageProperties[HttpRequestMessageProperty.Name];

                // Get the authorize header
                String authorization = httpMessage.Headers[System.Net.HttpRequestHeader.Authorization];
                if (authorization == null)
                {
                    if (httpMessage.Method == "OPTIONS" || httpMessage.Method == "PING")
                    {
                        //operationContext.ServiceSecurityContext.AuthorizationContext.Properties["Identities"] = identities;
                        operationContext.ServiceSecurityContext.AuthorizationContext.Properties["Principal"] = Core.Security.AuthenticationContext.AnonymousPrincipal;
                        Core.Security.AuthenticationContext.Current = new Core.Security.AuthenticationContext(Core.Security.AuthenticationContext.AnonymousPrincipal);

                        return(true); // OPTIONS is non PHI infrastructural
                    }
                    else
                    {
                        throw new UnauthorizedRequestException("Missing Authorization header", "Bearer", this.m_configuration.Security.ClaimsAuth.Realm, this.m_configuration.Security.ClaimsAuth.Audiences.FirstOrDefault());
                    }
                }
                else if (!authorization.Trim().StartsWith("bearer", StringComparison.InvariantCultureIgnoreCase))
                {
                    throw new UnauthorizedRequestException("Invalid authentication scheme", "Bearer", this.m_configuration.Security.ClaimsAuth.Realm, this.m_configuration.Security.ClaimsAuth.Audiences.FirstOrDefault());
                }

                String authorizationToken       = authorization.Substring(6).Trim();
                JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();

                var identityModelConfig = ApplicationContext.Current.GetService <IConfigurationManager>().GetSection("system.identityModel") as SystemIdentityModelSection;

                if (!handler.CanReadToken(authorizationToken))
                {
                    throw new SecurityTokenException("Token is not in a valid format");
                }

                SecurityToken token      = null;
                var           identities = handler.ValidateToken(authorizationToken, this.m_configuration?.Security?.ClaimsAuth?.ToConfigurationObject(), out token);

                // Validate token expiry
                if (token.ValidTo < DateTime.Now.ToUniversalTime())
                {
                    throw new SecurityTokenException("Token expired");
                }
                else if (token.ValidFrom > DateTime.Now.ToUniversalTime())
                {
                    throw new SecurityTokenException("Token not yet valid");
                }

                operationContext.ServiceSecurityContext.AuthorizationContext.Properties["Identities"] = identities.Identities;
                operationContext.ServiceSecurityContext.AuthorizationContext.Properties["Principal"]  = identities;
                Core.Security.AuthenticationContext.Current = new Core.Security.AuthenticationContext(identities);

                this.m_traceSource.TraceInformation("User {0} authenticated via JWT", identities.Identity.Name);

                return(base.CheckAccess(operationContext));
            }
            catch (UnauthorizedAccessException e) {
                this.m_traceSource.TraceEvent(TraceEventType.Error, e.HResult, "JWT Token Error (From: {0}) : {1}", remoteEndpoint?.Address, e);

                throw;
            }
            catch (UnauthorizedRequestException e) {
                this.m_traceSource.TraceEvent(TraceEventType.Error, e.HResult, "JWT Token Error (From: {0}) : {1}", remoteEndpoint?.Address, e);

                throw;
            }
            catch (Exception e)
            {
                this.m_traceSource.TraceEvent(TraceEventType.Error, e.HResult, "JWT Token Error (From: {0}) : {1}", remoteEndpoint?.Address, e);
                throw new SecurityTokenException(e.Message, e);
            }
        }
Esempio n. 23
0
        public async Task DashboardLoginSuccessFull_and_TokenValidForFhirServer()
        {
            Assert.True(!string.IsNullOrWhiteSpace(_config["FhirServerUrl"]));
            Assert.True(!string.IsNullOrWhiteSpace(_config["DashboardUrl"]));
            Assert.True(!string.IsNullOrWhiteSpace(_config["DashboardUserUpn"]));
            Assert.True(!string.IsNullOrWhiteSpace(_config["DashboardUserPassword"]));

            var options      = new ChromeOptions();
            var dashboardUrl = _config["DashboardUrl"];

            // We have to make sure the website is up
            // On a fresh deployment it can take time before site is deployed
            var client = new HttpClient();
            var result = await client.GetAsync(dashboardUrl);

            int waitCount = 0;

            while ((waitCount++ < 10) && !result.IsSuccessStatusCode)
            {
                Thread.Sleep(TimeSpan.FromSeconds(30));
                result = await client.GetAsync(dashboardUrl);
            }

            Assert.True(result.IsSuccessStatusCode);

            options.AddArgument("--headless");
            options.AddArgument("--disable-gpu");
            options.AddArgument("--incognito");

            // VSTS Hosted agents set the ChromeWebDriver Env, locally that is not the case
            // https://docs.microsoft.com/en-us/azure/devops/pipelines/test/continuous-test-selenium?view=vsts#decide-how-you-will-deploy-and-test-your-app
            if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("ChromeWebDriver")))
            {
                Environment.SetEnvironmentVariable("ChromeWebDriver", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
            }

            using (var driver = new ChromeDriver(Environment.GetEnvironmentVariable("ChromeWebDriver"), options))
            {
                // TODO: This parameter has been set (too) conservatively to ensure that content
                //       loads on build machines. Investigate if one could be less sensitive to that.
                driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);

                void Advance()
                {
                    while (true)
                    {
                        try
                        {
                            var button = driver.FindElementById("idSIButton9");
                            if (button.Enabled)
                            {
                                button.Click();
                                return;
                            }
                        }
                        catch (StaleElementReferenceException)
                        {
                        }
                    }
                }

                driver.Navigate().GoToUrl(_config["DashboardUrl"]);

                driver.SwitchTo().ActiveElement().SendKeys(_config["DashboardUserUpn"]);
                Advance();

                driver.FindElementByName("passwd").SendKeys(_config["DashboardUserPassword"]);
                Advance();

                // Consent, should only be done if we can find the button
                try
                {
                    var button = driver.FindElementById("idSIButton9");
                    Advance();
                }
                catch (NoSuchElementException)
                {
                    // Nothing to do
                }

                driver.Navigate().GoToUrl($"{dashboardUrl}/Home/AboutMe");

                waitCount = 0;
                while (!driver.Url.StartsWith($"{dashboardUrl}/Home/AboutMe"))
                {
                    Thread.Sleep(TimeSpan.FromMilliseconds(5000));

                    // We may have to consent a second time since we are asking for a new audience
                    try
                    {
                        var button = driver.FindElementById("idSIButton9");
                        Advance();
                    }
                    catch (NoSuchElementException)
                    {
                        // Nothing to do
                    }

                    Assert.InRange(waitCount++, 0, 10);
                }

                var    element    = driver.FindElement(By.Id("tokenfield"));
                string elementval = element.GetAttribute("value");

                var jwtHandler = new JwtSecurityTokenHandler();

                Assert.True(jwtHandler.CanReadToken(elementval));

                var token = jwtHandler.ReadJwtToken(elementval);
                var aud   = token.Claims.Where(c => c.Type == "aud");

                Assert.Single(aud);

                var tokenAudience = aud.First().Value;

                Assert.Equal(_config["FhirServerUrl"], tokenAudience);
            }
        }
Esempio n. 24
0
        private bool IsAuthorized(string tokenstring)
        {
            // return true;
            try
            {
                JwtSecurityTokenHandler tokenhandler = new JwtSecurityTokenHandler();
                if (tokenhandler.CanReadToken(tokenstring))
                {
                    JwtSecurityToken token   = tokenhandler.ReadJwtToken(tokenstring);
                    JwtPayload       payload = token.Payload;
                    if (payload.Count() > 0 && payload["Username"] != null)
                    {
                        string Username = payload["Username"].ToString();

                        //string role = payload["Role"].ToString();
                        //if (Roles != null)
                        //{
                        //    if (!Roles.Contains(role))
                        //    {
                        //        return false;
                        //    }
                        //}

                        var data = _userServices.GetuserByCustomuserName(Username).data;
                        if (data != null)
                        {
                            //Setting Userid in Session
                            //this.httpContextAccessor.HttpContext.Session.SetString("UserId", data.Id.ToString());


                            var securityKey          = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(System.Text.Encoding.UTF32.GetBytes(Username));
                            var validationParameters = new TokenValidationParameters
                            {
                                ValidateIssuerSigningKey = true,
                                IssuerSigningKey         = securityKey,
                                ValidateAudience         = false,
                                ValidateIssuer           = false,
                                ValidateActor            = false,
                                ValidateLifetime         = true,
                                ValidateTokenReplay      = false,
                                LifetimeValidator        = LifetimeValidator
                            };
                            SecurityToken validatedToken;
                            try
                            {
                                tokenhandler.ValidateToken(tokenstring, validationParameters, out validatedToken);
                            }
                            catch (Exception ex)
                            {
                                return(false);
                            }
                            return(validatedToken != null);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
            }
            catch (Exception ex)
            {
                return(false);
            }
        }
Esempio n. 25
0
        public JwtSecurityToken DecodeToken(string token)
        {
            var handler = new JwtSecurityTokenHandler();

            return(handler.CanReadToken(token) ? handler.ReadJwtToken(token) : null);
        }
Esempio n. 26
0
        private string Update(string jwtInput)
        {
            try
            {
                jwtInput = Strip(jwtInput);
                var jwtHandler = new JwtSecurityTokenHandler();

                //Check if readable token (string is in a JWT format)
                var readableToken = jwtHandler.CanReadToken(jwtInput);

                if (!readableToken)
                {
                    return("The token doesn't seem to be in a proper JWT format.");
                }
                var sb    = new StringBuilder();
                var token = jwtHandler.ReadJwtToken(jwtInput);

                //Extract the headers of the JWT
                var headers   = token.Header;
                var jwtHeader = "{";
                foreach (var h in headers)
                {
                    jwtHeader += '"' + h.Key + "\":\"" + h.Value + "\",";
                }
                jwtHeader += "}";
                sb.Append("Header:\r\n" + JToken.Parse(jwtHeader).ToString(Formatting.Indented));

                //Extract the payload of the JWT
                var claims     = token.Claims;
                var jwtPayload = "{";
                var claimMap   = new Dictionary <string, List <string> >();
                foreach (var c in claims)
                {
                    var value = c.Value;
                    if (int.TryParse(value, out int ts))
                    {
                        var time = DateTimeOffset.FromUnixTimeSeconds(ts);
                        value += $" ({time})";

                        if (c.Type == "iat" && time > DateTimeOffset.Now)
                        {
                            value += " NOT VALID YET";
                        }
                        else if (c.Type == "nbf" && time > DateTimeOffset.Now)
                        {
                            value += " NOT VALID YET";
                        }
                        else if (c.Type == "exp" && time < DateTimeOffset.Now)
                        {
                            value += " EXPIRED";
                        }
                    }
                    if (!claimMap.ContainsKey(c.Type))
                    {
                        claimMap.Add(c.Type, new List <string>());
                    }

                    claimMap[c.Type].Add(value);
                }
                foreach (var pair in claimMap)
                {
                    var type   = pair.Key;
                    var values = pair.Value;
                    if (values.Count == 1)
                    {
                        jwtPayload += '"' + type + "\":\"" + values[0] + "\",";
                    }
                    else
                    {
                        // same claim type might provide multiple values in separate claims (e.g. roles) -> merge into one
                        jwtPayload += '"' + type + "\":[" + string.Join(", ", values.Select(v => $"\"{v}\"")) + "],";
                    }
                }
                jwtPayload += "}";
                sb.Append("\r\nPayload:\r\n" + JToken.Parse(jwtPayload).ToString(Formatting.Indented));
                return(sb.ToString());
            }
            catch (Exception e)
            {
                return(e.Message);
            }
        }
Esempio n. 27
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var redisConnectionString = configuration.GetValue <string>("REDIS_CONNECTIONSTRING", null);
            var dataProtectionPath    = configuration.GetValue <string>("KEY_RING_PATH", null);
            var applicationName       = configuration.GetValue("APP_NAME", Assembly.GetExecutingAssembly().GetName().Name);

            if (!string.IsNullOrEmpty(redisConnectionString))
            {
                Log.Information("Configuring {0} to use Redis cache", applicationName);
                services.AddStackExchangeRedisCache(options =>
                {
                    options.Configuration = redisConnectionString;
                });
                services.AddDataProtection()
                .SetApplicationName(applicationName)
                .PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(redisConnectionString), "data-protection-keys");
            }
            else
            {
                Log.Warning("Configuring {0} to use in-memory cache", applicationName);
                services.AddDistributedMemoryCache();
                var dpBuilder = services.AddDataProtection()
                                .SetApplicationName(applicationName);

                if (!string.IsNullOrEmpty(dataProtectionPath))
                {
                    dpBuilder.PersistKeysToFileSystem(new DirectoryInfo(dataProtectionPath));
                }
            }

            services.AddControllers();

            var connectionString = configuration.GetConnectionString("DefaultConnection");
            var configFile       = configuration.GetValue("IDENTITYSERVER_CONFIG_FILE", (string)null);

            if (string.IsNullOrEmpty(configFile) || !File.Exists(configFile))
            {
                throw new Exception($"Config file not found: check env var IDENTITYSERVER_CONFIG_FILE={configFile}");
            }
            var config = JsonConvert.DeserializeObject <Config>(File.ReadAllText(configFile));

            //add IdentityServer
            var builder = services
                          .AddOidcStateDataFormatterCache()
                          .AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents       = true;
                options.Events.RaiseInformationEvents = true;
                options.Events.RaiseFailureEvents     = true;
                options.Events.RaiseSuccessEvents     = true;

                options.UserInteraction.LoginUrl  = "~/login";
                options.UserInteraction.LogoutUrl = "~/logout";
                options.IssuerUri = configuration.GetValue("IDENTITYSERVER_ISSUER_URI", (string)null);
            })

                          .AddOperationalStore(options =>
            {
                options.ConfigureDbContext = builder => builder.UseSqlite(connectionString, sql => sql.MigrationsAssembly(typeof(Startup).Assembly.FullName));
                options.EnableTokenCleanup = true;
            })
                          .AddInMemoryApiScopes(config.ApiScopes)
                          .AddInMemoryClients(config.Clients)
                          .AddInMemoryIdentityResources(config.IdentityResources)
                          .AddInMemoryApiResources(config.ApiResources)
                          .AddInMemoryCaching();

            services.AddTestUsers(configuration);

            //store the oidc key in the key ring persistent volume
            var keyPath = Path.Combine(new DirectoryInfo(dataProtectionPath ?? "./Data").FullName, "oidc_key.jwk");

            //add key as signing key
            builder.AddDeveloperSigningCredential(filename: keyPath);

            //add key as encryption key to oidc jwks endpoint that is used by BCSC to encrypt tokens
            var encryptionKey = Microsoft.IdentityModel.Tokens.JsonWebKey.Create(File.ReadAllText(keyPath));

            encryptionKey.Use = "enc";
            builder.AddValidationKey(new SecurityKeyInfo {
                Key = encryptionKey
            });

            services.AddDistributedMemoryCache();
            services.AddResponseCompression();

            services.AddAuthentication()
            .AddOpenIdConnect("bcsc", options =>
            {
                // Note: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler  doesn't handle JWE correctly
                // See https://github.com/dotnet/aspnetcore/issues/4650 for more information
                // When BCSC user info payload is encrypted, we need to load the user info manually in OnTokenValidated event below
                // IdentityModel.Client also doesn't support JWT userinfo responses, so the following code takes care of this manually
                options.GetClaimsFromUserInfoEndpoint = false;

                configuration.GetSection("identityproviders:bcsc").Bind(options);

                options.ResponseType  = OpenIdConnectResponseType.Code;
                options.SignInScheme  = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                options.SignOutScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

                //add required scopes
                options.Scope.Add("profile");
                options.Scope.Add("address");
                options.Scope.Add("email");

                //set the tokens decrypting key
                options.TokenValidationParameters.TokenDecryptionKey = encryptionKey;

                options.Events = new OpenIdConnectEvents
                {
                    OnTokenValidated = async ctx =>
                    {
                        var oidcConfig = await ctx.Options.ConfigurationManager.GetConfigurationAsync(CancellationToken.None);

                        //set token validation parameters
                        var validationParameters = ctx.Options.TokenValidationParameters.Clone();
                        validationParameters.IssuerSigningKeys = oidcConfig.JsonWebKeySet.GetSigningKeys();
                        validationParameters.ValidateLifetime  = false;
                        validationParameters.ValidateIssuer    = false;
                        var userInfoRequest = new UserInfoRequest
                        {
                            Address = oidcConfig.UserInfoEndpoint,
                            Token   = ctx.TokenEndpointResponse.AccessToken
                        };
                        //set the userinfo response to be JWT
                        userInfoRequest.Headers.Accept.Clear();
                        userInfoRequest.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/jwt"));

                        //request userinfo claims through the backchannel
                        var response = await ctx.Options.Backchannel.GetUserInfoAsync(userInfoRequest, CancellationToken.None);
                        if (response.IsError && response.HttpStatusCode == HttpStatusCode.OK)
                        {
                            //handle encrypted userinfo response...
                            if (response.HttpResponse.Content?.Headers?.ContentType?.MediaType == "application/jwt")
                            {
                                var handler = new JwtSecurityTokenHandler();
                                if (handler.CanReadToken(response.Raw))
                                {
                                    handler.ValidateToken(response.Raw, validationParameters, out var token);
                                    var jwe = token as JwtSecurityToken;
                                    ctx.Principal.AddIdentity(new ClaimsIdentity(new[] { new Claim("userInfo", jwe.Payload.SerializeToJson()) }));
                                }
                            }
                            else
                            {
                                //...or fail
                                ctx.Fail(response.Error);
                            }
                        }
                        else if (response.IsError)
                        {
                            //handle for all other failures
                            ctx.Fail(response.Error);
                        }
                        else
                        {
                            //handle non encrypted userinfo response
                            ctx.Principal.AddIdentity(new ClaimsIdentity(new[] { new Claim("userInfo", response.Json.GetRawText()) }));
                        }
                    },
                    OnUserInformationReceived = async ctx =>
                    {
                        //handle userinfo claim mapping when options.GetClaimsFromUserInfoEndpoint = true
                        await Task.CompletedTask;
                        ctx.Principal.AddIdentity(new ClaimsIdentity(new[]
                        {
                            new Claim("userInfo", ctx.User.RootElement.GetRawText())
                        }));
                    }
                };
            });
Esempio n. 28
0
        protected async override Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var _ = (request, cancellationToken);

            var authHeader = request.Headers.Authorization;

            if (authHeader == null)
            {
                return(Next(_));
            }

            if (authHeader.Scheme != "Bearer")
            {
                return(Next(_));
            }

            if (string.IsNullOrWhiteSpace(authHeader.Parameter))
            {
                return(Next(_));
            }

            var tokenHandler = new JwtSecurityTokenHandler();

            if (!tokenHandler.CanReadToken(authHeader.Parameter))
            {
                return(request.CreateErrorResponse(HttpStatusCode.BadRequest, "Malformed Token"));
            }

            var claimsIdentity = tokenHandler.ValidateToken(authHeader.Parameter, new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
            {
                ValidateAudience      = false,
                ValidateIssuer        = false,
                RequireExpirationTime = false,
                IssuerSigningKey      = new SymmetricSecurityKey(Convert.FromBase64String(WebApiApplication.JWTSecret))
            }, out var token).Identity as ClaimsIdentity;

            if (claimsIdentity == null)
            {
                return(request.CreateErrorResponse(HttpStatusCode.BadRequest, "Empty Claims"));
            }

            UserKind kind;

            try
            {
                kind = (UserKind)Enum.Parse(typeof(UserKind), claimsIdentity.FindFirst("UserKind").Value);
            }
            catch
            {
                return(request.CreateErrorResponse(HttpStatusCode.BadRequest, "Malformed Token"));
            }
            var userId = Int32.Parse(claimsIdentity.FindFirst("UserId").Value);

            if (kind == UserKind.Leitor)
            {
                SetPrincipal(new UserPrincipal(Leitor.GetLeitor(userId)));
            }
            else
            {
                SetPrincipal(new UserPrincipal(Funcionario.GetFuncionario(userId)));
            }



            return(Next(_));
        }
Esempio n. 29
0
        /// <inheritdoc />
        /// <summary>
        /// Validates the signed JWT.
        /// </summary>
        /// <param name="secrets">The stored secrets.</param>
        /// <param name="parsedSecret">The received secret.</param>
        /// <returns>
        /// A validation result
        /// </returns>
        /// <exception cref="T:System.ArgumentException">ParsedSecret.Credential is not a JWT token</exception>
        public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            var fail = Task.FromResult(new SecretValidationResult {
                Success = false
            });
            var success = Task.FromResult(new SecretValidationResult {
                Success = true
            });

            if (parsedSecret.Type != IdentityServerConstants.ParsedSecretTypes.JwtBearer)
            {
                return(fail);
            }

            if (!(parsedSecret.Credential is string token))
            {
                _logger.LogError("ParsedSecret.Credential is not a string.");
                return(fail);
            }

            var handler = new JwtSecurityTokenHandler();

            if (!handler.CanReadToken(token))
            {
                _logger.LogError("ParsedSecret.Credential is not a well formed JWT.");
                return(fail);
            }

            // Collect the potential public keys from the client secrets
            var secretArray = secrets as Secret[] ?? secrets.ToArray();
            var pemKeys     = GetPemKeys(secretArray);

            if (!pemKeys.Any())
            {
                _logger.LogError("There are no keys available to validate the client assertion.");
                return(fail);
            }

            var tokenValidationParameters = new TokenValidationParameters
            {
                // The token must be signed to prove the client credentials.
                RequireSignedTokens   = true,
                RequireExpirationTime = true,

                IssuerSigningKeys        = pemKeys,
                ValidateIssuerSigningKey = true,

                // IMS recommendation is to send any unique name as Issuer. The IMS reference
                // implementation sends the tool name. The tool's own name for this client
                // is not known by the platform and cannot be validated.
                ValidateIssuer = false,

                // IMS recommendation is to send the base url of the authentication server
                // or the token URL.
                ValidAudiences = new []
                {
                    _audienceUri,
                    string.Concat(_audienceUri.EnsureTrailingSlash(), "connect/token")
                },
                ValidateAudience = true
            };

            try
            {
                handler.ValidateToken(token, tokenValidationParameters, out _);

                return(success);
            }
            catch (Exception e)
            {
                _logger.LogError(e, "JWT token validation error");
                return(fail);
            }
        }
Esempio n. 30
0
        public async Task <LinkState> GetCurrentUserLinkStateAsync(string payload)
        {
            var jwt = OwnIdSerializer.Deserialize <JwtContainer>(payload)?.Jwt;

            if (string.IsNullOrEmpty(jwt))
            {
                throw new Exception("No JWT was found in HttpRequest");
            }

            var tokenHandler = new JwtSecurityTokenHandler();

            if (!tokenHandler.CanReadToken(jwt))
            {
                throw new Exception("Invalid jwt");
            }

            var rsaSecurityKey = await _restApiClient.GetPublicKey();

            try
            {
                tokenHandler.ValidateToken(jwt, new TokenValidationParameters
                {
                    IssuerSigningKey         = rsaSecurityKey,
                    RequireSignedTokens      = true,
                    RequireExpirationTime    = true,
                    ValidateIssuerSigningKey = true,
                    ValidateLifetime         = true,
                    ValidateAudience         = false,
                    ValidateIssuer           = false
                                               // TODO: add issuer to token for validation
                }, out _);
            }
            catch (SecurityTokenValidationException ex)
            {
                throw new Exception($"Token failed validation: {ex.Message}");
            }
            catch (ArgumentException ex)
            {
                throw new Exception($"Token was invalid: {ex.Message}");
            }

            var token = tokenHandler.ReadJwtToken(jwt);

            if (!token.Payload.ContainsKey(ApiKeyPayloadKey) ||
                (string)token.Payload[ApiKeyPayloadKey] != _configuration.ApiKey)
            {
                throw new Exception("Jwt was created for different apiKey");
            }

            var did = token.Subject;

            var accountInfo = await _restApiClient.SearchAsync <AccountInfoResponse <TProfile> >(GigyaFields.UID, did);

            if (!accountInfo.IsSuccess)
            {
                if (accountInfo.ErrorCode != 0)
                {
                    throw new Exception(accountInfo.GetFailureMessage());
                }

                throw new Exception($"Can't find user with did = {did}");
            }

            return(new LinkState(did, (uint)(accountInfo.First.Data?.OwnId?.Connections?.Count ?? 0)));
        }