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); }
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; }
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); }
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); }
/// <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); }
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); }
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())); }
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); }
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); }
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); }
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)); }
/// <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)); }
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)); }
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);
/// <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); } }
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); } }
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); } }
public JwtSecurityToken DecodeToken(string token) { var handler = new JwtSecurityTokenHandler(); return(handler.CanReadToken(token) ? handler.ReadJwtToken(token) : null); }
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); } }
// 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()) })); } }; });
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(_)); }
/// <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); } }
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))); }