From 48bc25c0f068c4bd0d823100253dc720a0697a1f Mon Sep 17 00:00:00 2001 From: Dimitri Bouniol Date: Tue, 17 Dec 2024 00:33:18 -0800 Subject: [PATCH] Added more docs to internal types --- README.md | 6 ++++- Sources/WebPush/VAPID/VAPIDKey.swift | 6 ++++- Sources/WebPush/VAPID/VAPIDToken.swift | 37 +++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index aa492e1..44397b1 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Please check the [releases](https://github.com/mochidev/swift-webpush/releases) ```swift dependencies: [ .package( - url: "https://github.com/mochidev/swift-webPush.git", + url: "https://github.com/mochidev/swift-webpush.git", .upToNextMinor(from: "0.2.1") ), ], @@ -180,11 +180,15 @@ The `WebPushTesting` module can be used to obtain a mocked `WebPushManager` inst ## Specifications +- [RFC 7515 JSON Web Signature (JWS)](https://datatracker.ietf.org/doc/html/rfc7515) +- [RFC 7519 JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519) - [RFC 8030 Generic Event Delivery Using HTTP Push](https://datatracker.ietf.org/doc/html/rfc8030) - [RFC 8188 Encrypted Content-Encoding for HTTP](https://datatracker.ietf.org/doc/html/rfc8188) - [RFC 8291 Message Encryption for Web Push](https://datatracker.ietf.org/doc/html/rfc8291) - [RFC 8292 Voluntary Application Server Identification (VAPID) for Web Push](https://datatracker.ietf.org/doc/html/rfc8292) +- [Push API Working Draft](https://www.w3.org/TR/push-api/) + ## Contributing Contribution is welcome! Please take a look at the issues already available, or start a new discussion to propose a new feature. Although guarantees can't be made regarding feature requests, PRs that fit within the goals of the project and that have been discussed beforehand are more than welcome! diff --git a/Sources/WebPush/VAPID/VAPIDKey.swift b/Sources/WebPush/VAPID/VAPIDKey.swift index 6f2e07c..6858719 100644 --- a/Sources/WebPush/VAPID/VAPIDKey.swift +++ b/Sources/WebPush/VAPID/VAPIDKey.swift @@ -66,7 +66,7 @@ extension VAPID.Key: Identifiable { /// /// This value can be shared as is with a subscription registration as the `applicationServerKey` key in JavaScript. /// - /// - SeeAlso: [Push API Working Draft §7.2. PushSubscriptionOptions Interface](https://www.w3.org/TR/push-api/#pushsubscriptionoptions-interface) + /// - SeeAlso: [Push API Working Draft §7.2. `PushSubscriptionOptions` Interface](https://www.w3.org/TR/push-api/#pushsubscriptionoptions-interface) public struct ID: Hashable, Comparable, Codable, Sendable, CustomStringConvertible { private var rawValue: String @@ -93,6 +93,10 @@ extension VAPID.Key: Identifiable { } } + /// The public key component in a format suitable for user agents to consume. + /// + /// - SeeAlso: [Push API Working Draft §7.2. `PushSubscriptionOptions` Interface](https://www.w3.org/TR/push-api/#dom-pushsubscriptionoptions-applicationserverkey) + /// - SeeAlso: [RFC 8292 Voluntary Application Server Identification (VAPID) for Web Push §3.2. Public Key Parameter ("k")](https://datatracker.ietf.org/doc/html/rfc8292#section-3.2) public var id: ID { ID(privateKey.publicKey.x963Representation.base64URLEncodedString()) } diff --git a/Sources/WebPush/VAPID/VAPIDToken.swift b/Sources/WebPush/VAPID/VAPIDToken.swift index fd94864..ac0fbae 100644 --- a/Sources/WebPush/VAPID/VAPIDToken.swift +++ b/Sources/WebPush/VAPID/VAPIDToken.swift @@ -13,6 +13,8 @@ extension VAPID { /// An internal representation the token and authorization headers used self-identification. /// /// - SeeAlso: [RFC 8292 Voluntary Application Server Identification (VAPID) for Web Push §2. Application Server Self-Identification](https://datatracker.ietf.org/doc/html/rfc8292#section-2) + /// - SeeAlso: [RFC 7515 JSON Web Signature (JWS)](https://datatracker.ietf.org/doc/html/rfc7515) + ///- SeeAlso: [RFC 7519 JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519) struct Token: Hashable, Codable, Sendable { enum CodingKeys: String, CodingKey { case audience = "aud" @@ -20,15 +22,34 @@ extension VAPID { case expiration = "exp" } + /// The audience claim, which encodes the origin of the ``Subscriber/endpoint`` + /// + /// - SeeAlso: ``/Foundation/URL/origin`` + /// - SeeAlso: [RFC 7519 JSON Web Token (JWT) §4.1.3. "aud" (Audience) Claim](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3) + /// - SeeAlso: [RFC 8292 Voluntary Application Server Identification (VAPID) for Web Push §2. Application Server Self-Identification](https://datatracker.ietf.org/doc/html/rfc8292#section-2) var audience: String - var subject: VAPID.Configuration.ContactInformation + + /// The subject claim, which encodes contact information for the application server. + /// + /// - SeeAlso: [RFC 7519 JSON Web Token (JWT) §4.1.2. "sub" (Subject) Claim](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2) + /// - SeeAlso: [RFC 8292 Voluntary Application Server Identification (VAPID) for Web Push §2.1. Application Server Contact Information](https://datatracker.ietf.org/doc/html/rfc8292#section-2.1) + var subject: Configuration.ContactInformation + + /// The expiry claim, which encodes the number of seconds after 1970/01/01 when the token expires. + /// + /// - SeeAlso: [RFC 7519 JSON Web Token (JWT) §4.1.4. "exp" (Expiration Time) Claim](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4) + /// - SeeAlso: [RFC 8292 Voluntary Application Server Identification (VAPID) for Web Push §2. Application Server Self-Identification](https://datatracker.ietf.org/doc/html/rfc8292#section-2) var expiration: Int + /// The standard header including the type and algorithm. + /// + /// - SeeAlso: [RFC 8292 Voluntary Application Server Identification (VAPID) for Web Push §2. Application Server Self-Identification](https://datatracker.ietf.org/doc/html/rfc8292#section-2) static let jwtHeader = Array(#"{"typ":"JWT","alg":"ES256"}"#.utf8).base64URLEncodedString() + /// Initialize a token with the specified claims. init( origin: String, - contactInformation: VAPID.Configuration.ContactInformation, + contactInformation: Configuration.ContactInformation, expiration: Date ) { self.audience = origin @@ -36,16 +57,18 @@ extension VAPID { self.expiration = Int(expiration.timeIntervalSince1970) } + /// Initialize a token with the specified claims. init( origin: String, - contactInformation: VAPID.Configuration.ContactInformation, - expiresIn: VAPID.Configuration.Duration + contactInformation: Configuration.ContactInformation, + expiresIn: Configuration.Duration ) { audience = origin subject = contactInformation expiration = Int(Date.now.timeIntervalSince1970) + expiresIn.seconds } + /// Initialize a token from a VAPID `Authorization` header's values. init?(token: String, key: String) { let components = token.split(separator: ".") @@ -69,6 +92,7 @@ extension VAPID { self = token } + /// - SeeAlso: [RFC 7515 JSON Web Signature (JWS) §3. JSON Web Signature (JWS) Overview](https://datatracker.ietf.org/doc/html/rfc7515#section-3) func generateJWT(signedBy signingKey: some VAPIDKeyProtocol) throws -> String { let header = Self.jwtHeader @@ -81,6 +105,9 @@ extension VAPID { return "\(message).\(signature)" } + /// Generate an `Authorization` header. + /// + /// - SeeAlso: [RFC 8292 Voluntary Application Server Identification (VAPID) for Web Push §3. VAPID Authentication Scheme](https://datatracker.ietf.org/doc/html/rfc8292#section-3) func generateAuthorization(signedBy signingKey: some VAPIDKeyProtocol) throws -> String { let token = try generateJWT(signedBy: signingKey) let key = signingKey.id @@ -93,5 +120,7 @@ extension VAPID { protocol VAPIDKeyProtocol: Identifiable, Sendable { associatedtype Signature: ContiguousBytes + /// Returns a JWS signature for the message. + /// - SeeAlso: [RFC 7515 JSON Web Signature (JWS)](https://datatracker.ietf.org/doc/html/rfc7515) func signature(for message: some DataProtocol) throws -> Signature }