protected override bool AuthorizeCore(HttpContextBase httpContext) { string token; token = httpContext.Request.Headers["Access"]; token = token ?? httpContext.Request["Access"]; token = token ?? httpContext.Request.Cookies["Access"]?.Value; if (token == null) { return(false); } else { //解析token ValidateTokenResult obj = JwtUtils.DecodingToken(token); if (obj.ResultCode == ResultCode.Ok) //验证通过 { //延长token时间 Cache.SetCache(token, obj.Payload, obj.Payload.Exp); return(true); } else //拦截请求 { return(false); } } }
public async Task <IActionResult> ValidateSession([FromQuery(Name = "key")] string token) { var validatedPrincipal = JwtUtils.ValidateJWT(token); if (validatedPrincipal is null) { return(Unauthorized()); } int userId = int.Parse(validatedPrincipal.FindFirstValue(ClaimTypes.NameIdentifier)); var validatedUser = await Repository.FindByIdAsync(userId); var userResponse = (UserResponse)ResponseModelFactory.Create(validatedUser); return(Ok(new { Token = token, userResponse.Id, userResponse.Username, userResponse.DisplayName, userResponse.AvatarLink, userResponse.Followings, userResponse.Link })); }
public Task SetUserAsync(string token) { var payload = JwtUtils.GetPayload(token); _currentUser.UserId = payload.sub; return(Task.CompletedTask); }
private int SignCert(SignCertOptions options) { var(signingKey, signingCert) = GetSigningKeyAndCert(options); // Get certificate ValidateFileExists(options.CertFileName, "Certificate file is not accessable"); var cert = new X509Certificate2(options.CertFileName); // Sign certificate var certJwt = JwtUtils.GenerateSignedCertificateJsonWebToken(cert, signingKey, signingCert); Tracer.TraceVerbose($"Generated signed JWT = \n{JwtUtils.FormatJwt(certJwt)}\n"); // Report JWT if (!string.IsNullOrEmpty(options.JwtFileName)) { File.WriteAllText(options.JwtFileName, certJwt); } Console.WriteLine(); Console.WriteLine($"Cert JWT:"); Console.WriteLine($"{certJwt}"); Console.WriteLine(); return(0); }
public async Task ResultFilterAsync(AuthResultContext authContext, CancellationToken token = default) { if (UseTokenCookie && authContext.Result.Cookies.All(x => x.Name != Keywords.TokenCookie)) { var accessToken = CreateJwtBearerToken(authContext.Request, authContext.Session); await authContext.Request.RemoveSessionAsync(authContext.Session.Id, token); authContext.Result.AddCookie(authContext.Request, new Cookie(Keywords.TokenCookie, accessToken, Cookies.RootPath) { HttpOnly = true, Secure = authContext.Request.IsSecureConnection, Expires = DateTime.UtcNow.Add(ExpireTokensIn), }); } if (UseTokenCookie && authContext.Result.Cookies.All(x => x.Name != Keywords.RefreshTokenCookie) && EnableRefreshToken()) { var refreshToken = CreateJwtRefreshToken(authContext.Request, authContext.Session.Id, ExpireRefreshTokensIn); authContext.Result.AddCookie(authContext.Request, new Cookie(Keywords.RefreshTokenCookie, refreshToken, Cookies.RootPath) { HttpOnly = true, Secure = authContext.Request.IsSecureConnection, Expires = DateTime.UtcNow.Add(ExpireRefreshTokensIn), }); } JwtUtils.NotifyJwtCookiesUsed(authContext.Result); }
private static void VerifyCustomToken(string token, string uid, Dictionary <string, object> claims) { string[] segments = token.Split("."); Assert.Equal(3, segments.Length); var payload = JwtUtils.Decode <FirebaseTokenFactory.CustomTokenPayload>(segments[1]); Assert.Equal("*****@*****.**", payload.Issuer); Assert.Equal("*****@*****.**", payload.Subject); Assert.Equal(uid, payload.Uid); if (claims == null) { Assert.Null(payload.Claims); } else { Assert.Equal(claims.Count, payload.Claims.Count); foreach (var entry in claims) { object value; Assert.True(payload.Claims.TryGetValue(entry.Key, out value)); Assert.Equal(entry.Value, value); } } var x509cert = new X509Certificate2(File.ReadAllBytes("./resources/public_cert.pem")); var rsa = (RSA)x509cert.PublicKey.Key; var tokenData = Encoding.UTF8.GetBytes(segments[0] + "." + segments[1]); var signature = JwtUtils.Base64DecodeToBytes(segments[2]); var verified = rsa.VerifyData(tokenData, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); Assert.True(verified); }
public ActionResult <PostResponseData> Post([FromBody] PostRequestData requestData) { if (!ValidationUtils.ValidateEmail(requestData.Email)) { return(BadRequest(new { Message = "Email is invalid" })); } if (!ValidationUtils.ValidatePassword(requestData.Password)) { return(BadRequest(new { Message = "Password is invalid" })); } var userRepository = UserRepository; User existingUser = userRepository.Find(requestData.Email); if (existingUser != null) { return(BadRequest(new { Message = "User with given email already exists" })); } User user = UserRepository.Create(requestData.Email, requestData.Password); return(Ok(new PostResponseData() { Id = user.Id, Email = user.Email, Token = JwtUtils.GenerateToken(user, _jwtConfig) })); }
public void ValidateSignature() { // ARRANGE string jwtIdToken = GetJWT(); Console.WriteLine("id_token: " + jwtIdToken); Console.WriteLine(); Assert.IsTrue(jwtIdToken?.Length > 0, "Failed to obtain a jwt from getJWT()"); // ACT var claims = JwtUtils.ValidateSignature(jwtIdToken, apiDomain); for (int i = 0; i < 200; i++) { claims = JwtUtils.ValidateSignature(jwtIdToken, apiDomain); // should be really fast as public key cached. } // ASSERT Assert.IsTrue(claims != null, "claims != null"); Assert.IsTrue((string)claims["sub"] == targetUID, "'sub' != targetUID"); Assert.IsTrue((string)claims["apiKey"] == apiKey, "'apiKey' == apiKey"); Assert.IsTrue((string)claims["email"] != null, "missing 'email'"); foreach (var pair in claims) { Console.WriteLine($"{pair.Key} : {pair.Value}"); } }
public async Task <ActionResult <ResponseData> > Auth(RequestData requestData) { if (!ValidationUtils.ValidateEmail(requestData.Email)) { return(BadRequest(new { Message = "Email is invalid" })); } UserRepository userRepository = UserRepository; var user = userRepository.Find(requestData.Email); if (user == null || !PasswordUtils.Verify(requestData.Password, user.PasswordHash)) { return(new UnauthorizedResult()); } var response = new ResponseData() { Id = user.Id, Email = user.Email, Token = JwtUtils.GenerateToken(user, _jwtConfig) }; return(Ok(response)); }
public IActionResult GetAvailableRegistrations([FromQuery] int semester, [FromQuery] string authToken) { // authenticate string username = JwtUtils.ValidateJWT(authToken); if (username is null) { return(Unauthorized(new MissingAuthTokenException())); } int studentId = int.Parse(username); // return list of course classes int facultyId = (int)Context.Student.Where(s => s.Id == studentId) .FirstOrDefault()?.FacultyId.GetValueOrDefault(); IEnumerable <RegistrationClass> classes = Context.CourseClass .Include(cc => cc.Course) .Include(cc => cc.Course) .ThenInclude(cc => cc.CourseType) .Include(cc => cc.Timetable) .Where(cc => cc.Course.SemesterId == semester && (cc.Course.FacultyId == facultyId || cc.Course.CourseTypeId == 1)) .AsEnumerable() .Select(cc => ClassConverter.ForwardConverter(cc)) .ToList(); return(new JsonResult(classes)); }
public ResponseResult <string> PostLogins(string username, string password) { if (!string.IsNullOrEmpty(username.Trim()) && !string.IsNullOrEmpty(password.Trim())) { try { string token = ""; password = MD5Utils.decode(password); var user = SystemService.AuthUser(username, password, connstr); if (user != null) { JwtUtils jwt = new JwtUtils(); JwtHeader header = new JwtHeader(); header.alg = AlgEnum.HS256; JwtClaim claim = new JwtClaim(); claim.isadmin = user.AREA == 0 ? true : false; claim.area = user.AREA; claim.uid = user.ID; claim.username = user.USERNAME; claim.exp = DateTime.Now.AddMinutes(30).ToBinary(); token = jwt.EncodingJwt(header, claim); return(ResponseResult <string> .Success(token, "登录成功")); } } catch (Exception ex) { Console.Write(ex.Message); return(ResponseResult <string> .Error("登录失败")); } } return(ResponseResult <string> .Error("登录失败")); }
public IActionResult GetAllTimetable([FromQuery] int semester, [FromQuery] string authToken) { // authentication string username = JwtUtils.ValidateJWT(authToken); if (username is null) { return(Unauthorized()); } int studentId = int.Parse(username); ICollection <int> registeredCourseIds = Context.Student .Include(s => s.Registration) .Where(s => s.Id == studentId) .FirstOrDefault()? .Registration.Where(r => r.SemesterId == 20192 && r.Status == true) .Select(r => r.CourseClassId) .ToList(); return(new JsonResult(Context.CourseClass .Include(cc => cc.Timetable) .Include(cc => cc.Course) .Where(cc => registeredCourseIds.Contains(cc.CourseClassId)) .AsEnumerable() .Select(cc => cc.Timetable) .SelectMany(t => t) .Select(t => Converter.ForwardConverter(t)) .ToList())); }
public IActionResult MockPayTuitionFee([FromQuery] int semester, [FromQuery] string authToken) { // authenticate string username = JwtUtils.ValidateJWT(authToken); if (username is null) { return(Unauthorized(new MissingAuthTokenException())); } int studentId = int.Parse(username); FeeLine[] tuitionFeeLines = Context.Student .Include(s => s.Registration) .ThenInclude(r => r.FeeLine) .Where(s => s.Id == studentId) .FirstOrDefault() ?.Registration .Where(r => r.SemesterId == semester) .SelectMany(r => r.FeeLine) .ToArray(); System.Console.WriteLine(tuitionFeeLines.Length); foreach (var feeLine in tuitionFeeLines) { feeLine.MarkAsPaid(); } Context.FeeLine.UpdateRange(tuitionFeeLines); Context.SaveChanges(); return(Ok()); }
public ViewModels.Profile GetProfileForAuthenticatedUser([FromQuery] string authToken) { string username = JwtUtils.ValidateJWT(authToken); int id = int.Parse(username); return(GetProfileById(id)); }
static void Main(string[] args) { var token = new JwtUtils().GetToken(); new JwtUtils().Parse(token, "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk"); Console.ReadLine(); }
public async Task <IActionResult> Refresh([FromBody] Dictionary <string, string> data) { if (!data.ContainsKey("refresh_token")) { return(BadRequest( new { errors = new { refresh_token = "refresh_token is required" } } )); } var refreshTokenObj = _userRepo.GetRefreshToken(data["refresh_token"]);//model.RefreshToken); if (DateTime.UtcNow > refreshTokenObj.Expiration) { return(StatusCode(StatusCodes.Status500InternalServerError, new { Status = "Error", Message = "Expired Token" })); } var userRoles = await _userManager.GetRolesAsync(refreshTokenObj.User); List <Claim> authClaims = JwtUtils.GetClaims(refreshTokenObj.User, userRoles); var jwtSecret = _configuration["JWT:Secret"]; var minutesExpiration = JwtUtils.MinutesExpiration; return(Ok(new { jwt = JwtUtils.GenerateJwtToken(jwtSecret, authClaims, minutesExpiration), })); }
private int SignPolicy(SignPolicyOptions options) { var(signingKey, signingCert) = GetSigningKeyAndCert(options); // Get policy ValidateFileExists(options.PolicyFileName, "Policy file is not accessable"); var policy = File.ReadAllText(options.PolicyFileName); Tracer.TraceVerbose($"Policy to be signed = \n{policy}\n"); // Sign policy var policyJwt = JwtUtils.GenerateSignedPolicyJsonWebToken(policy, signingKey, signingCert); Tracer.TraceVerbose($"Generated signed JWT = \n{JwtUtils.FormatJwt(policyJwt)}\n"); // Report JWT if (!string.IsNullOrEmpty(options.JwtFileName)) { File.WriteAllText(options.JwtFileName, policyJwt); } Console.WriteLine(); Console.WriteLine($"Policy JWT:"); Console.WriteLine($"{policyJwt}"); Console.WriteLine(); return(0); }
public async Task <IActionResult> Auth([FromServices] IUserRepository repository, [FromBody] UserAuth user) { try { var userExists = repository.GetByEmail(user.Email); if (userExists == null) { return(new BadRequestObjectResult(new { Message = "Email and/or password is invalid." })); } if (userExists.Password != user.Password) { return(new BadRequestObjectResult(new { Message = "Email and/or password is invalid." })); } string token = JwtUtils.GenerateToken(userExists); return(new OkObjectResult(new { Token = token, User = userExists.Name })); } catch (Exception) { return(new BadRequestObjectResult(new { Message = "Internal server error" })); } }
static void Main(string[] args) { Console.WriteLine("Hello World!"); var jwt = JwtUtils.GenerateToken("abc", "BBQHCZlEixJzs1dXapEezYEtcMfuS3"); var result = JwtUtils.CheckToken(jwt, "BBQHCZlEixJzs1dXapEezYEtcMfuS3"); var resultInfo = JwtUtils.GetPayload("eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ0eXAiOiJKV1QiLCJzdWIiOiJhYmMiLCJpYXQiOjE2MDQzNzQ3NDAsImV4cCI6MTYwNDM4MTk0MCwidXNlcm5hbWUiOiJyb3kifQ.XXI07fLDK-m2gGvJe46VvR2OA4Orp3kA3AivCBrOS1l3I-Lxq3n2C_BCC5qjsz_fHAm2TQdhOM6Zdx6FRD4PJA"); }
public void GivenCorrectTokenFormatValidatesTrue() { //arrange var res = JwtUtils.ValidateToken(tokenValid); //assert Assert.IsTrue(res); }
public void Serialize() { var userProviders = new List <UserProvider> { new UserProvider() { Uid = "google.uid", ProviderId = "google.com", }, }; var customClaims = new Dictionary <string, object>() { { "admin", true }, }; var userMetadata = new UserMetadata(1, 2, null); var passwordHash = Encoding.ASCII.GetBytes("secret"); var passwordSalt = Encoding.ASCII.GetBytes("salt"); var importUserRecordArgs = new ImportUserRecordArgs() { Uid = "123", Email = "*****@*****.**", EmailVerified = true, DisplayName = "Example", PhotoUrl = "http://example.com/photo", PhoneNumber = "+11234567890", Disabled = false, UserMetadata = userMetadata, PasswordHash = passwordHash, PasswordSalt = passwordSalt, CustomClaims = customClaims, UserProviders = userProviders, }; var expected = new Dictionary <string, object>() { { "createdAt", userMetadata.CreationTimestamp }, { "customAttributes", JsonConvert.SerializeObject(customClaims) }, { "disabled", false }, { "displayName", "Example" }, { "email", "*****@*****.**" }, { "emailVerified", true }, { "lastLoginAt", userMetadata.LastSignInTimestamp }, { "passwordHash", JwtUtils.UrlSafeBase64Encode(passwordHash) }, { "salt", JwtUtils.UrlSafeBase64Encode(passwordSalt) }, { "phoneNumber", "+11234567890" }, { "photoUrl", "http://example.com/photo" }, { "providerUserInfo", userProviders.Select(userProvider => userProvider.ToRequest()) }, { "localId", "123" }, }; Assert.Equal( JsonConvert.SerializeObject(expected), JsonConvert.SerializeObject(importUserRecordArgs.ToRequest())); }
public BaseTest() { _appSettings = Options.Create(new AppSettings { Secret = SECRET_KEY }); _dateTimeProvider = new Mock <IDateTimeProvider>(); _randomCryptoBytesGenerator = new Mock <IRandomCryptoBytesGenerator>(); _sut = new JwtUtils(_appSettings, _dateTimeProvider.Object, _randomCryptoBytesGenerator.Object); }
public IActionResult AddRegistrations([FromBody] IList <ViewModels.Registration> registrations, [FromQuery] string authToken) { // authentication check string username = JwtUtils.ValidateJWT(authToken); if (username is null) { return(Unauthorized(new MissingAuthTokenException())); } // check exists in db if (registrations is null || registrations.Count == 0) { return(StatusCode(500, new { message = "Cannot register for 0 courses!" })); } IList <string> classCodes = registrations.Select(r => r.ClassCode).ToList(); int studentId = registrations.FirstOrDefault().StudentId; int semesterId = registrations.FirstOrDefault().Semester; var courseClassesToUpdate = Context.CourseClass .Include(cc => cc.Course) .Where(cc => cc.Course.SemesterId == semesterId && classCodes.Contains(cc.CourseClassCode) && cc.RemainingSlots > 0) .ToList(); classCodes = courseClassesToUpdate.Select(cc => cc.CourseClassCode).ToList(); courseClassesToUpdate.ForEach(cc => cc.RemainingSlots--); var existingRegistrations = Context.Registration.Include(r => r.CourseClass) .Where(r => classCodes.Contains(r.CourseClass.CourseClassCode) && r.StudentId == studentId && r.SemesterId == semesterId) .ToList(); existingRegistrations.ForEach(r => r.Status = true); IList <string> classCodesWithExistingRegistration = existingRegistrations .Select(r => r.CourseClass.CourseClassCode).ToList(); var newRegistrationsToCreate = registrations.Where(r => !classCodesWithExistingRegistration.Contains(r.ClassCode)) .Select(r => CreateRegistration(r)) .ToList(); // modify db Context.AddRange(newRegistrationsToCreate); Context.UpdateRange(existingRegistrations); Context.UpdateRange(courseClassesToUpdate); Context.SaveChanges(); return(Ok()); }
public IActionResult InvalidateSession([FromQuery(Name = "key")] string jwt) { var principal = JwtUtils.ValidateJWT(jwt); if (principal is null) { return(Unauthorized()); } JwtUtils.InvalidateJWT(jwt); return(Ok()); }
public ActionResult GetToken(string account, string Pwd) { //account = "admin"; //Pwd = "4a7d1ed414474e4033ac29ccb8653d9b"; Sys_User user = UserService.GetEntity(u => u.F_Account == account).FirstOrDefault(); LoginResult loginResult; if (user == null) { loginResult = new LoginResult() { Message = "用户不存在", Status = false, ResultCode = ResultCode.Error }; return(Json(loginResult)); } Sys_UserLogOn userLogOn = UserLogService.GetEntityByUserId(user.F_Id); if (userLogOn == null) { loginResult = new LoginResult() { Message = "查询不到密码信息", Status = false, ResultCode = ResultCode.Error }; return(Json(loginResult)); } string key = userLogOn.F_UserSecretkey; string pwd = DESEncrypt.Encrypt(Pwd, key).ToLower().ToMd5().ToLower(); if (userLogOn.F_UserPassword == pwd) //登录成功 { Payload payload = new Payload() { Account = account, Exp = DateTime.Now.AddDays(7), Issuer = "IServer", IMEI = "0000" }; //创建一个token string token = JwtUtils.EncodingToken(payload); Cache.AddCache(token, payload, payload.Exp); return(Content(token)); } loginResult = new LoginResult() { Message = "用户名密码错误", Status = false, ResultCode = ResultCode.Error }; return(Json(loginResult)); }
protected override void AssertSignature(string tokenData, string signature) { var tokenDataBytes = Encoding.UTF8.GetBytes(tokenData); var signatureBytes = JwtUtils.Base64DecodeToBytes(signature); var verified = this.rsa.VerifyData( tokenDataBytes, signatureBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); Assert.True(verified); }
public IActionResult TerminateSession(string authToken) { if (CheckJwtValidity(authToken)) { JwtUtils.InvalidateJWT(authToken); return(Ok()); } else { return(Unauthorized()); } }
public JsonResult login(string userId, string userPwd) { string token = ""; string loginName = ""; int loginType = 0; string loginUserId = ""; string loginMsg = ""; string title = ""; //要判斷校長及主管 的簽核權限 Dictionary <string, dynamic> result = service.loginCheck(userId, userPwd); if (result["status"].ToString() == "success" || result["status"].ToString() == "warn") { VwLoginInfo vwLoginInfo = result["loginInfo"]; title = vwLoginInfo.title; optEventRecord(vwLoginInfo.userId, vwLoginInfo.account, "使用者:" + vwLoginInfo.name + "(" + vwLoginInfo.account + "), 登入"); try{ token = new JwtUtils().EnCodeJwt(vwLoginInfo); }catch (Exception e) { logger.Error(e, e.Message); } loginName = vwLoginInfo.name + "(" + vwLoginInfo.school + ")"; loginType = vwLoginInfo.loginType; loginUserId = vwLoginInfo.userId; if (loginType.ToString() == "3" || loginType.ToString() == "4") { loginMsg = new DrugsNoticeService().getLoginMsgByAdmin(loginType.ToString(), userId.ToString()); } else { loginMsg = new DrugsNoticeService().getLoginMsg(userId.ToString()); } } string login_type = service.qryLoginAuth(userId); LoginAuthEnable model = getLoginAuthEnable(login_type, title); string jsonStr = ""; if (!object.ReferenceEquals(model, null)) { jsonStr = JsonConvert.SerializeObject(model); } return(Json(new { status = result["status"].ToString(), msg = result["msg"].ToString(), token = token, loginName = loginName, loginType = loginType, loginMsg = loginMsg, auth = jsonStr })); }
public async Task <IActionResult> RegisterCertificateCallback([FromBody] SmartCardAuthorizationResponse smartCardAuthorizationResponse) { var sub = HttpContext.User.Claims.FirstOrDefault(x => x.Type == "sub")?.Value; if (string.IsNullOrEmpty(sub)) { return(Json(new { success = false })); } var user = await _users.FindByIdAsync(sub); if (smartCardAuthorizationResponse == null || string.IsNullOrEmpty(smartCardAuthorizationResponse.Certificate) || string.IsNullOrEmpty(smartCardAuthorizationResponse.Token)) { return(Json(new { success = false })); } var certificate = CertificateUtilities.GetAndValidateCertificate(smartCardAuthorizationResponse.Certificate); if (certificate == null) { return(Json(new { success = false })); } if (_authContext.UserCertificates.FirstOrDefault(x => x.Thumbprint == certificate.Thumbprint) != null) { return(Json(new { success = false })); } var payload = HttpContext.Session.GetString("certificateRegister.challenge"); var verifyResult = JwtUtils.ValidateJWT( certificate, smartCardAuthorizationResponse.Token, smartCardAuthorizationResponse.Algorithm, payload); if (verifyResult) { var dbuser = _authContext.Users.First(u => u.Id == user.Id); var userCert = new UserCertificate() { Certificate = Convert.ToBase64String(certificate.RawData), Thumbprint = certificate.Thumbprint, User = dbuser, RegistrationDate = DateTime.Now, Subject = certificate.Subject }; _authContext.UserCertificates.Add(userCert); _authContext.SaveChanges(); return(Json(new { success = true })); } return(Json(new { success = false })); }
public async Task <string> CreateTokenAsync( IDictionary <string, object> headerOverrides = null, IDictionary <string, object> payloadOverrides = null) { var header = new Dictionary <string, object>() { { "alg", "RS256" }, { "typ", "jwt" }, { "kid", "test-key-id" }, }; if (headerOverrides != null) { foreach (var entry in headerOverrides) { header[entry.Key] = entry.Value; } } var uid = this.Uid.ThrowIfNullOrEmpty(nameof(this.Uid)); var issuerPrefix = this.IssuerPrefix.ThrowIfNullOrEmpty(nameof(this.IssuerPrefix)); var projectId = this.ProjectId.ThrowIfNullOrEmpty(nameof(this.ProjectId)); var clock = this.Clock.ThrowIfNull(nameof(this.Clock)); var payload = new Dictionary <string, object>() { { "sub", uid }, { "iss", $"{issuerPrefix}/{projectId}" }, { "aud", projectId }, { "iat", clock.UnixTimestamp() - (60 * 10) }, { "exp", clock.UnixTimestamp() + (60 * 50) }, }; if (this.TenantId != null) { payload["firebase"] = new Dictionary <string, object> { { "tenant", this.TenantId }, }; } if (payloadOverrides != null) { foreach (var entry in payloadOverrides) { payload[entry.Key] = entry.Value; } } var signer = this.Signer.ThrowIfNull(nameof(this.Signer)); return(await JwtUtils.CreateSignedJwtAsync(header, payload, signer)); }