Skip to content

Commit

Permalink
Added complete documentation for VAPID Configurations
Browse files Browse the repository at this point in the history
  • Loading branch information
dimitribouniol committed Dec 14, 2024
1 parent 91d0cd1 commit 4a51c35
Showing 1 changed file with 64 additions and 4 deletions.
68 changes: 64 additions & 4 deletions Sources/WebPush/VAPID/VAPIDConfiguration.swift
Original file line number Diff line number Diff line change
@@ -9,19 +9,62 @@
import Foundation

extension VoluntaryApplicationServerIdentification {
/// A configuration object specifying the contact information along with the keys that your application server identifies itself with.
///
/// The ``primaryKey``, when priovided, will always be used for new subscriptions when ``WebPushManager/nextVAPIDKeyID`` is called. If omitted, one of the keys in ``keys`` will be randomely chosen instead.
///
/// ``deprecatedKeys`` that you must stull support for older subscribers, but don't wish to use when registering new subscribers, may also be specified.
///
/// To reduce implementation complexity, it is recommended to only use a single ``primaryKey``, though this key should be stored with subscribers as ``Subscriber`` encourages you to do so that you can deprecate it in the future should it ever leak.
///
/// ## Codable
///
/// VAPID configurations should ideally be generated a single time and shared across all instances of your application server, across runs. To facilitate this, you can encode and decode a configuration to load it at runtime rather than instanciate a new one every time:
/// ```swift
/// // TODO: Load this data from .env or from file system
/// let configurationData = Data(#" {"contactInformation":"https://example.com","expirationDuration":79200,"primaryKey":"6PSSAJiMj7uOvtE4ymNo5GWcZbT226c5KlV6c+8fx5g=","validityDuration":72000} "#.utf8)
/// let vapidConfiguration = try JSONDecoder().decode(VAPID.Configuration.self, from: configurationData)
/// ```
///
/// - SeeAlso: [Generating Keys](https://github.com/mochidev/swift-webpush?tab=readme-ov-file#generating-keys): Keys can also be generated by our `vapid-key-generator` helper tool.
public struct Configuration: Hashable, Sendable {
/// The VAPID key that identifies the push service to subscribers.
///
/// This key should be shared by all instances of your push service, and should be kept secure. Rotating this key is not recommended as you'll lose access to subscribers that registered against it.
///
/// Some implementations will choose to use different keys per subscriber. In that case, choose to provide a set of keys instead.
/// If not provided, a key from ``keys`` will be used instead.
/// - SeeAlso: ``VoluntaryApplicationServerIdentification/Configuration``
public private(set) var primaryKey: Key?

/// The set of valid keys to choose from when identifying the applications erver to new registrations.
public private(set) var keys: Set<Key>

/// The set of deprecated keys to continue to support when signing push messages, but shouldn't be used for new registrations.
///
/// This set can be interogated via ``WebPushManager/`` to determine if a subscriber should be re-registered against a new key or not:
/// ```swift
/// webPushManager.keyStatus(for: subscriber.vapidKeyID) == .deprecated
/// ```
public private(set) var deprecatedKeys: Set<Key>?

/// The contact information an administrator of a push service may use to contact you in the case of an issue.
public var contactInformation: ContactInformation

/// The number of seconds before a cached authentication header signed by this configuration fully expires.
///
/// This value must be 24 hours or less, and it conservatively set to 22 hours by default to account for clock drift between your applications erver and push services.
public var expirationDuration: Duration

/// The number of seconds before a cached authentication header signed by this configuration is renewed.
///
/// This valus must be less than ``expirationDuration``, and is set to 20 hours by default as an adequate compromise between re-usability and key over-use.
public var validityDuration: Duration

/// Initialize a configuration with a single primary key.
/// - Parameters:
/// - key: The primary key to use when introducing your application server during registration.
/// - deprecatedKeys: Suppoted, but deprecated, keys to use during push delivery if a subscriber requires them.
/// - contactInformation: The contact information an administrator of a push service may use to contact you in the case of an issue.
/// - expirationDuration: The number of seconds before a cached authentication header signed by this configuration fully expires.
/// - validityDuration: The number of seconds before a cached authentication header signed by this configuration is renewed.
public init(
key: Key,
deprecatedKeys: Set<Key>? = nil,
@@ -39,6 +82,16 @@ extension VoluntaryApplicationServerIdentification {
self.validityDuration = validityDuration
}

/// Initialize a configuration with a multiple VAPID keys.
///
/// Use this initializer _only_ if you wish to implement more complicated key rotation if you believe keys may be leaked at a higher rate than usual. In all other cases, it is highly recommended to use ``init(key:deprecatedKeys:contactInformation:expirationDuration:validityDuration:)`` instead to supply a singly primary key and keep it secure.
/// - Parameters:
/// - primaryKey: The optional primary key to use when introducing your application server during registration.
/// - keys: The set of valid keys to choose from when identifying the applications erver to new registrations.
/// - deprecatedKeys: Suppoted, but deprecated, keys to use during push delivery if a subscriber requires them.
/// - contactInformation: The contact information an administrator of a push service may use to contact you in the case of an issue.
/// - expirationDuration: The number of seconds before a cached authentication header signed by this configuration fully expires.
/// - validityDuration: The number of seconds before a cached authentication header signed by this configuration is renewed.
public init(
primaryKey: Key?,
keys: Set<Key>,
@@ -64,7 +117,14 @@ extension VoluntaryApplicationServerIdentification {
self.validityDuration = validityDuration
}

mutating func updateKeys(
/// Update the keys that this configuration represents.
///
/// At least one non-deprecated key must be specified, whether it is a primary key or specified in the list of keys, or this method will throw.
/// - Parameters:
/// - primaryKey: The primary key to use when registering a new subscriber.
/// - keys: A list of valid, non deprecated keys to cycle through if a primary key is not specified.
/// - deprecatedKeys: A list of deprecated keys to use for signing if a subscriber requires it, but won't be used for new registrations.
public mutating func updateKeys(
primaryKey: Key?,
keys: Set<Key>,
deprecatedKeys: Set<Key>? = nil

0 comments on commit 4a51c35

Please sign in to comment.