|
@@ -52,7 +52,8 @@ func (rm *ResumeManager) GenerateToken(client *Client) (token string) {
|
52
|
52
|
}
|
53
|
53
|
|
54
|
54
|
// VerifyToken looks up the client corresponding to a resume token, returning
|
55
|
|
-// nil if there is no such client or the token is invalid.
|
|
55
|
+// nil if there is no such client or the token is invalid. If successful,
|
|
56
|
+// the token is consumed and cannot be used to resume again.
|
56
|
57
|
func (rm *ResumeManager) VerifyToken(token string) (client *Client) {
|
57
|
58
|
if len(token) != 2*utils.SecretTokenLength {
|
58
|
59
|
return
|
|
@@ -68,6 +69,8 @@ func (rm *ResumeManager) VerifyToken(token string) (client *Client) {
|
68
|
69
|
// disallow resume of an unregistered client; this prevents the use of
|
69
|
70
|
// resume as an auth bypass
|
70
|
71
|
if pair.client.Registered() {
|
|
72
|
+ // consume the token, ensuring that at most one resume can succeed
|
|
73
|
+ delete(rm.resumeIDtoCreds, id)
|
71
|
74
|
return pair.client
|
72
|
75
|
}
|
73
|
76
|
}
|