Skip to content

Commit 05c1dbb

Browse files
committed
Allow Vapid header to include expiration.
1 parent bdc39fc commit 05c1dbb

File tree

4 files changed

+42
-13
lines changed

4 files changed

+42
-13
lines changed

WebPush.Test/VapidHelperTest.cs

+26-12
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ public void TestGenerateVapidKeysNoCache()
4141
public void TestGetVapidHeaders()
4242
{
4343
var publicKey = TestPublicKey;
44-
var privatekey = TestPrivateKey;
45-
var headers = VapidHelper.GetVapidHeaders(ValidAudience, ValidSubject, publicKey, privatekey);
44+
var privateKey = TestPrivateKey;
45+
var headers = VapidHelper.GetVapidHeaders(ValidAudience, ValidSubject, publicKey, privateKey);
4646

4747
Assert.IsTrue(headers.ContainsKey(@"Authorization"));
4848
Assert.IsTrue(headers.ContainsKey(@"Crypto-Key"));
@@ -52,54 +52,68 @@ public void TestGetVapidHeaders()
5252
public void TestGetVapidHeadersAudienceNotAUrl()
5353
{
5454
var publicKey = TestPublicKey;
55-
var privatekey = TestPrivateKey;
55+
var privateKey = TestPrivateKey;
5656
Assert.ThrowsException<ArgumentException>(
5757
delegate
5858
{
59-
VapidHelper.GetVapidHeaders("invalid audience", ValidSubjectMailto, publicKey, privatekey);
59+
VapidHelper.GetVapidHeaders("invalid audience", ValidSubjectMailto, publicKey, privateKey);
6060
});
6161
}
6262

6363
[TestMethod]
6464
public void TestGetVapidHeadersInvalidPrivateKey()
6565
{
6666
var publicKey = UrlBase64.Encode(new byte[65]);
67-
var privatekey = UrlBase64.Encode(new byte[1]);
67+
var privateKey = UrlBase64.Encode(new byte[1]);
6868

6969
Assert.ThrowsException<ArgumentException>(
70-
delegate { VapidHelper.GetVapidHeaders(ValidAudience, ValidSubject, publicKey, privatekey); });
70+
delegate { VapidHelper.GetVapidHeaders(ValidAudience, ValidSubject, publicKey, privateKey); });
7171
}
7272

7373
[TestMethod]
7474
public void TestGetVapidHeadersInvalidPublicKey()
7575
{
7676
var publicKey = UrlBase64.Encode(new byte[1]);
77-
var privatekey = UrlBase64.Encode(new byte[32]);
77+
var privateKey = UrlBase64.Encode(new byte[32]);
7878

7979
Assert.ThrowsException<ArgumentException>(
80-
delegate { VapidHelper.GetVapidHeaders(ValidAudience, ValidSubject, publicKey, privatekey); });
80+
delegate { VapidHelper.GetVapidHeaders(ValidAudience, ValidSubject, publicKey, privateKey); });
8181
}
8282

8383
[TestMethod]
8484
public void TestGetVapidHeadersSubjectNotAUrlOrMailTo()
8585
{
8686
var publicKey = TestPublicKey;
87-
var privatekey = TestPrivateKey;
87+
var privateKey = TestPrivateKey;
8888

8989
Assert.ThrowsException<ArgumentException>(
90-
delegate { VapidHelper.GetVapidHeaders(ValidAudience, @"invalid subject", publicKey, privatekey); });
90+
delegate { VapidHelper.GetVapidHeaders(ValidAudience, @"invalid subject", publicKey, privateKey); });
9191
}
9292

9393
[TestMethod]
9494
public void TestGetVapidHeadersWithMailToSubject()
9595
{
9696
var publicKey = TestPublicKey;
97-
var privatekey = TestPrivateKey;
97+
var privateKey = TestPrivateKey;
9898
var headers = VapidHelper.GetVapidHeaders(ValidAudience, ValidSubjectMailto, publicKey,
99-
privatekey);
99+
privateKey);
100100

101101
Assert.IsTrue(headers.ContainsKey(@"Authorization"));
102102
Assert.IsTrue(headers.ContainsKey(@"Crypto-Key"));
103103
}
104+
105+
[TestMethod]
106+
public void TestExpirationInPastExceptions()
107+
{
108+
var publicKey = TestPublicKey;
109+
var privateKey = TestPrivateKey;
110+
111+
Assert.ThrowsException<ArgumentException>(
112+
delegate
113+
{
114+
VapidHelper.GetVapidHeaders(ValidAudience, ValidSubjectMailto, publicKey,
115+
privateKey, 1552715607);
116+
});
117+
}
104118
}
105119
}

WebPush/Model/VapidDetails.cs

+2
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,7 @@ public VapidDetails(string subject, string publicKey, string privateKey)
1919
public string Subject { get; set; }
2020
public string PublicKey { get; set; }
2121
public string PrivateKey { get; set; }
22+
23+
public long Expiration { get; set; } = -1;
2224
}
2325
}

WebPush/VapidHelper.cs

+13
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ public static Dictionary<string, string> GetVapidHeaders(string audience, string
4848
{
4949
expiration = UnixTimeNow() + 43200;
5050
}
51+
else
52+
{
53+
ValidateExpiration(expiration);
54+
}
55+
5156

5257
var header = new Dictionary<string, object> {{"typ", "JWT"}, {"alg", "ES256"}};
5358

@@ -136,6 +141,14 @@ public static void ValidatePrivateKey(string privateKey)
136141
}
137142
}
138143

144+
private static void ValidateExpiration(long expiration)
145+
{
146+
if (expiration <= UnixTimeNow())
147+
{
148+
throw new ArgumentException(@"Vapid expiration must be a unix timestamp in the future");
149+
}
150+
}
151+
139152
private static long UnixTimeNow()
140153
{
141154
var timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0);

WebPush/WebPushClient.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ public HttpRequestMessage GenerateRequestDetails(PushSubscription subscription,
230230
var audience = uri.Scheme + @"://" + uri.Host;
231231

232232
var vapidHeaders = VapidHelper.GetVapidHeaders(audience, currentVapidDetails.Subject,
233-
currentVapidDetails.PublicKey, currentVapidDetails.PrivateKey);
233+
currentVapidDetails.PublicKey, currentVapidDetails.PrivateKey, currentVapidDetails.Expiration);
234234
request.Headers.Add(@"Authorization", vapidHeaders["Authorization"]);
235235
if (string.IsNullOrEmpty(cryptoKeyHeader))
236236
{

0 commit comments

Comments
 (0)