internal static byte[] EncodeToken(GitHubTokenData token) { using (var stream = new MemoryStream()) using (var writer = new BinaryWriter(stream)) { writer.Write(token.UserId); writer.Write(token.TokenId); writer.Write(token.Expiration.Ticks); writer.Write(token.AccessToken); writer.Flush(); return(stream.ToArray()); } }
private bool TryDecodeToken(string protectedToken, out GitHubTokenData token) { Span <byte> tokenBytes = stackalloc byte[1024]; if (!Convert.TryFromBase64String(protectedToken, tokenBytes, out int bytesWritten)) { token = default; return(false); } // DataProtector can't handle spans, so we have to copy out the value var toUnprotect = new byte[bytesWritten]; tokenBytes.Slice(0, bytesWritten).CopyTo(toUnprotect.AsSpan()); byte[] unprotected; try { unprotected = _dataProtector.Unprotect(toUnprotect); } catch (Exception e) { Logger.LogWarning("IDataProtector.Unprotect exception: {exception}", e); token = default; return(false); } if (!GitHubTokenEncoder.TryDecodeToken(unprotected, Logger, out GitHubTokenData candidateToken)) { Logger.LogWarning("Malformed token, aborting"); token = default; return(false); } if (candidateToken.Expiration < DateTimeOffset.UtcNow) { Logger.LogInformation("Expired token used, expired on {expiration}, from user {user}, with id {id}", candidateToken.Expiration, candidateToken.UserId, candidateToken.TokenId); token = default; return(false); } token = candidateToken; return(true); }
internal static bool TryDecodeToken(byte[] encoded, ILogger logger, out GitHubTokenData token) { try { using (MemoryStream stream = new MemoryStream(encoded)) using (BinaryReader reader = new BinaryReader(stream)) { long userId = reader.ReadInt64(); long tokenId = reader.ReadInt64(); var expiration = new DateTimeOffset(reader.ReadInt64(), TimeSpan.Zero); string accessToken = reader.ReadString(); token = new GitHubTokenData(userId, tokenId, expiration, accessToken); } return(true); } catch (Exception e) { logger.LogWarning("Invalid token: {exception}", e); token = default; return(false); } }