| 68 | } |
| 69 | |
| 70 | func (p ResumeTokenKeyProvider) GenerateResumeToken(ctx context.Context, peerID uuid.UUID) (*proto.RefreshResumeTokenResponse, error) { |
| 71 | exp := p.clock.Now().Add(p.expiry) |
| 72 | payload := jwtutils.RegisteredClaims{ |
| 73 | Subject: peerID.String(), |
| 74 | Expiry: jwt.NewNumericDate(exp), |
| 75 | } |
| 76 | |
| 77 | token, err := jwtutils.Sign(ctx, p.key, payload) |
| 78 | if err != nil { |
| 79 | return nil, xerrors.Errorf("sign payload: %w", err) |
| 80 | } |
| 81 | |
| 82 | return &proto.RefreshResumeTokenResponse{ |
| 83 | Token: token, |
| 84 | RefreshIn: durationpb.New(p.expiry / 2), |
| 85 | ExpiresAt: timestamppb.New(exp), |
| 86 | }, nil |
| 87 | } |
| 88 | |
| 89 | // VerifyResumeToken parses a signed tailnet resume token with the given key and |
| 90 | // returns the payload. If the token is invalid or expired, an error is |