Repository: IBM-Swift/Swift-JWT Branch: master Commit: 29fe084d8740 Files: 95 Total size: 1.2 MB Directory structure: gitextract__aylbjyz/ ├── .codebeatignore ├── .gitignore ├── .jazzy.yaml ├── .spi.yml ├── .swift-version ├── .travis.yml ├── LICENSE ├── Package.swift ├── README.md ├── Sources/ │ └── SwiftJWT/ │ ├── BlueECDSA.swift │ ├── BlueHMAC.swift │ ├── BlueRSA.swift │ ├── Claims.swift │ ├── ClaimsExamples/ │ │ ├── ClaimsMicroProfile.swift │ │ ├── ClaimsOpenID.swift │ │ └── ClaimsStandardJWT.swift │ ├── Data+Base64URLEncoded.swift │ ├── Header.swift │ ├── JWT.swift │ ├── JWTDecoder.swift │ ├── JWTEncoder.swift │ ├── JWTError.swift │ ├── JWTSigner.swift │ ├── JWTVerifier.swift │ ├── NoneAlgorithm.swift │ ├── RSAKeyType.swift │ ├── SignerAlgorithm.swift │ ├── ValidateClaimsResult.swift │ └── VerifierAlgorithm.swift ├── SwiftJWT.podspec ├── Tests/ │ ├── LinuxMain.swift │ └── SwiftJWTTests/ │ ├── TestJWT.swift │ ├── cert_private_key │ ├── certificate │ ├── ec384_private_key │ ├── ec384_public_key │ ├── ec512_private_key │ ├── ec512_public_key │ ├── ecdsa_private_key │ ├── ecdsa_public_key │ ├── privateRSA.der │ ├── publicRSA.der │ ├── rsa_private_key │ └── rsa_public_key ├── docs/ │ ├── Classes/ │ │ ├── ClaimsMicroProfile.html │ │ ├── ClaimsOpenID.html │ │ ├── ClaimsStandardJWT.html │ │ ├── JWTDecoder.html │ │ └── JWTEncoder.html │ ├── Classes.html │ ├── Protocols/ │ │ └── Claims.html │ ├── Protocols.html │ ├── Structs/ │ │ ├── AddressClaim.html │ │ ├── Header.html │ │ ├── JWT.html │ │ ├── JWTError.html │ │ ├── JWTSigner.html │ │ ├── JWTVerifier.html │ │ └── ValidateClaimsResult.html │ ├── Structs.html │ ├── css/ │ │ ├── highlight.css │ │ └── jazzy.css │ ├── docsets/ │ │ ├── SwiftJWT.docset/ │ │ │ └── Contents/ │ │ │ ├── Info.plist │ │ │ └── Resources/ │ │ │ ├── Documents/ │ │ │ │ ├── Classes/ │ │ │ │ │ ├── ClaimsMicroProfile.html │ │ │ │ │ ├── ClaimsOpenID.html │ │ │ │ │ ├── ClaimsStandardJWT.html │ │ │ │ │ ├── JWTDecoder.html │ │ │ │ │ └── JWTEncoder.html │ │ │ │ ├── Classes.html │ │ │ │ ├── Protocols/ │ │ │ │ │ └── Claims.html │ │ │ │ ├── Protocols.html │ │ │ │ ├── Structs/ │ │ │ │ │ ├── AddressClaim.html │ │ │ │ │ ├── Header.html │ │ │ │ │ ├── JWT.html │ │ │ │ │ ├── JWTError.html │ │ │ │ │ ├── JWTSigner.html │ │ │ │ │ ├── JWTVerifier.html │ │ │ │ │ └── ValidateClaimsResult.html │ │ │ │ ├── Structs.html │ │ │ │ ├── css/ │ │ │ │ │ ├── highlight.css │ │ │ │ │ └── jazzy.css │ │ │ │ ├── index.html │ │ │ │ ├── js/ │ │ │ │ │ ├── jazzy.js │ │ │ │ │ ├── jazzy.search.js │ │ │ │ │ └── typeahead.jquery.js │ │ │ │ └── search.json │ │ │ └── docSet.dsidx │ │ └── SwiftJWT.tgz │ ├── index.html │ ├── js/ │ │ ├── jazzy.js │ │ ├── jazzy.search.js │ │ └── typeahead.jquery.js │ ├── search.json │ └── undocumented.json └── migration.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .codebeatignore ================================================ docs/** ================================================ FILE: .gitignore ================================================ .build build .vagrant Packages *.pkg SwiftJWT.xcodeproj *.DS_Store Package.resolved .swiftpm ================================================ FILE: .jazzy.yaml ================================================ module: SwiftJWT author: IBM & Kitura Project Contributors github_url: https://github.com/Kitura/Swift-JWT/ theme: fullwidth clean: true exclude: [Packages] readme: README.md skip_undocumented: false hide_documentation_coverage: false ================================================ FILE: .spi.yml ================================================ version: 1 builder: configs: - documentation_targets: [SwiftJWT] scheme: SwiftJWT ================================================ FILE: .swift-version ================================================ 5.1 ================================================ FILE: .travis.yml ================================================ # Travis CI build file. # whitelist (branches that should be built) branches: only: - master - /^issue.*$/ # the matrix of builds should cover each combination of Swift version # and platform that is supported. The version of Swift used is specified # by .swift-version, unless SWIFT_SNAPSHOT is specified. matrix: include: - os: linux dist: xenial sudo: required services: docker env: DOCKER_IMAGE=docker.kitura.net/kitura/swift-ci-ubuntu16.04:5.2.5 SWIFT_TEST_ARGS="" - os: linux dist: bionic sudo: required services: docker env: DOCKER_IMAGE=docker.kitura.net/kitura/swift-ci-ubuntu18.04:5.4 SWIFT_TEST_ARGS="" - os: linux dist: xenial sudo: required services: docker env: DOCKER_IMAGE=docker.kitura.net/kitura/swift-ci-ubuntu18.04:latest USE_SWIFT_DEVELOPMENT_SNAPSHOT=1 SWIFT_TEST_ARGS="" - os: osx osx_image: xcode12.2 sudo: required env: JAZZY_ELIGIBLE=true SWIFT_TEST_ARGS="" - os: osx osx_image: xcode12.5 sudo: required env: SWIFT_TEST_ARGS="" - os: osx osx_image: xcode12.5 sudo: required env: USE_SWIFT_DEVELOPMENT_SNAPSHOT=1 SWIFT_TEST_ARGS="" before_install: - git clone https://github.com/Kitura/Package-Builder.git script: - ./Package-Builder/build-package.sh -projectDir $TRAVIS_BUILD_DIR ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS ================================================ FILE: Package.swift ================================================ // swift-tools-version:5.2 /** * Copyright IBM Corporation and the Kitura project authors 2018-2020 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import PackageDescription let targetDependencies: [Target.Dependency] let package = Package( name: "SwiftJWT", products: [ // Products define the executables and libraries produced by a package, and make them visible to other packages. .library( name: "SwiftJWT", targets: ["SwiftJWT"] ) ], dependencies: [ .package(name: "CryptorRSA", url: "https://github.com/Kitura/BlueRSA.git", from: "1.0.202"), .package(name: "Cryptor", url: "https://github.com/Kitura/BlueCryptor.git", from: "2.0.1"), .package(name: "CryptorECC", url: "https://github.com/Kitura/BlueECC.git", from: "1.2.200"), .package(url: "https://github.com/Kitura/LoggerAPI.git", from: "2.0.0"), .package(url: "https://github.com/Kitura/KituraContracts.git", from: "2.0.1") ], targets: [ .target(name: "SwiftJWT", dependencies: [ "LoggerAPI", "KituraContracts", "CryptorRSA", "Cryptor", "CryptorECC", ]), .testTarget(name: "SwiftJWTTests", dependencies: ["SwiftJWT"]) ] ) ================================================ FILE: README.md ================================================

Kitura

[![](https://img.shields.io/badge/apidoc-SwiftJWT-1FBCE4.svg?style=flat)](https://kitura.github.io/Swift-JWT/index.html) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FKitura%2FSwift-JWT%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/Kitura/Swift-JWT) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FKitura%2FSwift-JWT%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/Kitura/Swift-JWT) # SwiftJWT An implementation of [JSON Web Token](https://tools.ietf.org/html/rfc7519) using Swift. JWTs offer a lightweight and compact format for transmitting information between parties, and the information can be verified and trusted due to JWTs being digitally signed. For more information on JSON Web Tokens, their use cases and how they work, we recommend visiting [jwt.io](https://jwt.io/introduction/). **Reminder:** JWTs sent as JWS do **not** encrypt data, so never send anything sensitive or confidential in a JWT. This library does not currently support JWE. ## Swift version The latest version of Swift-JWT requires **Swift 5.2** or later. You can download this version of the Swift binaries by following this [link](https://swift.org/download/). Compatibility with other Swift versions is not guaranteed. ## Usage ### Swift Package Manager #### Add dependencies Add the `Swift-JWT` package to the dependencies within your application’s `Package.swift` file. Substitute `"x.x.x"` with the latest `Swift-JWT` [release](https://github.com/Kitura/Swift-JWT/releases). ```swift .package(url: "https://github.com/Kitura/Swift-JWT.git", from: "x.x.x") ``` Add `SwiftJWT` to your target's dependencies: ```swift .target(name: "example", dependencies: ["SwiftJWT"]), ``` #### Import package ```swift import SwiftJWT ``` ### Cocoapods To include `Swift-JWT` in a project using CocoaPods, add `SwiftJWT` to your Podfile: ``` pod 'SwiftJWT' ``` ## Getting Started ### The JWT model In its compact form, a JSON Web Tokens consist of three sections of Base64Url encoded JSON, separated by dots (.). These section are: Headers, Claims and the Signature. Therefore, a JWT typically looks like the following: xxxxx.yyyyy.zzzzz #### Header The Header struct contains the fields of the JSON Web Token header as defined by [RFC7515](https://tools.ietf.org/html/rfc7515#section-4). The "typ" header will default to "JWT". The "alg" header will be set to the algorithm name when you sign the JWT. The other Header fields can be set when initializing the Header or by changing them directly on the Header object. ```swift let myHeader = Header(kid: "KeyID1") ``` #### Claims Claims are statements about an entity (typically, the user) and additional data. The Claims are defined by creating a Swift type that conforms to the `Claims` protocol. The fields of this type represent the information that will be shared using the JWT. A list of recommended claims is defined in [RFC7519](https://tools.ietf.org/html/rfc7519#section-4.1). ```swift struct MyClaims: Claims { let iss: String let sub: String let exp: Date let admin: Bool } let myClaims = MyClaims(iss: "Kitura", sub: "John", exp: Date(timeIntervalSinceNow: 3600), admin: true) ``` ##### ClaimsExamples This library includes some example `Claims` structs as defined by their online specifications: - `ClaimsStandardJWT` as defined in [RFC7519](https://tools.ietf.org/html/rfc7519#section-4.1). - `ClaimsMicroProfile` as defined [here](http://microprofile.io/project/eclipse/microprofile-jwt-auth/spec/src/main/asciidoc/interoperability.asciidoc). - `ClaimsOpenID.swift` as defined [here](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). #### JWT The JWT struct represents the `Header` and `Claims` of a JSON Web Token. You can initialize a JWT by decoding a JWT String, or by providing the JWT Header and Claims. ```swift let myJWT = JWT(header: myHeader, claims: myClaims) ``` ### Signing and Verifying JSON web tokens #### Creating public and private keys To sign and verify a JWT using an RSA algorithm, you must provide a public and private key. This could be the contents of a .key file generated via the following Terminal commands: ``` $ ssh-keygen -t rsa -b 4096 -m PEM -f privateKey.key # Don't add a passphrase $ openssl rsa -in privateKey.key -pubout -outform PEM -out privateKey.key.pub ``` This will create a public and private key pair on your system, and the contents of the private key can be passed into a Swift variable using the following code: ```swift let privateKeyPath = URL(fileURLWithPath: getAbsolutePath(relativePath: "/path/to/privateKey.key")) let privateKey: Data = try Data(contentsOf: privateKeyPath, options: .alwaysMapped) let publicKeyPath = URL(fileURLWithPath: getAbsolutePath(relativePath: "/path/to/publicKey.key")) let publicKey: Data = try Data(contentsOf: publicKeyPath, options: .alwaysMapped) ``` For details on creating elliptic curve public and private keys, view the [BlueECC README.txt](https://github.com/Kitura/BlueECC). #### Sign a JWT using a JWTSigner The struct JWTSigner contains the algorithms that can be used to sign a JWT. Initialize a JWTSigner using the static function corresponding to the desired RSA algorithm: ```swift let jwtSigner = JWTSigner.rs256(privateKey: privateKey) ``` To generate a signed JWT string, call the `sign` function on your JWT instance, passing in a JWTSigner: ```swift let signedJWT = try myJWT.sign(using: jwtSigner) ``` The resulting `signedJWT` will be a `String` of the form: ``` .. ``` **Note:** The sign function sets the alg (algorithm) field of the header. #### Verify a JWT using JWTVerifier The struct JWTVerifier contains the algorithms that can be used to verify a JWT. Initialize a JWTVerifier using the static function corresponding to the desired RSA algorithm: ```swift let jwtVerifier = JWTVerifier.rs256(publicKey: publicKey) ``` To verify a signed JWT string, call the static `verify` function, passing in your JWT string and the JWTVerifier: ```swift let verified = JWT.verify(signedJWT, using: jwtVerifier) ``` The `verified` field will be a `bool` that is true if the signature is verified. #### Supported Algorithms The supported algorithms for signing and verifying JWTs are: * RS256 - RSASSA-PKCS1-v1_5 using SHA-256 * RS384 - RSASSA-PKCS1-v1_5 using SHA-384 * RS512 - RSASSA-PKCS1-v1_5 using SHA-512 * HS256 - HMAC using using SHA-256 * HS384 - HMAC using using SHA-384 * HS512 - HMAC using using SHA-512 * ES256 - ECDSA using using SHA-256 and a P-256 curve * ES384 - ECDSA using using SHA-384 and a P-384 curve * ES512 - ECDSA using using SHA-512 and a P-521 curve * PS256 - RSA-PSS using SHA-256 * PS384 - RSA-PSS using SHA-384 * PS512 - RSA-PSS using SHA-512 * none - Don't sign or verify the JWT Note: ECDSA and RSA-PSS algorithms require a minimum Swift version of 4.1. ### Validate claims The `validateClaims` function validates the standard `Date` claims of a JWT instance. The following claims are validated if they are present in the `Claims` object: - exp (expiration date) - nbf (not before date) - iat (issued at date) The method returns `ValidateClaimsResult` - an struct that list the various reasons for validation failure. If the validation succeeds `ValidateClaimsResult.success` is returned. The `leeway` parameter is the `TimeInterval` in seconds that a standard `Date` claim will be valid outside of the specified time. This can be used to account for clock skew between issuers and verifiers. ```swift let validationResult = verified.validateClaims(leeway: 10) if validationResult != .success { print("Claims validation failed: ", validationResult) } ``` ### Decode a JWT from a JWT string A JWT struct can be initialized from a JWT string. If a JWTVerifier is provided it will be used to verify the signature before initialization ```swift let newJWT = try JWT(jwtString: signedJWT, verifier: jwtVerifier) ``` ### JWTEncoder and JWTDecoder The JWTEncoder and JWTDecoder classes encode and decode JWT Strings using the same API as JSONEncoder and JSONDecoder: ```swift let jwtEncoder = JWTEncoder(jwtSigner: jwtSigner) let jwtString = try jwtEncoder.encodeToString(myJWT) let jwtDecoder = JWTDecoder(jwtVerifier: jwtVerifier) let jwt = try jwtDecoder.decode(JWT.self, fromString: jwtString) ``` Because JWTEncoder and JWTDecoder conform to [KituraContract's](https://github.com/Kitura/KituraContracts/blob/master/Sources/KituraContracts/Contracts.swift) BodyEncoder and BodyDecoder protocols, they can be used as a [custom coder](https://developer.ibm.com/swift/2018/09/01/kitura-custom-encoders-and-decoders/) in Codable routes for sending and receiving JWTs: ```swift router.encoders[MediaType(type: .application, subType: "jwt")] = { return jwtEncoder } router.decoders[MediaType(type: .application, subType: "jwt")] = { return jwtDecoder } ``` This allows for the use of JWT's in information exchange. By sending and receiving JWT's you can ensure the sending is who they say they are and verify the content hasn't been tampered with. ## API Documentation For more information visit our [API reference](https://kitura.github.io/Swift-JWT/index.html). ## Community We love to talk server-side Swift, and Kitura. Join our [Slack](http://swift-at-ibm-slack.mybluemix.net/) to meet the team! ## License This library is licensed under Apache 2.0. Full license text is available in [LICENSE](https://github.com/Kitura/Swift-JWT/blob/master/LICENSE). ================================================ FILE: Sources/SwiftJWT/BlueECDSA.swift ================================================ /** * Copyright IBM Corporation 2019 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import CryptorECC import LoggerAPI import Foundation // Class for ECDSA signing using BlueECC @available(OSX 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *) class BlueECSigner: SignerAlgorithm { let name: String = "ECDSA" private let key: Data private let curve: EllipticCurve // Initialize a signer using .utf8 encoded PEM private key. init(key: Data, curve: EllipticCurve) { self.key = key self.curve = curve } // Sign the header and claims to produce a signed JWT String func sign(header: String, claims: String) throws -> String { let unsignedJWT = header + "." + claims guard let unsignedData = unsignedJWT.data(using: .utf8) else { throw JWTError.invalidJWTString } let signature = try sign(unsignedData) let signatureString = JWTEncoder.base64urlEncodedString(data: signature) return header + "." + claims + "." + signatureString } // send utf8 encoded `header.claims` to BlueECC for signing private func sign(_ data: Data) throws -> Data { guard let keyString = String(data: key, encoding: .utf8) else { throw JWTError.invalidPrivateKey } let privateKey = try ECPrivateKey(key: keyString) guard privateKey.curve == curve else { throw JWTError.invalidPrivateKey } let signedData = try data.sign(with: privateKey) return signedData.r + signedData.s } } // Class for ECDSA verifying using BlueECC @available(OSX 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *) class BlueECVerifier: VerifierAlgorithm { let name: String = "ECDSA" private let key: Data private let curve: EllipticCurve // Initialize a verifier using .utf8 encoded PEM public key. init(key: Data, curve: EllipticCurve) { self.key = key self.curve = curve } // Verify a signed JWT String func verify(jwt: String) -> Bool { let components = jwt.components(separatedBy: ".") if components.count == 3 { guard let signature = JWTDecoder.data(base64urlEncoded: components[2]), let jwtData = (components[0] + "." + components[1]).data(using: .utf8) else { return false } return self.verify(signature: signature, for: jwtData) } else { return false } } // Send the base64URLencoded signature and `header.claims` to BlueECC for verification. private func verify(signature: Data, for data: Data) -> Bool { do { guard let keyString = String(data: key, encoding: .utf8) else { return false } let r = signature.subdata(in: 0 ..< signature.count/2) let s = signature.subdata(in: signature.count/2 ..< signature.count) let signature = try ECSignature(r: r, s: s) let publicKey = try ECPublicKey(key: keyString) guard publicKey.curve == curve else { return false } return signature.verify(plaintext: data, using: publicKey) } catch { Log.error("Verification failed: \(error)") return false } } } ================================================ FILE: Sources/SwiftJWT/BlueHMAC.swift ================================================ /** * Copyright IBM Corporation 2017 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Cryptor import LoggerAPI import Foundation class BlueHMAC: SignerAlgorithm, VerifierAlgorithm { let name: String = "HMAC" private let key: Data private let algorithm: HMAC.Algorithm init(key: Data, algorithm: HMAC.Algorithm) { self.key = key self.algorithm = algorithm } func sign(header: String, claims: String) throws -> String { let unsignedJWT = header + "." + claims guard let unsignedData = unsignedJWT.data(using: .utf8) else { throw JWTError.invalidJWTString } let signature = try sign(unsignedData) let signatureString = JWTEncoder.base64urlEncodedString(data: signature) return header + "." + claims + "." + signatureString } func sign(_ data: Data) throws -> Data { guard #available(macOS 10.12, iOS 10.0, *) else { Log.error("macOS 10.12.0 (Sierra) or higher or iOS 10.0 or higher is required by Cryptor") throw JWTError.osVersionToLow } guard let hmac = HMAC(using: algorithm, key: key).update(data: data)?.final() else { throw JWTError.invalidPrivateKey } #if swift(>=5.0) return Data(hmac) #else return Data(bytes: hmac) #endif } func verify(jwt: String) -> Bool { let components = jwt.components(separatedBy: ".") if components.count == 3 { guard let signature = JWTDecoder.data(base64urlEncoded: components[2]), let jwtData = (components[0] + "." + components[1]).data(using: .utf8) else { return false } return self.verify(signature: signature, for: jwtData) } else { return false } } func verify(signature: Data, for data: Data) -> Bool { guard #available(macOS 10.12, iOS 10.0, *) else { return false } do { let expectedHMAC = try sign(data) return expectedHMAC == signature } catch { Log.error("Verification failed: \(error)") return false } } } ================================================ FILE: Sources/SwiftJWT/BlueRSA.swift ================================================ /** * Copyright IBM Corporation 2017 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import CryptorRSA import LoggerAPI import Foundation class BlueRSA: SignerAlgorithm, VerifierAlgorithm { let name: String = "RSA" private let key: Data private let keyType: RSAKeyType private let algorithm: Data.Algorithm private let usePSS: Bool init(key: Data, keyType: RSAKeyType?=nil, algorithm: Data.Algorithm, usePSS: Bool = false) { self.key = key self.keyType = keyType ?? .publicKey self.algorithm = algorithm self.usePSS = usePSS } func sign(header: String, claims: String) throws -> String { let unsignedJWT = header + "." + claims guard let unsignedData = unsignedJWT.data(using: .utf8) else { throw JWTError.invalidJWTString } let signature = try sign(unsignedData) let signatureString = JWTEncoder.base64urlEncodedString(data: signature) return header + "." + claims + "." + signatureString } func sign(_ data: Data) throws -> Data { guard #available(macOS 10.12, iOS 10.3, tvOS 12.0, watchOS 3.3, *) else { Log.error("macOS 10.12.0 (Sierra) or higher or iOS 10.0 or higher is required by CryptorRSA") throw JWTError.osVersionToLow } // Convert PEM format to DER let keyDer: Data if let keyString = String(data: key, encoding: .utf8) { let strippedKey = String(keyString.filter { !" \n\t\r".contains($0) }) let pemComponents = strippedKey.components(separatedBy: "-----") guard pemComponents.count >= 5 else { throw JWTError.missingPEMHeaders } guard let der = Data(base64Encoded: pemComponents[2]) else { throw JWTError.invalidPrivateKey } keyDer = der } else { keyDer = key } let privateKey = try CryptorRSA.createPrivateKey(with: keyDer) let myPlaintext = CryptorRSA.createPlaintext(with: data) guard let signedData = try myPlaintext.signed(with: privateKey, algorithm: algorithm, usePSS: usePSS) else { throw JWTError.invalidPrivateKey } return signedData.data } func verify(jwt: String) -> Bool { let components = jwt.components(separatedBy: ".") if components.count == 3 { guard let signature = JWTDecoder.data(base64urlEncoded: components[2]), let jwtData = (components[0] + "." + components[1]).data(using: .utf8) else { return false } return self.verify(signature: signature, for: jwtData) } else { return false } } func verify(signature: Data, for data: Data) -> Bool { guard #available(macOS 10.12, iOS 10.3, tvOS 12.0, watchOS 3.3, *) else { return false } do { var publicKey: CryptorRSA.PublicKey switch keyType { case .privateKey: return false case .publicKey: // Convert PEM format to DER let keyDer: Data if let keyString = String(data: key, encoding: .utf8) { let strippedKey = String(keyString.filter { !" \n\t\r".contains($0) }) let pemComponents = strippedKey.components(separatedBy: "-----") guard pemComponents.count >= 5 else { return false } guard let der = Data(base64Encoded: pemComponents[2]) else { return false } keyDer = der } else { keyDer = key } publicKey = try CryptorRSA.createPublicKey(with: keyDer) case .certificate: publicKey = try CryptorRSA.createPublicKey(extractingFrom: key) } let myPlaintext = CryptorRSA.createPlaintext(with: data) let signedData = CryptorRSA.createSigned(with: signature) return try myPlaintext.verify(with: publicKey, signature: signedData, algorithm: algorithm, usePSS: usePSS) } catch { Log.error("Verification failed: \(error)") return false } } } ================================================ FILE: Sources/SwiftJWT/Claims.swift ================================================ /** * Copyright IBM Corporation 2018 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation // MARK: Claims /** A protocol for representing the claims on a JSON web token. https://tools.ietf.org/html/rfc7519#section-4.1 ### Usage Example: ### ```swift struct AdminClaims: Claims { var sub: String var isAdmin: Bool var exp: Date? } let jwt = JWT(claims: AdminClaims(sub: "Kitura", isAdmin: true, exp: Date(timeIntervalSinceNow: 3600))) ``` */ public protocol Claims: Codable { /** The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the "exp" claim requires that the current date/time MUST be before the expiration date/time listed in the "exp" claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. */ var exp: Date? { get } /** The "nbf" (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing. The processing of the "nbf" claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the "nbf" claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. */ var nbf: Date? { get } /** The "iat" (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT. */ var iat: Date? { get } /// Encode the Claim object as a Base64 String. func encode() throws -> String } public extension Claims { var exp: Date? { return nil } var nbf: Date? { return nil } var iat: Date? { return nil } func encode() throws -> String { let jsonEncoder = JSONEncoder() jsonEncoder.dateEncodingStrategy = .secondsSince1970 let data = try jsonEncoder.encode(self) return JWTEncoder.base64urlEncodedString(data: data) } } ================================================ FILE: Sources/SwiftJWT/ClaimsExamples/ClaimsMicroProfile.swift ================================================ /** * Copyright IBM Corporation 2018 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation // MARK ClaimsMicroProfile /// A class representing the MicroProfile claims as listed in [MicroProfile specs](http://microprofile.io/project/eclipse/microprofile-jwt-auth/spec/src/main/asciidoc/interoperability.asciidoc). public class ClaimsMicroProfile: Claims { /// Initialize a `ClaimsMicroProfile` public init( iss: String, sub: String, exp: Date, iat: Date, jti: String, upn: String, groups: [String] ) { self.iss = iss self.sub = sub self.exp = exp self.iat = iat self.jti = jti self.upn = upn self.groups = groups } /** The MP-JWT issuer. [RFC7519, Section 4.1.1](https://tools.ietf.org/html/rfc7519#section-4.1.1) */ public var iss: String /** Identifies the principal that is the subject of the JWT. */ public var sub: String /** Identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. */ public var exp: Date /** Identifies the time at which the JWT was issued. */ public var iat: Date /** The "jti" (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object. */ public var jti: String /** This MP-JWT custom claim is the user principal name in the java.security.Principal interface, and is the caller principal name in javax.security.enterprise.identitystore.IdentityStore. If this claim is missing, fallback to the "preferred_username", should be attempted, and if that claim is missing, fallback to the "sub" claim should be used. */ public var upn: String? /** Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace. */ public var preferred_username: String? /** This MP-JWT custom claim is the list of group names that have been assigned to the principal of the MP-JWT. This typically will required a mapping at the application container level to application deployment roles, but a one-to-one between group names and application role names is required to be performed in addition to any other mapping. */ public var groups: [String] } ================================================ FILE: Sources/SwiftJWT/ClaimsExamples/ClaimsOpenID.swift ================================================ /** * Copyright IBM Corporation 2018 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation // MARK ClaimsOpenID /// A class representing OpenID related claims as decsribed in [OpenID specs](http://openid.net/specs/openid-connect-core-1_0.html). public class ClaimsOpenID: Claims { /// Initalise the `ClaimsOpenID` public init( iss: String, sub: String, aud: [String], exp: Date, iat: Date, auth_time: Date? = nil, nonce: String? = nil, acr: String? = nil, amr: [String]? = nil, azp: String? = nil, name: String? = nil, given_name: String? = nil, family_name: String? = nil, middle_name: String? = nil, nickname: String? = nil, preferred_username: String? = nil, profile: String? = nil, picture: String? = nil, website: String? = nil, email: String? = nil, email_verified: Bool? = nil, gender: String? = nil, birthdate: String? = nil, zoneinfo: String? = nil, locale: String? = nil, phone_number: String? = nil, phone_number_verified: Bool? = nil, address: AddressClaim? = nil, updated_at: Date? = nil ) { self.iss = iss self.sub = sub self.aud = aud self.exp = exp self.iat = iat self.auth_time = auth_time self.nonce = nonce self.acr = acr self.amr = amr self.azp = azp self.name = name self.given_name = given_name self.family_name = family_name self.middle_name = middle_name self.nickname = nickname self.preferred_username = preferred_username self.profile = profile self.picture = picture self.website = website self.email = email self.email_verified = email_verified self.gender = gender self.birthdate = birthdate self.zoneinfo = zoneinfo self.locale = locale self.phone_number = phone_number self.phone_number_verified = phone_number_verified self.address = address self.updated_at = updated_at } // MARK: ID Token /// Issuer Identifier for the Issuer of the response. The iss value is a case sensitive URL using the https scheme that contains scheme, host, and optionally, port number and path components and no query or fragment components. public var iss: String /// Subject Identifier. A locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client, e.g., 24400320 or AItOawmwtWwcT0k51BayewNvutrJUqsvl6qs7A4. It MUST NOT exceed 255 ASCII characters in length. The sub value is case sensitive. public var sub: String /// Audience(s) that this ID Token is intended for. It MUST contain the OAuth 2.0 client_id of the Relying Party as an audience value. It MAY also contain identifiers for other audiences. public var aud: [String] /// Expiration time on or after which the ID Token MUST NOT be accepted for processing. The processing of this parameter requires that the current date/time MUST be before the expiration date/time listed in the value. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. public var exp: Date /// Time at which the JWT was issued. public var iat: Date /// Time when the End-User authentication occurred. public var auth_time: Date? /// String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. If present in the ID Token, Clients MUST verify that the nonce Claim Value is equal to the value of the nonce parameter sent in the Authentication Request. If present in the Authentication Request, Authorization Servers MUST include a nonce Claim in the ID Token with the Claim Value being the nonce value sent in the Authentication Request. Authorization Servers SHOULD perform no other processing on nonce values used. public var nonce: String? /// Authentication Context Class Reference. String specifying an Authentication Context Class Reference value that identifies the Authentication Context Class that the authentication performed satisfied. The value "0" indicates the End-User authentication did not meet the requirements of ISO/IEC 29115 level 1. Authentications with level 0 SHOULD NOT be used to authorize access to any resource of any monetary value. Parties using this claim will need to agree upon the meanings of the values used, which may be context-specific. public var acr: String? /// Authentication Methods References. JSON array of strings that are identifiers for authentication methods used in the authentication. For instance, values might indicate that both password and OTP authentication methods were used. Parties using this claim will need to agree upon the meanings of the values used, which may be context-specific. public var amr: [String]? /// Authorized party - the party to which the ID Token was issued. If present, it MUST contain the OAuth 2.0 Client ID of this party. This Claim is only needed when the ID Token has a single audience value and that audience is different than the authorized party. It MAY be included even when the authorized party is the same as the sole audience. public var azp: String? // MARK: Standard Claims /// End-User's full name in displayable form including all name parts, possibly including titles and suffixes, ordered according to the End-User's locale and preferences. public var name: String? /// Given name(s) or first name(s) of the End-User. Note that in some cultures, people can have multiple given names; all can be present, with the names being separated by space characters. public var given_name: String? /// Surname(s) or last name(s) of the End-User. Note that in some cultures, people can have multiple family names or no family name; all can be present, with the names being separated by space characters. public var family_name: String? /// Middle name(s) of the End-User. Note that in some cultures, people can have multiple middle names; all can be present, with the names being separated by space characters. Also note that in some cultures, middle names are not used. public var middle_name: String? /// Casual name of the End-User that may or may not be the same as the given_name. For instance, a nickname value of Mike might be returned alongside a given_name value of Michael. public var nickname: String? /// Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace. public var preferred_username: String? /// URL of the End-User's profile page. The contents of this Web page SHOULD be about the End-User. public var profile: String? /// URL of the End-User's profile picture. This URL MUST refer to an image file (for example, a PNG, JPEG, or GIF image file), rather than to a Web page containing an image. Note that this URL SHOULD specifically reference a profile photo of the End-User suitable for displaying when describing the End-User, rather than an arbitrary photo taken by the End-User. public var picture: String? /// URL of the End-User's Web page or blog. This Web page SHOULD contain information published by the End-User or an organization that the End-User is affiliated with. public var website: String? /// End-User's preferred e-mail address. public var email: String? /// True if the End-User's e-mail address has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this e-mail address was controlled by the End-User at the time the verification was performed. The means by which an e-mail address is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating. public var email_verified: Bool? /// End-User's gender. Values defined by this specification are female and male. Other values MAY be used when neither of the defined values are applicable. public var gender: String? /// End-User's birthday, represented as an ISO 8601:2004 YYYY-MM-DD format. The year MAY be 0000, indicating that it is omitted. To represent only the year, YYYY format is allowed. public var birthdate: String? /// String from zoneinfo time zone database representing the End-User's time zone. For example, Europe/Paris or America/Los_Angeles. public var zoneinfo: String? /// End-User's locale, represented as a BCP47 language tag. This is typically an ISO 639-1 Alpha-2 language code in lowercase and an ISO 3166-1 Alpha-2 country code in uppercase, separated by a dash. For example, en-US or fr-CA. As a compatibility note, some implementations have used an underscore as the separator rather than a dash, for example, en_US; Relying Parties MAY choose to accept this locale syntax as well. public var locale: String? /// End-User's preferred telephone number. E.164 is RECOMMENDED as the format of this Claim, for example, +1 (425) 555-1212 or +56 (2) 687 2400. public var phone_number: String? /// True if the End-User's phone number has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this phone number was controlled by the End-User at the time the verification was performed. The means by which a phone number is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating. When true, the phone_number Claim MUST be in E.164 format and any extensions MUST be represented in RFC 3966 format. public var phone_number_verified: Bool? /// End-User's preferred postal address. public var address: AddressClaim? /// Time the End-User's information was last updated. public var updated_at: Date? } /// Struct representing an AddressClaim as defined in the [OpenID specs](http://openid.net/specs/openid-connect-core-1_0.html). public struct AddressClaim: Codable { /// Full mailing address, formatted for display or use on a mailing label. This field MAY contain multiple lines, separated by newlines. Newlines can be represented either as a carriage return/line feed pair ("\r\n") or as a single line feed character ("\n"). public var formatted: String? /// Full street address component, which MAY include house number, street name, Post Office Box, and multi-line extended street address information. This field MAY contain multiple lines, separated by newlines. Newlines can be represented either as a carriage return/line feed pair ("\r\n") or as a single line feed character ("\n"). public var street_address: String? /// City or locality component. public var locality: String? /// State, province, prefecture, or region component. public var region: String? /// Zip code or postal code component. public var postal_code: String? /// Country name component. public var country: String? } ================================================ FILE: Sources/SwiftJWT/ClaimsExamples/ClaimsStandardJWT.swift ================================================ /** * Copyright IBM Corporation 2018 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation // MARK ClaimsStandardJWT /// A class representing the Standard JWT claims as described in [RFC7519](https://tools.ietf.org/html/rfc7519#section-4.1). public class ClaimsStandardJWT: Claims { /// Initialize a `ClaimsStandardJWT` public init( iss: String? = nil, sub: String? = nil, aud: [String]? = nil, exp: Date? = nil, nbf: Date? = nil, iat: Date? = nil, jti: String? = nil ) { self.iss = iss self.sub = sub self.aud = aud self.exp = exp self.nbf = nbf self.iat = iat self.jti = jti } /** The "iss" (issuer) claim identifies the principal that issued the JWT. The processing of this claim is generally application specific. The "iss" value is a case-sensitive. */ public var iss: String? /** The "sub" (subject) claim identifies the principal that is the subject of the JWT. The claims in a JWT are normally statements about the subject. The subject value MUST either be scoped to be locally unique in the context of the issuer or be globally unique. The processing of this claim is generally application specific. The "sub" value is case-sensitive. */ public var sub: String? /** The "aud" (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the "aud" claim when this claim is present, then the JWT MUST be rejected. The interpretation of audience values is generally application specific. The "aud" value is case-sensitive. */ public var aud: [String]? /** The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the "exp" claim requires that the current date/time MUST be before the expiration date/time listed in the "exp" claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. */ public var exp: Date? /** The "nbf" (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing. The processing of the "nbf" claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the "nbf" claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. */ public var nbf: Date? /** The "iat" (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT. */ public var iat: Date? /** The "jti" (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well. The "jti" claim can be used to prevent the JWT from being replayed. The "jti" value is case- sensitive */ public var jti: String? } ================================================ FILE: Sources/SwiftJWT/Data+Base64URLEncoded.swift ================================================ /** * Copyright IBM Corporation 2017-2019 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation /// Convenience extension for encoding a `Data` as a base64url-encoded `String`. extension JWTEncoder { /// Returns a `String` representation of this data, encoded in base64url format /// as defined in RFC4648 (https://tools.ietf.org/html/rfc4648). /// /// This is the appropriate format for encoding the header and claims of a JWT. public static func base64urlEncodedString(data: Data) -> String { let result = data.base64EncodedString() return result.replacingOccurrences(of: "+", with: "-") .replacingOccurrences(of: "/", with: "_") .replacingOccurrences(of: "=", with: "") } } /// Convenience extension for decoding a `Data` from a base64url-encoded `String`. extension JWTDecoder { /// Initializes a new `Data` from the base64url-encoded `String` provided. The /// base64url encoding is defined in RFC4648 (https://tools.ietf.org/html/rfc4648). /// /// This is appropriate for reading the header or claims portion of a JWT string. public static func data(base64urlEncoded: String) -> Data? { let paddingLength = 4 - base64urlEncoded.count % 4 let padding = (paddingLength < 4) ? String(repeating: "=", count: paddingLength) : "" let base64EncodedString = base64urlEncoded .replacingOccurrences(of: "-", with: "+") .replacingOccurrences(of: "_", with: "/") + padding return Data(base64Encoded: base64EncodedString) } } ================================================ FILE: Sources/SwiftJWT/Header.swift ================================================ /** * Copyright IBM Corporation 2018 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation // MARK: Header /** A representation of a JSON Web Token header. https://tools.ietf.org/html/rfc7515#section-4.1 ### Usage Example: ### ```swift struct MyClaims: Claims { var name: String } let myHeader = Header(kid: "keyID") let jwt = JWT(header: myHeader, claims: MyClaims(name: "Kitura")) ``` */ public struct Header: Codable { /// Type Header Parameter public var typ: String? /// Algorithm Header Parameter public internal(set) var alg: String? /// JSON Web Token Set URL Header Parameter public var jku : String? /// JSON Web Key Header Parameter public var jwk: String? /// Key ID Header Parameter public var kid: String? /// X.509 URL Header Parameter public var x5u: String? /// X.509 Certificate Chain Header Parameter public var x5c: [String]? /// X.509 Certificate SHA-1 Thumbprint Header Parameter public var x5t: String? /// X.509 Certificate SHA-256 Thumbprint Header Parameter public var x5tS256: String? /// Content Type Header Parameter public var cty: String? /// Critical Header Parameter public var crit: [String]? /// Initialize a `Header` instance. /// /// - Parameter typ: The Type Header Parameter /// - Parameter jku: The JSON Web Token Set URL Header Parameter /// - Parameter jwk: The JSON Web Key Header Parameter /// - Parameter kid: The Key ID Header Parameter /// - Parameter x5u: The X.509 URL Header Parameter /// - Parameter x5c: The X.509 Certificate Chain Header Parameter /// - Parameter x5t: The X.509 Certificate SHA-1 Thumbprint Header Parameter /// - Parameter x5tS256: X.509 Certificate SHA-256 Thumbprint Header Parameter /// - Parameter cty: The Content Type Header Parameter /// - Parameter crit: The Critical Header Parameter /// - Returns: A new instance of `Header`. public init( typ: String? = "JWT", jku: String? = nil, jwk: String? = nil, kid: String? = nil, x5u: String? = nil, x5c: [String]? = nil, x5t: String? = nil, x5tS256: String? = nil, cty: String? = nil, crit: [String]? = nil ) { self.typ = typ self.alg = nil self.jku = jku self.jwk = jwk self.kid = kid self.x5u = x5u self.x5c = x5c self.x5t = x5t self.x5tS256 = x5tS256 self.cty = cty self.crit = crit } func encode() throws -> String { let jsonEncoder = JSONEncoder() jsonEncoder.dateEncodingStrategy = .secondsSince1970 let data = try jsonEncoder.encode(self) return JWTEncoder.base64urlEncodedString(data: data) } } ================================================ FILE: Sources/SwiftJWT/JWT.swift ================================================ /** * Copyright IBM Corporation 2017 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation // MARK: JWT /** A struct representing the `Header` and `Claims` of a JSON Web Token. ### Usage Example: ### ```swift struct MyClaims: Claims { var name: String } let jwt = JWT(claims: MyClaims(name: "Kitura")) let key = "".data(using: .utf8)! let signedJWT: String? = try? jwt.sign(using: .rs256(key: key, keyType: .privateKey)) ``` */ public struct JWT: Codable { /// The JWT header. public var header: Header /// The JWT claims public var claims: T /// Initialize a `JWT` instance from a `Header` and `Claims`. /// /// - Parameter header: A JSON Web Token header object. /// - Parameter claims: A JSON Web Token claims object. /// - Returns: A new instance of `JWT`. public init(header: Header = Header(), claims: T) { self.header = header self.claims = claims } /// Initialize a `JWT` instance from a JWT String. /// The signature will be verified using the provided JWTVerifier. /// The time based standard JWT claims will be verified with `validateClaims()`. /// If the string is not a valid JWT, or the verification fails, the initializer returns nil. /// /// - Parameter jwt: A String with the encoded and signed JWT. /// - Parameter verifier: The `JWTVerifier` used to verify the JWT. /// - Returns: An instance of `JWT` if the decoding succeeds. /// - Throws: `JWTError.invalidJWTString` if the provided String is not in the form mandated by the JWT specification. /// - Throws: `JWTError.failedVerification` if the verifier fails to verify the jwtString. /// - Throws: A DecodingError if the JSONDecoder throws an error while decoding the JWT. public init(jwtString: String, verifier: JWTVerifier = .none ) throws { let components = jwtString.components(separatedBy: ".") guard components.count == 2 || components.count == 3, let headerData = JWTDecoder.data(base64urlEncoded: components[0]), let claimsData = JWTDecoder.data(base64urlEncoded: components[1]) else { throw JWTError.invalidJWTString } guard JWT.verify(jwtString, using: verifier) else { throw JWTError.failedVerification } let jsonDecoder = JSONDecoder() jsonDecoder.dateDecodingStrategy = .secondsSince1970 let header = try jsonDecoder.decode(Header.self, from: headerData) let claims = try jsonDecoder.decode(T.self, from: claimsData) self.header = header self.claims = claims } /// Sign the JWT using the given algorithm and encode the header, claims and signature as a JWT String. /// /// - Note: This function will set header.alg field to the name of the signing algorithm. /// /// - Parameter using algorithm: The algorithm to sign with. /// - Returns: A String with the encoded and signed JWT. /// - Throws: An EncodingError if the JSONEncoder throws an error while encoding the JWT. /// - Throws: `JWTError.osVersionToLow` if not using macOS 10.12.0 (Sierra) or iOS 10.0 or higher. /// - Throws: A Signing error if the jwtSigner is unable to sign the JWT with the provided key. public mutating func sign(using jwtSigner: JWTSigner) throws -> String { var tempHeader = header tempHeader.alg = jwtSigner.name let headerString = try tempHeader.encode() let claimsString = try claims.encode() header.alg = tempHeader.alg return try jwtSigner.sign(header: headerString, claims: claimsString) } /// Verify the signature of the encoded JWT using the given algorithm. /// /// - Parameter jwt: A String with the encoded and signed JWT. /// - Parameter using algorithm: The algorithm to verify with. /// - Returns: A Bool indicating whether the verification was successful. public static func verify(_ jwt: String, using jwtVerifier: JWTVerifier) -> Bool { return jwtVerifier.verify(jwt: jwt) } /// Validate the time based standard JWT claims. /// This function checks that the "exp" (expiration time) is in the future /// and the "iat" (issued at) and "nbf" (not before) headers are in the past, /// /// - Parameter leeway: The time in seconds that the JWT can be invalid but still accepted to account for clock differences. /// - Returns: A value of `ValidateClaimsResult`. public func validateClaims(leeway: TimeInterval = 0) -> ValidateClaimsResult { if let expirationDate = claims.exp { if expirationDate + leeway < Date() { return .expired } } if let notBeforeDate = claims.nbf { if notBeforeDate > Date() + leeway { return .notBefore } } if let issuedAtDate = claims.iat { if issuedAtDate > Date() + leeway { return .issuedAt } } return .success } } ================================================ FILE: Sources/SwiftJWT/JWTDecoder.swift ================================================ /** * Copyright IBM Corporation 2018 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation import KituraContracts // MARK: JWTDecoder /** A thread safe decoder that decodes either Data or a JWT String as a `JWT` instance and verifies the signiture using the provided algorithm. ### Usage Example: ### ```swift struct MyClaims: Claims { var name: String } let publicKey = "".data(using: .utf8)! let rsaJWTDecoder = JWTDecoder(jwtVerifier: JWTVerifier.rs256(publicKey: publicKey)) do { let jwt = try rsaJWTDecoder.decode(JWT.self, fromString: exampleJWTString) } catch { print("Failed to decode JWT: \(error)") } ``` */ public class JWTDecoder: BodyDecoder { let keyIDToVerifier: (String) -> JWTVerifier? let jwtVerifier: JWTVerifier? // MARK: Initializers /// Initialize a `JWTDecoder` instance with a single `JWTVerifier`. /// /// - Parameter JWTVerifier: The `JWTVerifier` that will be used to verify the signiture of the JWT. /// - Returns: A new instance of `JWTDecoder`. public init(jwtVerifier: JWTVerifier) { self.keyIDToVerifier = {_ in return jwtVerifier } self.jwtVerifier = jwtVerifier } /// Initialize a `JWTDecoder` instance with a function to generate the `JWTVerifier` from the JWT `kid` header. /// /// - Parameter keyIDToVerifier: The function that will generate the `JWTVerifier` using the "kid" header. /// - Returns: A new instance of `JWTDecoder`. public init(keyIDToVerifier: @escaping (String) -> JWTVerifier?) { self.keyIDToVerifier = keyIDToVerifier self.jwtVerifier = nil } // MARK: Decode /// Decode a `JWT` instance from a JWT String. /// /// - Parameter type: The JWT type the String will be decoded as. /// - Parameter fromString: The JWT String that will be decoded. /// - Returns: A `JWT` instance of the provided type. /// - throws: `JWTError.invalidJWTString` if the provided String is not in the form mandated by the JWT specification. /// - throws: `JWTError.invalidKeyID` if the KeyID `kid` header fails to generate a jwtVerifier. /// - throws: `JWTError.failedVerification` if the `JWTVerifier` fails to verify the decoded String. /// - throws: `DecodingError` if the decoder fails to decode the String as the provided type. public func decode(_ type: T.Type, fromString: String) throws -> T { // Seperate the JWT into the headers and claims. let components = fromString.components(separatedBy: ".") guard components.count > 1, let headerData = JWTDecoder.data(base64urlEncoded: components[0]), let claimsData = JWTDecoder.data(base64urlEncoded: components[1]) else { throw JWTError.invalidJWTString } // Decode the JWT headers and claims data into a _JWTDecoder. let decoder = _JWTDecoder(header: headerData, claims: claimsData) let jwt = try decoder.decode(type) let _jwtVerifier: JWTVerifier // Verify the JWT String using the JWTDecoder constant jwtVerifier. if let jwtVerifier = jwtVerifier { _jwtVerifier = jwtVerifier } else { // The JWTVerifier is generated using the kid Header that was read inside the _JWTDecoder // and then used to verify the JWT. guard let keyID = decoder.keyID, let jwtVerifier = keyIDToVerifier(keyID) else { throw JWTError.invalidKeyID } _jwtVerifier = jwtVerifier } guard _jwtVerifier.verify(jwt: fromString) else { throw JWTError.failedVerification } return jwt } /// Decode a `JWT` instance from a utf8 encoded JWT String. /// /// - Parameter type: The JWT type the Data will be decoded as. /// - Parameter data: The utf8 encoded JWT String that will be decoded. /// - Returns: A `JWT` instance of the provided type. /// - throws: `JWTError.invalidUTF8Data` if the provided Data can't be decoded to a String. /// - throws: `JWTError.invalidJWTString` if the provided String is not in the form mandated by the JWT specification. /// - throws: `JWTError.invalidKeyID` if the KeyID `kid` header fails to generate a `JWTVerifier`. /// - throws: `JWTError.failedVerification` if the `JWTVerifier` fails to verify the decoded String. /// - throws: `DecodingError` if the decoder fails to decode the String as the provided type. public func decode(_ type: T.Type, from data: Data) throws -> T { guard let jwtString = String(data: data, encoding: .utf8) else { throw JWTError.invalidUTF8Data } return try decode(type, fromString: jwtString) } } /* The JWTDecoder creates it's own instance of _JWTDecoder everytime the decode function is called. This is because the _JWTDecoder changes it's own value so we can only have one thread using it at a time. The following is the code generated by codable and called by JWTDecoder.decode(type:, fromString:) for a JWT struct: ``` enum MyStructKeys: String, CodingKey { case header, claims } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: MyStructKeys.self) // defining our (keyed) container let header: Header = try container.decode(Header.self, forKey: .header) // extracting the data let claims: MyClaims = try container.decode(MyClaims.self, forKey: .claims) // extracting the data self.init(header: header, claims: claims) // initializing our struct } ``` Where decoder is a _JWTDecoder instance, and MyClaims is the user defined object conforming to Claims. */ fileprivate class _JWTDecoder: Decoder { init(header: Data, claims: Data) { self.header = header self.claims = claims } var header: Data var claims: Data var keyID: String? var codingPath: [CodingKey] = [] var userInfo: [CodingUserInfoKey : Any] = [:] // Call the Codable Types init from decoder function. public func decode(_ type: T.Type) throws -> T { return try type.init(from: self) } // JWT should only be a Keyed container func container(keyedBy type: Key.Type) throws -> KeyedDecodingContainer { let container = _JWTKeyedDecodingContainer(decoder: self, header: header, claims: claims) return KeyedDecodingContainer(container) } // This function should not be called when decoding a JWT func unkeyedContainer() throws -> UnkeyedDecodingContainer { return UnkeyedContainer(decoder: self) } // This function should not be called when decoding a JWT func singleValueContainer() throws -> SingleValueDecodingContainer { return UnkeyedContainer(decoder: self) } } private struct _JWTKeyedDecodingContainer: KeyedDecodingContainerProtocol { // A reference to the Decoder the container is inside let decoder: _JWTDecoder var header: Data var claims: Data var codingPath: [CodingKey] public var allKeys: [Key] { #if swift(>=4.1) return ["header", "claims"].compactMap { Key(stringValue: $0) } #else return ["header", "claims"].flatMap { Key(stringValue: $0) } #endif } fileprivate init(decoder: _JWTDecoder, header: Data, claims: Data) { self.decoder = decoder self.header = header self.claims = claims self.codingPath = decoder.codingPath } public func contains(_ key: Key) -> Bool { return key.stringValue == "header" || key.stringValue == "claims" } // The JWT Class should only have to decode Decodable types // Those types will be a `Header` object and a generic `Claims` object. func decode(_ type: T.Type, forKey key: Key) throws -> T { decoder.codingPath.append(key) let jsonDecoder = JSONDecoder() jsonDecoder.dateDecodingStrategy = .secondsSince1970 if key.stringValue == "header" { let header = try jsonDecoder.decode(Header.self, from: self.header) decoder.keyID = header.kid guard let decodedHeader = header as? T else { throw DecodingError.typeMismatch(T.self, DecodingError.Context(codingPath: codingPath, debugDescription: "Type of header key was not a JWT Header")) } return decodedHeader } else if key.stringValue == "claims" { return try jsonDecoder.decode(type, from: claims) } else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: codingPath, debugDescription: "value not found for provided key")) } } // No functions beyond this point should be called when decoding JWT, However the functions are required by KeyedDecodingContainerProtocol. func decodeNil(forKey key: Key) throws -> Bool { throw DecodingError.typeMismatch(Key.self, DecodingError.Context(codingPath: codingPath, debugDescription: "JWTDecoder can only Decode JWT tokens")) } func nestedContainer(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer where NestedKey : CodingKey { return try decoder.container(keyedBy: type) } func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer { return try decoder.unkeyedContainer() } func superDecoder() throws -> Decoder { return decoder } func superDecoder(forKey key: Key) throws -> Decoder { return decoder } } // When decoding a JWT you should not have an UnkeyedContainer private struct UnkeyedContainer: UnkeyedDecodingContainer, SingleValueDecodingContainer { var decoder: _JWTDecoder var codingPath: [CodingKey] { return [] } var count: Int? { return nil } var currentIndex: Int { return 0 } var isAtEnd: Bool { return false } func decode(_ type: T.Type) throws -> T { throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath, debugDescription: "JWTDecoder can only Decode JWT tokens")) } func decodeNil() -> Bool { return true } func nestedContainer(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer where NestedKey : CodingKey { return try decoder.container(keyedBy: type) } func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer { return self } func superDecoder() throws -> Decoder { return decoder } } ================================================ FILE: Sources/SwiftJWT/JWTEncoder.swift ================================================ /** * Copyright IBM Corporation 2018 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation import KituraContracts // MARK: JWTEncoder /** A thread safe encoder that signs the JWT header and claims using the provided algorithm and encodes a `JWT` instance as either Data or a JWT String. ### Usage Example: ### ```swift struct MyClaims: Claims { var name: String } var jwt = JWT(claims: MyClaims(name: "John Doe")) let privateKey = "".data(using: .utf8)! let rsaJWTEncoder = JWTEncoder(jwtSigner: JWTSigner.rs256(privateKey: privateKey)) do { let jwtString = try rsaJWTEncoder.encodeToString(jwt) } catch { print("Failed to encode JWT: \(error)") } ``` */ public class JWTEncoder: BodyEncoder { let keyIDToSigner: (String) -> JWTSigner? let jwtSigner: JWTSigner? // MARK: Initializers /// Initialize a `JWTEncoder` instance with a single `JWTSigner`. /// /// - Parameter jwtSigner: The `JWTSigner` that will be used to sign the JWT. /// - Returns: A new instance of `JWTEncoder`. public init(jwtSigner: JWTSigner) { self.keyIDToSigner = {_ in return jwtSigner } self.jwtSigner = jwtSigner } /// Initialize a `JWTEncoder` instance with a function to generate the `JWTSigner` from the JWT `kid` header. /// /// - Parameter keyIDToSigner: The function to generate the `JWTSigner` from the JWT `kid` header. /// - Returns: A new instance of `JWTEncoder`. public init(keyIDToSigner: @escaping (String) -> JWTSigner?) { self.keyIDToSigner = keyIDToSigner self.jwtSigner = nil } // MARK: Encode /// Encode a `JWT` instance into a UTF8 encoded JWT String. /// /// - Parameter value: The JWT instance to be encoded as Data. /// - Returns: The UTF8 encoded JWT String. /// - throws: `JWTError.invalidUTF8Data` if the provided Data can't be decoded to a String. /// - throws: `JWTError.invalidKeyID` if the KeyID `kid` header fails to generate a jwtSigner. /// - throws: `EncodingError` if the encoder fails to encode the object as Data. public func encode(_ value: T) throws -> Data { guard let jwt = try self.encodeToString(value).data(using: .utf8) else { throw JWTError.invalidUTF8Data } return jwt } /// Encode a `JWT` instance as a JWT String. /// /// - Parameter value: The JWT instance to be encoded as a JWT String. /// - Returns: A JWT String. /// - throws: `JWTError.invalidKeyID` if the KeyID `kid` header fails to generate a jwtSigner. /// - throws: `EncodingError` if the encoder fails to encode the object as Data. public func encodeToString(_ value: T) throws -> String { let encoder = _JWTEncoder(jwtSigner: jwtSigner, keyIDToSigner: keyIDToSigner) try value.encode(to: encoder) guard let header = encoder.header, let claims = encoder.claims, let jwtSigner = encoder.jwtSigner else { throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: [], debugDescription: "Failed to sign JWT Header and Claims")) } return try jwtSigner.sign(header: header, claims: claims) } } /* The JWTEncoder creates it's own instance of _JWTEncoder everytime the encode function is called. This is because the _JWTEncoder changes it's own value so we can only have one thread using it at a time. The following is the code generated by codable and called by JWTEncoder.encode() -> String for a JWT struct: ``` enum MyStructKeys: String, CodingKey { case header, claims } extension JWT: Encodable { func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(header, forKey: .header) try container.encode(claims, forKey: .claims) } } ``` Where encoder is a _JWTEncoder instance, and MyClaims is the user defined object conforming to Claims. */ fileprivate class _JWTEncoder: Encoder { init(jwtSigner: JWTSigner?, keyIDToSigner: @escaping (String) -> JWTSigner?) { self.jwtSigner = jwtSigner self.keyIDToSigner = keyIDToSigner } var claims: String? var header: String? var jwtSigner: JWTSigner? let keyIDToSigner: (String) -> JWTSigner? var codingPath: [CodingKey] = [] var userInfo: [CodingUserInfoKey : Any] = [:] // We will be provided a keyed container representing the JWT instance func container(keyedBy type: Key.Type) -> KeyedEncodingContainer { let container = _JWTKeyedEncodingContainer(encoder: self, codingPath: self.codingPath) return KeyedEncodingContainer(container) } private struct _JWTKeyedEncodingContainer: KeyedEncodingContainerProtocol { /// A reference to the encoder we're writing to. let encoder: _JWTEncoder var codingPath: [CodingKey] // Set the Encoder header and claims Strings using the container mutating func encode(_ value: T, forKey key: Key) throws { self.codingPath.append(key) let fieldName = key.stringValue let jsonEncoder = JSONEncoder() jsonEncoder.dateEncodingStrategy = .secondsSince1970 if fieldName == "header" { guard var _header = value as? Header else { throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: [], debugDescription: "Failed to encode into header CodingKey")) } // Set the jwtSigner while you have acces to the keyID if encoder.jwtSigner == nil { guard let keyID = _header.kid, let keyIDJWTSigner = encoder.keyIDToSigner(keyID) else { throw JWTError.invalidKeyID } encoder.jwtSigner = keyIDJWTSigner } _header.alg = encoder.jwtSigner?.name let data = try jsonEncoder.encode(_header) encoder.header = JWTEncoder.base64urlEncodedString(data: data) } else if fieldName == "claims" { let data = try jsonEncoder.encode(value) encoder.claims = JWTEncoder.base64urlEncodedString(data: data) } } // No functions beyond this point should be called for encoding a JWT token mutating func nestedContainer(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer where NestedKey : CodingKey { return encoder.container(keyedBy: keyType) } mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer { return encoder.unkeyedContainer() } mutating func superEncoder() -> Encoder { return encoder } mutating func superEncoder(forKey key: Key) -> Encoder { return encoder } // Throw if trying to encode something other than a JWT token mutating func encodeNil(forKey key: Key) throws { throw EncodingError.invalidValue(key, EncodingError.Context(codingPath: codingPath, debugDescription: "JWTEncoder can only encode JWT tokens")) } } func unkeyedContainer() -> UnkeyedEncodingContainer { return UnkeyedContainer(encoder: self) } func singleValueContainer() -> SingleValueEncodingContainer { return UnkeyedContainer(encoder: self) } // This Decoder should not be used to decode UnkeyedContainer private struct UnkeyedContainer: UnkeyedEncodingContainer, SingleValueEncodingContainer { var encoder: _JWTEncoder var codingPath: [CodingKey] { return [] } var count: Int { return 0 } func nestedContainer(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer where NestedKey : CodingKey { return encoder.container(keyedBy: keyType) } func nestedUnkeyedContainer() -> UnkeyedEncodingContainer { return self } func superEncoder() -> Encoder { return encoder } func encodeNil() throws {} func encode(_ value: T) throws where T : Encodable { throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath, debugDescription: "JWTEncoder can only encode JWT tokens")) } } } ================================================ FILE: Sources/SwiftJWT/JWTError.swift ================================================ /** * Copyright IBM Corporation 2018 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation // MARK: JWTError /// A struct representing the different errors that can be thrown by SwiftJWT public struct JWTError: LocalizedError, Equatable { /// A human readable description of the error. public let errorDescription: String? private let internalError: InternalError private enum InternalError { case invalidJWTString, failedVerification, osVersionToLow, invalidPrivateKey, invalidData, invalidKeyID, missingPEMHeaders } /// Error when an invalid JWT String is provided public static let invalidJWTString = JWTError(errorDescription: "Input was not a valid JWT String", internalError: .invalidJWTString) /// Error when the JWT signiture fails verification. public static let failedVerification = JWTError(errorDescription: "JWT verifier failed to verify the JWT String signiture", internalError: .failedVerification) /// Error when using RSA encryption with an OS version that is too low. public static let osVersionToLow = JWTError(errorDescription: "macOS 10.12.0 (Sierra) or higher or iOS 10.0 or higher is required by CryptorRSA", internalError: .osVersionToLow) /// Error when an invalid private key is provided for RSA encryption. public static let invalidPrivateKey = JWTError(errorDescription: "Provided private key could not be used to sign JWT", internalError: .invalidPrivateKey) /// Error when the provided Data cannot be decoded to a String public static let invalidUTF8Data = JWTError(errorDescription: "Could not decode Data from UTF8 to String", internalError: .invalidData) /// Error when the KeyID field `kid` in the JWT header fails to generate a JWTSigner or JWTVerifier public static let invalidKeyID = JWTError(errorDescription: "The JWT KeyID `kid` header failed to generate a JWTSigner/JWTVerifier", internalError: .invalidKeyID) /// Error when a PEM string is provided without the expected PEM headers/footers. (e.g. -----BEGIN PRIVATE KEY-----) public static let missingPEMHeaders = JWTError(errorDescription: "The provided key did not have the expected PEM headers/footers", internalError: .missingPEMHeaders) /// Function to check if JWTErrors are equal. Required for equatable protocol. public static func == (lhs: JWTError, rhs: JWTError) -> Bool { return lhs.internalError == rhs.internalError } /// Function to enable pattern matching against generic Errors. public static func ~= (lhs: JWTError, rhs: Error) -> Bool { guard let rhs = rhs as? JWTError else { return false } return lhs == rhs } } ================================================ FILE: Sources/SwiftJWT/JWTSigner.swift ================================================ /** * Copyright IBM Corporation 2018 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation // MARK: JWTSigner /** A struct that will be used to sign the JWT `Header` and `Claims` and generate a signed JWT. For RSA and ECDSA, the provided key should be a .utf8 encoded PEM String. ### Usage Example: ### ```swift let pemString = """ -----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw 33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW +jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB AoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS 3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5Cp uGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE 2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0 GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0K Su5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY 6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5 fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523 Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aP FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw== -----END RSA PRIVATE KEY----- """ let privateKey = pemString.data(using: .utf8)! let jwtSigner = JWTSigner.rs256(privateKey: privateKey) struct MyClaims: Claims { var name: String } let jwt = JWT(claims: MyClaims(name: "Kitura")) let signedJWT = try? jwt.sign(using: jwtSigner) ``` */ public struct JWTSigner { /// The name of the algorithm that will be set in the "alg" header let name: String let signerAlgorithm: SignerAlgorithm init(name: String, signerAlgorithm: SignerAlgorithm) { self.name = name self.signerAlgorithm = signerAlgorithm } func sign(header: String, claims: String) throws -> String { return try signerAlgorithm.sign(header: header, claims: claims) } /// Initialize a JWTSigner using the RSA 256 bits algorithm and the provided privateKey. /// - Parameter privateKey: The UTF8 encoded PEM private key, with a "BEGIN RSA PRIVATE KEY" header. public static func rs256(privateKey: Data) -> JWTSigner { return JWTSigner(name: "RS256", signerAlgorithm: BlueRSA(key: privateKey, keyType: .privateKey, algorithm: .sha256)) } /// Initialize a JWTSigner using the RSA 384 bits algorithm and the provided privateKey. /// - Parameter privateKey: The UTF8 encoded PEM private key, with a "BEGIN RSA PRIVATE KEY" header. public static func rs384(privateKey: Data) -> JWTSigner { return JWTSigner(name: "RS384", signerAlgorithm: BlueRSA(key: privateKey, keyType: .privateKey, algorithm: .sha384)) } /// Initialize a JWTSigner using the RSA 512 bits algorithm and the provided privateKey. /// - Parameter privateKey: The UTF8 encoded PEM private key, with a "BEGIN RSA PRIVATE KEY" header. public static func rs512(privateKey: Data) -> JWTSigner { return JWTSigner(name: "RS512", signerAlgorithm: BlueRSA(key: privateKey, keyType: .privateKey, algorithm: .sha512)) } /// Initialize a JWTSigner using the RSA-PSS 256 bits algorithm and the provided privateKey. /// - Parameter privateKey: The UTF8 encoded PEM private key, with a "BEGIN RSA PRIVATE KEY" header. public static func ps256(privateKey: Data) -> JWTSigner { return JWTSigner(name: "PS256", signerAlgorithm: BlueRSA(key: privateKey, keyType: .privateKey, algorithm: .sha256, usePSS: true)) } /// Initialize a JWTSigner using the RSA-PSS 384 bits algorithm and the provided privateKey. /// - Parameter privateKey: The UTF8 encoded PEM private key, with a "BEGIN RSA PRIVATE KEY" header. public static func ps384(privateKey: Data) -> JWTSigner { return JWTSigner(name: "PS384", signerAlgorithm: BlueRSA(key: privateKey, keyType: .privateKey, algorithm: .sha384, usePSS: true)) } /// Initialize a JWTSigner using the RSA-PSS 512 bits algorithm and the provided privateKey. /// This signer requires at least a 2048 bit RSA key. /// - Parameter privateKey: The UTF8 encoded PEM private key, with a "BEGIN RSA PRIVATE KEY" header. public static func ps512(privateKey: Data) -> JWTSigner { return JWTSigner(name: "PS512", signerAlgorithm: BlueRSA(key: privateKey, keyType: .privateKey, algorithm: .sha512, usePSS: true)) } /// Initialize a JWTSigner using the HMAC 256 bits algorithm and the provided privateKey. /// - Parameter key: The HMAC symmetric password data. public static func hs256(key: Data) -> JWTSigner { return JWTSigner(name: "HS256", signerAlgorithm: BlueHMAC(key: key, algorithm: .sha256)) } /// Initialize a JWTSigner using the HMAC 384 bits algorithm and the provided privateKey. /// - Parameter key: The HMAC symmetric password data. public static func hs384(key: Data) -> JWTSigner { return JWTSigner(name: "HS384", signerAlgorithm: BlueHMAC(key: key, algorithm: .sha384)) } /// Initialize a JWTSigner using the HMAC 512 bits algorithm and the provided privateKey. /// - Parameter key: The HMAC symmetric password data. public static func hs512(key: Data) -> JWTSigner { return JWTSigner(name: "HS512", signerAlgorithm: BlueHMAC(key: key, algorithm: .sha512)) } /// Initialize a JWTSigner using the ECDSA SHA256 algorithm and the provided privateKey. /// - Parameter privateKey: The UTF8 encoded PEM private key, with either a "BEGIN EC PRIVATE KEY" or "BEGIN PRIVATE KEY" header. @available(OSX 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *) public static func es256(privateKey: Data) -> JWTSigner { return JWTSigner(name: "ES256", signerAlgorithm: BlueECSigner(key: privateKey, curve: .prime256v1)) } /// Initialize a JWTSigner using the ECDSA SHA384 algorithm and the provided privateKey. /// - Parameter privateKey: The UTF8 encoded PEM private key, with either a "BEGIN EC PRIVATE KEY" or "BEGIN PRIVATE KEY" header. @available(OSX 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *) public static func es384(privateKey: Data) -> JWTSigner { return JWTSigner(name: "ES384", signerAlgorithm: BlueECSigner(key: privateKey, curve: .secp384r1)) } /// Initialize a JWTSigner using the ECDSA SHA512 algorithm and the provided privateKey. /// - Parameter privateKey: The UTF8 encoded PEM private key, with either a "BEGIN EC PRIVATE KEY" or "BEGIN PRIVATE KEY" header. @available(OSX 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *) public static func es512(privateKey: Data) -> JWTSigner { return JWTSigner(name: "ES512", signerAlgorithm: BlueECSigner(key: privateKey, curve: .secp521r1)) } /// Initialize a JWTSigner that will not sign the JWT. This is equivelent to using the "none" alg header. public static let none = JWTSigner(name: "none", signerAlgorithm: NoneAlgorithm()) } ================================================ FILE: Sources/SwiftJWT/JWTVerifier.swift ================================================ /** * Copyright IBM Corporation 2018 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation // MARK: JWTVerifier /** A struct that will be used to verify the signature of a JWT is valid for the provided `Header` and `Claims`. For RSA and ECDSA, the provided key should be a .utf8 encoded PEM String. ### Usage Example: ### ```swift let pemString = """ -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D o2kQ+X5xK9cipRgEKwIDAQAB -----END PUBLIC KEY----- """ let signedJWT = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS2l0dXJhIn0.o2Rv_w1W6qfkldgb6FwzC3tAFEzo7WyYcLyykijCEqDbW8A7TwoFev85KGo_Bi7eNaSgZ6Q8jgkA31r8EDQWtSRg3_o5Zlq-ZCndyVeibgbyM2BMVUGcGzkUD2ikARfnb6GNGHr2waVeFSDehTN8WTLl0mGFxUE6wx5ZugR7My0" struct MyClaims: Claims { var name: String } let jwt = JWT(claims: MyClaims(name: "Kitura")) let publicKey = pemString.data(using: .utf8)! let jwtVerifier = JWTVerifier.rs256(publicKey: publicKey) let verified: Bool = jwt.verify(signedJWT, using: jwtVerifier) ``` */ public struct JWTVerifier { let verifierAlgorithm: VerifierAlgorithm init(verifierAlgorithm: VerifierAlgorithm) { self.verifierAlgorithm = verifierAlgorithm } func verify(jwt: String) -> Bool { return verifierAlgorithm.verify(jwt: jwt) } /// Initialize a JWTVerifier using the RSA 256 bits algorithm and the provided publicKey. /// - Parameter publicKey: The UTF8 encoded PEM public key, with a "BEGIN PUBLIC KEY" header. public static func rs256(publicKey: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueRSA(key: publicKey, keyType: .publicKey, algorithm: .sha256)) } /// Initialize a JWTVerifier using the RSA 384 bits algorithm and the provided publicKey. /// - Parameter publicKey: The UTF8 encoded PEM public key, with a "BEGIN PUBLIC KEY" header. public static func rs384(publicKey: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueRSA(key: publicKey, keyType: .publicKey, algorithm: .sha384)) } /// Initialize a JWTVerifier using the RSA 512 bits algorithm and the provided publicKey. /// - Parameter publicKey: The UTF8 encoded PEM public key, with a "BEGIN PUBLIC KEY" header. public static func rs512(publicKey: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueRSA(key: publicKey, keyType: .publicKey, algorithm: .sha512)) } /// Initialize a JWTVerifier using the RSA 256 bits algorithm and the provided certificate. /// - Parameter publicKey: The UTF8 encoded PEM public key, with a "BEGIN CERTIFICATE" header. public static func rs256(certificate: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueRSA(key: certificate, keyType: .certificate, algorithm: .sha256)) } /// Initialize a JWTVerifier using the RSA 384 bits algorithm and the provided certificate. /// - Parameter publicKey: The UTF8 encoded PEM public key, with a "BEGIN CERTIFICATE" header. public static func rs384(certificate: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueRSA(key: certificate, keyType: .certificate, algorithm: .sha384)) } /// Initialize a JWTVerifier using the RSA 512 bits algorithm and the provided certificate. /// - Parameter publicKey: The UTF8 encoded PEM public key, with a "BEGIN CERTIFICATE" header. public static func rs512(certificate: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueRSA(key: certificate, keyType: .certificate, algorithm: .sha512)) } /// Initialize a JWTVerifier using the RSA-PSS 256 bits algorithm and the provided publicKey. /// - Parameter publicKey: The UTF8 encoded PEM public key, with a "BEGIN PUBLIC KEY" header. public static func ps256(publicKey: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueRSA(key: publicKey, keyType: .publicKey, algorithm: .sha256, usePSS: true)) } /// Initialize a JWTVerifier using the RSA-PSS 384 bits algorithm and the provided publicKey. /// - Parameter publicKey: The UTF8 encoded PEM public key, with a "BEGIN PUBLIC KEY" header. public static func ps384(publicKey: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueRSA(key: publicKey, keyType: .publicKey, algorithm: .sha384, usePSS: true)) } /// Initialize a JWTVerifier using the RSA-PSS 512 bits algorithm and the provided publicKey. /// This verifier requires at least a 2048 bit RSA key. /// - Parameter publicKey: The UTF8 encoded PEM public key, with a "BEGIN PUBLIC KEY" header. public static func ps512(publicKey: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueRSA(key: publicKey, keyType: .publicKey, algorithm: .sha512, usePSS: true)) } /// Initialize a JWTSigner using the HMAC 256 bits algorithm and the provided privateKey. /// - Parameter key: The HMAC symmetric password data. public static func hs256(key: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueHMAC(key: key, algorithm: .sha256)) } /// Initialize a JWTSigner using the HMAC 384 bits algorithm and the provided privateKey. /// - Parameter key: The HMAC symmetric password data. public static func hs384(key: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueHMAC(key: key, algorithm: .sha384)) } /// Initialize a JWTSigner using the HMAC 512 bits algorithm and the provided privateKey. /// - Parameter key: The HMAC symmetric password data. public static func hs512(key: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueHMAC(key: key, algorithm: .sha512)) } /// Initialize a JWTVerifier using the ECDSA SHA 256 algorithm and the provided public key. /// - Parameter publicKey: The UTF8 encoded PEM public key, with a "BEGIN PUBLIC KEY" header. @available(OSX 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *) public static func es256(publicKey: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueECVerifier(key: publicKey, curve: .prime256v1)) } /// Initialize a JWTVerifier using the ECDSA SHA 384 algorithm and the provided public key. /// - Parameter publicKey: The UTF8 encoded PEM public key, with a "BEGIN PUBLIC KEY" header. @available(OSX 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *) public static func es384(publicKey: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueECVerifier(key: publicKey, curve: .secp384r1)) } /// Initialize a JWTVerifier using the ECDSA SHA 512 algorithm and the provided public key. /// - Parameter publicKey: The UTF8 encoded PEM public key, with a "BEGIN PUBLIC KEY" header. @available(OSX 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *) public static func es512(publicKey: Data) -> JWTVerifier { return JWTVerifier(verifierAlgorithm: BlueECVerifier(key: publicKey, curve: .secp521r1)) } /// Initialize a JWTVerifier that will always return true when verifying the JWT. This is equivelent to using the "none" alg header. public static let none = JWTVerifier(verifierAlgorithm: NoneAlgorithm()) } ================================================ FILE: Sources/SwiftJWT/NoneAlgorithm.swift ================================================ /** * Copyright IBM Corporation 2017 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import Foundation /// An EncryptionAlgorithm representing an alg of "none" in a JWT. /// Using this algorithm means the header and claims will not be signed or verified. struct NoneAlgorithm: VerifierAlgorithm, SignerAlgorithm { let name: String = "none" func sign(header: String, claims: String) -> String { return header + "." + claims } func verify(jwt: String) -> Bool { return true } } ================================================ FILE: Sources/SwiftJWT/RSAKeyType.swift ================================================ /** * Copyright IBM Corporation 2017 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ // MARK RSAKeyType /// The type of the key used in the RSA algorithm. enum RSAKeyType { /// The key is a certificate containing both the private and the public keys. case certificate /// The key is an RSA public key. case publicKey /// The key is an RSA private key. case privateKey } ================================================ FILE: Sources/SwiftJWT/SignerAlgorithm.swift ================================================ /** * Copyright IBM Corporation 2018 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ protocol SignerAlgorithm { /// A function to sign the header and claims of a JSON web token and return a signed JWT string. func sign(header: String, claims: String) throws -> String } ================================================ FILE: Sources/SwiftJWT/ValidateClaimsResult.swift ================================================ /** * Copyright IBM Corporation 2017 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ // MARK: ValidateClaimsResult /// ValidateClaimsResult list the possible results of a call to JWT.validateClaims method. /// In case of successful validation, .success is returned, all other cases list various /// problems that may occur during claims validation and indicate that the validation failed. public struct ValidateClaimsResult: CustomStringConvertible, Equatable { /// The human readable description of the ValidateClaimsResult public let description: String /// Successful validation. public static let success = ValidateClaimsResult(description: "Success") /// Invalid Expiration claim. public static let invalidExpiration = ValidateClaimsResult(description: "Invalid Expiration claim") /// Expired token: expiration time claim is in the past. public static let expired = ValidateClaimsResult(description: "Expired token") /// Invalid Not Before claim. public static let invalidNotBefore = ValidateClaimsResult(description: "Invalid Not Before claim") /// Not Before claim is in the future. public static let notBefore = ValidateClaimsResult(description: "Token is not valid yet, Not Before claim is greater than the current time") /// Invalid Issued At claim. public static let invalidIssuedAt = ValidateClaimsResult(description: "Invalid Issued At claim") /// Issued At claim is in the future. public static let issuedAt = ValidateClaimsResult(description: "Issued At claim is greater than the current time") /// Check if two ValidateClaimsResults are equal. Required for the Equatable protocol public static func == (lhs: ValidateClaimsResult, rhs: ValidateClaimsResult) -> Bool { return lhs.description == rhs.description } } ================================================ FILE: Sources/SwiftJWT/VerifierAlgorithm.swift ================================================ /** * Copyright IBM Corporation 2018 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ protocol VerifierAlgorithm { /// A function to verify the signature of a JSON web token string is correct for the header and claims. func verify(jwt: String) -> Bool } ================================================ FILE: SwiftJWT.podspec ================================================ Pod::Spec.new do |s| s.name = "SwiftJWT" s.version = "4.0.1" s.summary = "An implementation of JSON Web Token using Swift." s.homepage = "https://github.com/Kitura/Swift-JWT" s.license = { :type => "Apache License, Version 2.0" } s.authors = 'IBM and the Kitura project authors' s.module_name = 'SwiftJWT' s.swift_version = '5.2' s.osx.deployment_target = "10.13" s.ios.deployment_target = "11.0" s.tvos.deployment_target = "11.0" s.watchos.deployment_target = "4.0" s.source = { :git => "https://github.com/Kitura/Swift-JWT.git", :tag => s.version } s.source_files = "Sources/**/*.swift" s.dependency 'BlueRSA', '~> 1.0.200' s.dependency 'BlueCryptor', '~> 2.0.1' s.dependency 'BlueECC', '~> 1.2.200' s.dependency 'LoggerAPI', '~> 2.0.0' s.dependency 'KituraContracts', '~> 2.0.1' end ================================================ FILE: Tests/LinuxMain.swift ================================================ /** * Copyright IBM Corporation 2017 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ import XCTest @testable import SwiftJWTTests XCTMain([ testCase(TestJWT.allTests), ]) ================================================ FILE: Tests/SwiftJWTTests/TestJWT.swift ================================================ /** Copyright IBM Corporation 2017 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ import XCTest import Foundation @testable import SwiftJWT let rsaPrivateKey = read(fileName: "rsa_private_key") let rsaPublicKey = read(fileName: "rsa_public_key") let rsaDERPrivateKey = read(fileName: "privateRSA.der") let rsaDERPublicKey = read(fileName: "publicRSA.der") let ecdsaPrivateKey = read(fileName: "ecdsa_private_key") let ecdsaPublicKey = read(fileName: "ecdsa_public_key") let ec384PrivateKey = read(fileName: "ec384_private_key") let ec384PublicKey = read(fileName: "ec384_public_key") let ec512PrivateKey = read(fileName: "ec512_private_key") let ec512PublicKey = read(fileName: "ec512_public_key") let rsaJWTEncoder = JWTEncoder(jwtSigner: .rs256(privateKey: rsaPrivateKey)) let rsaJWTDecoder = JWTDecoder(jwtVerifier: .rs256(publicKey: rsaPublicKey)) let certPrivateKey = read(fileName: "cert_private_key") let certificate = read(fileName: "certificate") let rsaEncodedTestClaimJWT = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.pOeiYYHuxBu27llpKrLfHX-tt0Cr41m3hn7d1_CPl7dRMksQRJC5U7AM2CkF8uyObwAKg88orK6eHlOQ0x2C4gDoG7WmgszpthOB6ZUTUPj_FNsn3z4fM8sFx3wON7jtRRSuULH13f-RjLoIFhY_VuqVhla3ybjnfbwjcsd8EqDumdFN6La5D0KugCgvuH51JaEjdHfwXkxkRsynmhv3jCpvRbUbforfEnDjyAImez2hd0Pnb3Vtqr-21z1vFWqqRiz_K-qSiO5NTaO1VbLg7SOYBB9hMAD-_6R2ZZh0JvFP7hycCftRIxTSDd5r0I9sQh9iqurVq03_h0ZjS9BwJQ" let rsaPSSEncodedTestClaimJWT = "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.gytxKF6HsfRI-dmyS0KsVoGquSWHTbosqmgBM_8UnTBZd56ThVdxZSTZzkVE0kS6SZdN7iogLiPqWzvGac0orTkf3XMbxecpHiO8b_BywIqrXhXcz84NFxrq5s8KL_LB8Cs9ro_5xmptp_fNtCedg9leju7VUzrEZP0hyTG_dlar2t7SWY47JD3rlgdaXEfkGgSuDgOO2CzBzqlbP7DUxTQ6OwI8RMNWAxeCalvWTgNQkb1DAy_2JKaga4zDnieUHMd2c_8iSt6SS9dLkxl4nih_2IjHJc73Qcg4Epx5CrhJXWg5CmKoTFDVgpMBGXJRIxT5qpAAx4qvRzlNgJVM2A" let certificateEncodedTestClaimJWT = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJuYW1lIjoiSm9obiBEb2UiLCJhZG1pbiI6dHJ1ZSwic3ViIjoiMTIzNDU2Nzg5MCJ9.CpnzQLuWGfH5Kba36vg0ZZKBnzwlrIgapFVfBfk_nea-eej84ktHZANqIeolskZopRJ4DQ3oaLtHWEg16-ZsujxmkOdiAIbk0-C4QLOVFLZH78WLZAqkyNLS8rFuK9hloLNwz1j6VVUd1f0SOT-wIRzL0_0VRYqQd1bVcCj7wc7BmXENlOfHY7KGHS-6JX-EClT1DygDSoCmdvBExBf3vx0lwMIbP4ryKkyhOoU13ZfSUt1gpP9nZAfzqfRTPxZc_f7neiAlMlF6SzsedsskRCNegW8cg5e_NuVmZZkj0_bnswXFDMmIaxiPdtOEWkmyEOca-EHSwbO5PgCgXOIrgg" // A `TestClaims` encoded using HMAC with "Super Secret Key" from "www.jwt.io" let hmacEncodedTestClaimJWT = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJhZG1pbiI6dHJ1ZSwic3ViIjoiMTIzNDU2Nzg5MCJ9.8kIE0ZCq1Vw7aW1kACpgJLcgY2DpTXgO6P5T3cdCuTs" // A `TestClaims` encoded using es256 with `ecdsaPrivateKey` let ecdsaEncodedTestClaimJWT = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.z1nUPt7mJk5EZBJKrRiCRLSum1B5E5ucaMeuMqxcvnw3a5FnKC-XsR6rvBVdUPRVzWF6L9CHQuSBlDy579SqQA" let jwtSigners: [String: JWTSigner] = ["0": .rs256(privateKey: rsaPrivateKey), "1": .rs256(privateKey: certPrivateKey)] let jwtVerifiers: [String: JWTVerifier] = ["0": .rs256(publicKey: rsaPublicKey), "1": .rs256(certificate: certificate)] let rsaJWTKidEncoder = JWTEncoder(keyIDToSigner: { kid in return jwtSigners[kid]}) let rsaJWTKidDecoder = JWTDecoder(keyIDToVerifier: { kid in return jwtVerifiers[kid]}) struct TestClaims: Claims, Equatable { var name: String? var admin: Bool? var iss: String? var sub: String? var aud: [String]? var exp: Date? var nbf: Date? var iat: Date? var jti: String? init(name: String? = nil) { self.name = name } static func == (lhs: TestClaims, rhs: TestClaims) -> Bool { return lhs.name == rhs.name && lhs.admin == rhs.admin && lhs.iss == rhs.iss && lhs.sub == rhs.sub && lhs.aud ?? [""] == rhs.aud ?? [""] && lhs.exp == rhs.exp && lhs.nbf == rhs.nbf && lhs.iat == rhs.iat && lhs.jti == rhs.jti } } extension Header: Equatable { /// Function to check if two headers are equal. Required to conform to the equatable protocol. public static func == (lhs: Header, rhs: Header) -> Bool { return lhs.alg == rhs.alg && lhs.crit ?? [] == rhs.crit ?? [] && lhs.cty == rhs.cty && lhs.jku == rhs.jku && lhs.jwk == rhs.jwk && lhs.kid == rhs.kid && lhs.typ == rhs.typ && lhs.x5c ?? [] == rhs.x5c ?? [] && lhs.x5t == rhs.x5t && lhs.x5tS256 == rhs.x5tS256 && lhs.x5u == rhs.x5u } } struct MicroProfile: Claims { var name: String? var groups: [String]? var upn: String? var admin: Bool? var iss: String? var sub: String? var aud: [String]? var exp: Date? var nbf: Date? var iat: Date? var jti: String? init(name: String) { self.name = name } } @available(macOS 10.12, iOS 10.0, *) class TestJWT: XCTestCase { static var allTests: [(String, (TestJWT) -> () throws -> Void)] { return [ ("testSignAndVerify", testSignAndVerify), ("testSignAndVerifyRSA", testSignAndVerifyRSA), ("testSignAndVerifyRSAPSS", testSignAndVerifyRSAPSS), ("testSignAndVerifyCert", testSignAndVerifyCert), ("testSignAndVerifyHMAC", testSignAndVerifyHMAC), ("testSignAndVerifyECDSA", testSignAndVerifyECDSA), ("testSignAndVerifyRSA384", testSignAndVerifyRSA384), ("testSignAndVerifyRSAPSS384", testSignAndVerifyRSAPSS384), ("testSignAndVerifyCert384", testSignAndVerifyCert384), ("testSignAndVerifyHMAC384", testSignAndVerifyHMAC384), ("testSignAndVerifyECDSA384", testSignAndVerifyECDSA384), ("testSignAndVerifyRSA512", testSignAndVerifyRSA512), ("testSignAndVerifyRSAPSS512", testSignAndVerifyRSAPSS512), ("testSignAndVerifyCert512", testSignAndVerifyCert512), ("testSignAndVerifyHMAC512", testSignAndVerifyHMAC512), ("testSignAndVerifyECDSA512", testSignAndVerifyECDSA512), ("testJWTEncoder", testJWTEncoder), ("testJWTDecoder", testJWTDecoder), ("testJWTCoderCycle", testJWTCoderCycle), ("testJWTEncoderKeyID", testJWTEncoderKeyID), ("testJWTDecoderKeyID", testJWTDecoderKeyID), ("testJWTCoderCycleKeyID", testJWTCoderCycleKeyID), ("testJWT", testJWT), ("testJWTRSAPSS", testJWTRSAPSS), ("testJWTUsingHMAC", testJWTUsingHMAC), ("testJWTUsingECDSA", testJWTUsingECDSA), ("testMicroProfile", testMicroProfile), ("testValidateClaims", testValidateClaims), ("testValidateClaimsLeeway", testValidateClaimsLeeway), ("testErrorPattenMatching", testErrorPattenMatching), ("testTypeErasedErrorLocalizedDescription", testTypeErasedErrorLocalizedDescription), ] } func testSignAndVerify() { do { try signAndVerify(signer: .none, verifier: .none) } catch { XCTFail("testSignAndVerify failed: \(error)") } } func testSignAndVerifyRSA() { do { try signAndVerify(signer: .rs256(privateKey: rsaPrivateKey), verifier: .rs256(publicKey: rsaPublicKey)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } func testSignAndVerifyRSADERKey() { do { try signAndVerify(signer: .rs256(privateKey: rsaDERPrivateKey), verifier: .rs256(publicKey: rsaDERPublicKey)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } func testSignAndVerifyRSAPSS() { if #available(OSX 10.13, *) { do { try signAndVerify(signer: .ps256(privateKey: rsaPrivateKey), verifier: .ps256(publicKey: rsaPublicKey)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } } func testSignAndVerifyCert() { do { try signAndVerify(signer: .rs256(privateKey: certPrivateKey), verifier: .rs256(certificate: certificate)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } func testSignAndVerifyHMAC() { do { let hmacData = "Super Secret Key".data(using: .utf8)! try signAndVerify(signer: .hs256(key: hmacData), verifier: .hs256(key: hmacData)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } func testSignAndVerifyECDSA() { if #available(OSX 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *) { do { try signAndVerify(signer: .es256(privateKey: ecdsaPrivateKey), verifier: .es256(publicKey: ecdsaPublicKey)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } } func testSignAndVerifyRSA384() { do { try signAndVerify(signer: .rs384(privateKey: rsaPrivateKey), verifier: .rs384(publicKey: rsaPublicKey)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } func testSignAndVerifyRSAPSS384() { if #available(OSX 10.13, *) { do { try signAndVerify(signer: .ps384(privateKey: rsaPrivateKey), verifier: .ps384(publicKey: rsaPublicKey)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } } func testSignAndVerifyCert384() { do { try signAndVerify(signer: .rs384(privateKey: certPrivateKey), verifier: .rs384(certificate: certificate)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } func testSignAndVerifyHMAC384() { do { let hmacData = "Super Secret Key".data(using: .utf8)! try signAndVerify(signer: .hs384(key: hmacData), verifier: .hs384(key: hmacData)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } func testSignAndVerifyECDSA384() { if #available(OSX 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *) { do { try signAndVerify(signer: .es384(privateKey: ec384PrivateKey), verifier: .es384(publicKey: ec384PublicKey)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } } func testSignAndVerifyRSA512() { do { try signAndVerify(signer: .rs512(privateKey: rsaPrivateKey), verifier: .rs512(publicKey: rsaPublicKey)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } func testSignAndVerifyRSAPSS512() { if #available(OSX 10.13, iOS 11, *) { do { try signAndVerify(signer: .ps512(privateKey: rsaPrivateKey), verifier: .ps512(publicKey: rsaPublicKey)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } } func testSignAndVerifyCert512() { do { try signAndVerify(signer: .rs512(privateKey: certPrivateKey), verifier: .rs512(certificate: certificate)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } func testSignAndVerifyHMAC512() { do { let hmacData = "Super Secret Key".data(using: .utf8)! try signAndVerify(signer: .hs512(key: hmacData), verifier: .hs512(key: hmacData)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } func testSignAndVerifyECDSA512() { if #available(OSX 10.13, iOS 11, tvOS 11.0, *) { do { try signAndVerify(signer: .es512(privateKey: ec512PrivateKey), verifier: .es512(publicKey: ec512PublicKey)) } catch { XCTFail("testSignAndVerify failed: \(error)") } } } func signAndVerify(signer: JWTSigner, verifier: JWTVerifier) throws { var jwt = JWT(claims: TestClaims(name:"Kitura")) jwt.claims.name = "Kitura-JWT" XCTAssertEqual(jwt.claims.name, "Kitura-JWT") jwt.claims.iss = "issuer" jwt.claims.aud = ["clientID"] jwt.claims.iat = Date(timeIntervalSince1970: 1485949565.58463) jwt.claims.exp = Date(timeIntervalSince1970: 2485949565.58463) jwt.claims.nbf = Date(timeIntervalSince1970: 1485949565.58463) let signed = try jwt.sign(using: signer) let ok = JWT.verify(signed, using: verifier) XCTAssertTrue(ok, "Verification failed") let decoded = try JWT(jwtString: signed) check(jwt: decoded, algorithm: signer.name) XCTAssertEqual(decoded.validateClaims(), .success, "Validation failed") } func check(jwt: JWT, algorithm: String) { XCTAssertEqual(jwt.header.alg, algorithm, "Wrong .alg in decoded") XCTAssertEqual(jwt.claims.exp, Date(timeIntervalSince1970: 2485949565.58463), "Wrong .exp in decoded") XCTAssertEqual(jwt.claims.iat, Date(timeIntervalSince1970: 1485949565.58463), "Wrong .iat in decoded") XCTAssertEqual(jwt.claims.nbf, Date(timeIntervalSince1970: 1485949565.58463), "Wrong .nbf in decoded") } func checkMicroProfile(jwt: JWT, algorithm: String) { XCTAssertEqual(jwt.header.alg, "RS256", "Wrong .alg in decoded. MicroProfile only supports RS256.") XCTAssertEqual(jwt.claims.iss, "https://server.example.com", "Wrong .iss in decoded") XCTAssertEqual(jwt.claims.exp, Date(timeIntervalSince1970: 2485949565.58463), "Wrong .exp in decoded") XCTAssertEqual(jwt.claims.iat, Date(timeIntervalSince1970: 1485949565.58463), "Wrong .iat in decoded") XCTAssertEqual(jwt.claims.aud ?? [""], ["clientID"], "Wrong .aud in decoded") XCTAssertEqual(jwt.claims.groups ?? [""], ["red-group", "green-group", "admin-group", "admin"], "Wrong .groups in decoded") } func testMicroProfile() { var jwt = JWT(claims: MicroProfile(name: "MP-JWT")) jwt.header.kid = "abc-1234567890" jwt.header.typ = "JWT" XCTAssertEqual(jwt.claims.name, "MP-JWT") jwt.claims.iss = "https://server.example.com" jwt.claims.aud = ["clientID"] jwt.claims.iat = Date(timeIntervalSince1970: 1485949565.58463) jwt.claims.exp = Date(timeIntervalSince1970: 2485949565.58463) jwt.claims.upn = "jdoe@server.example.com" jwt.claims.groups = ["red-group", "green-group", "admin-group", "admin"] // public key (MP-JWT needs to be signed) if let signed = try? jwt.sign(using: .rs256(privateKey: rsaPrivateKey)) { let ok = JWT.verify(signed, using: .rs256(publicKey: rsaPublicKey)) XCTAssertTrue(ok, "Verification failed") if let decoded = try? JWT(jwtString: signed) { checkMicroProfile(jwt: decoded, algorithm: "RS256") XCTAssertEqual(decoded.validateClaims(), .success, "Validation failed") } else { XCTFail("Failed to decode") } } else { XCTFail("Failed to sign") } // certificate if let signed = try? jwt.sign(using: .rs256(privateKey: certPrivateKey)) { let ok = JWT.verify(signed, using: .rs256(certificate: certificate)) XCTAssertTrue(ok, "Verification failed") if let decoded = try? JWT(jwtString: signed) { checkMicroProfile(jwt: decoded, algorithm: "RS256") XCTAssertEqual(decoded.validateClaims(), .success, "Validation failed") } else { XCTFail("Failed to decode") } } } // This test uses the rsaJWTEncoder to encode a JWT as a JWT String. // It then decodes the resulting JWT String using the JWT init from String. // The test checks that the decoded JWT is the same as the JWT you started as well as the decoded rsaEncodedTestClaimJWT. func testJWTEncoder() { var jwt = JWT(claims: TestClaims()) jwt.claims.sub = "1234567890" jwt.claims.name = "John Doe" jwt.claims.admin = true jwt.claims.iat = Date(timeIntervalSince1970: 1516239022) do { let jwtString = try rsaJWTEncoder.encodeToString(jwt) let decodedJWTString = try JWT(jwtString: jwtString) let decodedTestClaimJWT = try JWT(jwtString: rsaEncodedTestClaimJWT) // Setting the alg field on the header since the decoded JWT will have had the alg header set in the signing process. jwt.header.alg = "RS256" XCTAssertEqual(jwt.claims, decodedJWTString.claims) XCTAssertEqual(jwt.header, decodedJWTString.header) XCTAssertEqual(jwt.claims, decodedTestClaimJWT.claims) XCTAssertEqual(jwt.header, decodedTestClaimJWT.header) } catch { XCTFail("Failed to encode JTW: \(error)") } } // This test uses the rsaJWTDecoder to decode the rsaEncodedTestClaimJWT as a JWT. // The test checks that the decoded JWT is the same as the JWT that was originally encoded. func testJWTDecoder() { var jwt = JWT(claims: TestClaims()) jwt.claims.sub = "1234567890" jwt.claims.name = "John Doe" jwt.claims.admin = true jwt.claims.iat = Date(timeIntervalSince1970: 1516239022) do { let decodedJWT = try rsaJWTDecoder.decode(JWT.self, fromString: rsaEncodedTestClaimJWT) jwt.header.alg = "RS256" XCTAssertEqual(decodedJWT.claims, jwt.claims) XCTAssertEqual(decodedJWT.header, jwt.header) } catch { XCTFail("Failed to encode JTW: \(error)") } } // This test encoded and then decoded a JWT and checks you get the original JWT back with only the alg header changed. func testJWTCoderCycle() { var jwt = JWT(claims: TestClaims()) jwt.claims.sub = "1234567890" jwt.claims.name = "John Doe" jwt.claims.admin = true do { let jwtData = try rsaJWTEncoder.encode(jwt) let decodedJWT = try rsaJWTDecoder.decode(JWT.self, from: jwtData) jwt.header.alg = "RS256" XCTAssertEqual(decodedJWT.claims, jwt.claims) XCTAssertEqual(decodedJWT.header, jwt.header) } catch { XCTFail("Failed to encode JTW: \(error)") } } // This test uses the rsaJWTKidEncoder to encode a JWT as a JWT String using the kid header to select the JWTSigner. // It then decodes the resulting JWT String using the JWT init from String. // The test checks that the decoded JWT is the same as the JWT you started as well as the decoded certificateEncodedTestClaimJWT. func testJWTEncoderKeyID() { var jwt = JWT(claims: TestClaims()) jwt.header.kid = "0" jwt.claims.sub = "1234567890" jwt.claims.name = "John Doe" jwt.claims.admin = true do { let jwtString = try rsaJWTKidEncoder.encodeToString(jwt) let decodedJWTString = try JWT(jwtString: jwtString) jwt.header.alg = "RS256" XCTAssertEqual(jwt.claims, decodedJWTString.claims) XCTAssertEqual(jwt.header, decodedJWTString.header) } catch { XCTFail("Failed to encode JTW: \(error)") } } // This test uses the rsaJWTKidDecoder to decode the certificateEncodedTestClaimJWT as a JWT using the kid header to select the JWTVerifier. // The test checks that the decoded JWT is the same as the JWT that was originally encoded. func testJWTDecoderKeyID() { var jwt = JWT(claims: TestClaims()) jwt.header.kid = "1" jwt.claims.sub = "1234567890" jwt.claims.name = "John Doe" jwt.claims.admin = true do { let decodedJWT = try rsaJWTKidDecoder.decode(JWT.self, fromString: certificateEncodedTestClaimJWT) jwt.header.alg = "RS256" XCTAssertEqual(decodedJWT.claims, jwt.claims) XCTAssertEqual(decodedJWT.header, jwt.header) } catch { XCTFail("Failed to encode JTW: \(error)") } } // This test encoded and then decoded a JWT and checks you get the original JWT back with only the alg header changed. // The kid header is used to select the rsa private and public keys for encoding/decoding. func testJWTCoderCycleKeyID() { var jwt = JWT(claims: TestClaims()) jwt.header.kid = "1" jwt.claims.sub = "1234567890" jwt.claims.name = "John Doe" jwt.claims.admin = true do { let jwtData = try rsaJWTKidEncoder.encode(jwt) let decodedJWT = try rsaJWTKidDecoder.decode(JWT.self, from: jwtData) jwt.header.alg = "RS256" XCTAssertEqual(decodedJWT.claims, jwt.claims) XCTAssertEqual(decodedJWT.header, jwt.header) } catch { XCTFail("Failed to encode JTW: \(error)") } } // From jwt.io func testJWT() { let ok = JWT.verify(rsaEncodedTestClaimJWT, using: .rs256(publicKey: rsaPublicKey)) XCTAssertTrue(ok, "Verification failed") if let decoded = try? JWT(jwtString: rsaEncodedTestClaimJWT) { XCTAssertEqual(decoded.header.alg, "RS256", "Wrong .alg in decoded") XCTAssertEqual(decoded.header.typ, "JWT", "Wrong .typ in decoded") XCTAssertEqual(decoded.claims.sub, "1234567890", "Wrong .sub in decoded") XCTAssertEqual(decoded.claims.name, "John Doe", "Wrong .name in decoded") XCTAssertEqual(decoded.claims.admin, true, "Wrong .admin in decoded") XCTAssertEqual(decoded.claims.iat, Date(timeIntervalSince1970: 1516239022), "Wrong .iat in decoded") XCTAssertEqual(decoded.validateClaims(), .success, "Validation failed") } else { XCTFail("Failed to decode") } } // From jwt.io func testJWTRSAPSS() { if #available(OSX 10.13, *) { let ok = JWT.verify(rsaPSSEncodedTestClaimJWT, using: .ps256(publicKey: rsaPublicKey)) XCTAssertTrue(ok, "Verification failed") if let decoded = try? JWT(jwtString: rsaPSSEncodedTestClaimJWT) { XCTAssertEqual(decoded.header.alg, "PS256", "Wrong .alg in decoded") XCTAssertEqual(decoded.header.typ, "JWT", "Wrong .typ in decoded") XCTAssertEqual(decoded.claims.sub, "1234567890", "Wrong .sub in decoded") XCTAssertEqual(decoded.claims.name, "John Doe", "Wrong .name in decoded") XCTAssertEqual(decoded.claims.admin, true, "Wrong .admin in decoded") XCTAssertEqual(decoded.claims.iat, Date(timeIntervalSince1970: 1516239022), "Wrong .iat in decoded") XCTAssertEqual(decoded.validateClaims(), .success, "Validation failed") } else { XCTFail("Failed to decode") } } } func testJWTUsingHMAC() { guard let hmacData = "Super Secret Key".data(using: .utf8) else { return XCTFail("Failed to convert hmacKey to Data") } let ok = JWT.verify(hmacEncodedTestClaimJWT, using: .hs256(key: hmacData)) XCTAssertTrue(ok, "Verification failed") if let decoded = try? JWT(jwtString: hmacEncodedTestClaimJWT) { XCTAssertEqual(decoded.header.alg, "HS256", "Wrong .alg in decoded") XCTAssertEqual(decoded.header.typ, "JWT", "Wrong .typ in decoded") XCTAssertEqual(decoded.claims.sub, "1234567890", "Wrong .sub in decoded") XCTAssertEqual(decoded.claims.name, "John Doe", "Wrong .name in decoded") XCTAssertEqual(decoded.claims.admin, true, "Wrong .admin in decoded") XCTAssertEqual(decoded.validateClaims(), .success, "Validation failed") } else { XCTFail("Failed to decode") } } // Test using a JWT generated from jwt.io using es256 with `ecdsaPrivateKey` for interoperability. func testJWTUsingECDSA() { if #available(OSX 10.13, iOS 11, tvOS 11.0, *) { let ok = JWT.verify(ecdsaEncodedTestClaimJWT, using: .es256(publicKey: ecdsaPublicKey)) XCTAssertTrue(ok, "Verification failed") if let decoded = try? JWT(jwtString: ecdsaEncodedTestClaimJWT) { XCTAssertEqual(decoded.header.alg, "ES256", "Wrong .alg in decoded") XCTAssertEqual(decoded.header.typ, "JWT", "Wrong .typ in decoded") XCTAssertEqual(decoded.claims.sub, "1234567890", "Wrong .sub in decoded") XCTAssertEqual(decoded.claims.name, "John Doe", "Wrong .name in decoded") XCTAssertEqual(decoded.claims.admin, true, "Wrong .admin in decoded") XCTAssertEqual(decoded.claims.iat, Date(timeIntervalSince1970: 1516239022), "Wrong .iat in decoded") XCTAssertEqual(decoded.validateClaims(), .success, "Validation failed") } else { XCTFail("Failed to decode") } } } func testValidateClaims() { var jwt = JWT(claims: TestClaims(name:"Kitura")) jwt.claims.exp = Date() XCTAssertEqual(jwt.validateClaims(), .expired, "Validation failed") jwt.claims.exp = nil jwt.claims.iat = Date(timeIntervalSinceNow: 10) XCTAssertEqual(jwt.validateClaims(), .issuedAt, "Validation failed") jwt.claims.iat = nil jwt.claims.nbf = Date(timeIntervalSinceNow: 10) XCTAssertEqual(jwt.validateClaims(), .notBefore, "Validation failed") } func testValidateClaimsLeeway() { var jwt = JWT(claims: TestClaims(name:"Kitura")) jwt.claims.exp = Date() XCTAssertEqual(jwt.validateClaims(leeway: 20), .success, "Validation failed") jwt.claims.exp = nil jwt.claims.iat = Date(timeIntervalSinceNow: 10) XCTAssertEqual(jwt.validateClaims(leeway: 20), .success, "Validation failed") jwt.claims.iat = nil jwt.claims.nbf = Date(timeIntervalSinceNow: 10) XCTAssertEqual(jwt.validateClaims(leeway: 20), .success, "Validation failed") } func testErrorPattenMatching() { do { let _ = try JWT(jwtString: "InvalidString", verifier: .rs256(publicKey: rsaPublicKey)) } catch JWTError.invalidJWTString { // Caught correct error } catch { XCTFail("Incorrect error thrown: \(error)") } } func testTypeErasedErrorLocalizedDescription() { let error = JWTError.invalidJWTString XCTAssertEqual((error as Error).localizedDescription, error.errorDescription) } } func read(fileName: String) -> Data { do { var pathToTests = #file if pathToTests.hasSuffix("TestJWT.swift") { pathToTests = pathToTests.replacingOccurrences(of: "TestJWT.swift", with: "") } let fileData = try Data(contentsOf: URL(fileURLWithPath: "\(pathToTests)\(fileName)")) XCTAssertNotNil(fileData, "Failed to read in the \(fileName) file") return fileData } catch { XCTFail("Error in \(fileName).") exit(1) } } ================================================ FILE: Tests/SwiftJWTTests/cert_private_key ================================================ -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAnBvOjQhLaidHb8O9Z193tE4PrsOgjdGGQt1Bm8xPNm/cYIOE Y7vVFCHxG/UV6D3QBhD66XGons0/NWLYhJJwXHwHKdJbhoDEmU93SP8Rzgl/XxpE 0nbhCjaMcV+DgGeNaAAZy6yHwKyBNWt7WOtW/5K8Z3Y27PWNJ/vzA2PHrP/DtPjz jWkPn2J5LzLrg/Y5V2ELJ6RU1dz6Pgpdtx19NgIgms4n5+yohq7HIaFKQ5K83iiY x2RslPDG5thJ2LneGWc+PnYtqFDQBQqBM9bvlMtfJ7OhNdlexWbaLsPOMCW+eq8c /8aQXnRFg2ttsPNc4qBIXXdUCjj0wXLu3LclCQIDAQABAoIBAB+XCO9FNG2g0TXu uE9I5GJaQZYuBDluouq492PdrlHnxQLK2mmMQww16iKsL+i1SXlQylWfKG4qPpZB EGuTbqVoe9KcvOS0/hPAHvVomGPHTD0khbTJVbTJYRY4K9Y6HkVjb9TlbvswbV0w CN/vj8VcHkAZjffZoNzsgTq4YFnDfx+f9BSHo07KltZ/N4rR/7K1CPJ7hrDxiozb EI6Ul1GXfPA2BmfEa/WO9vOSbgHQmZYeWxqy1IMCJwnCrYE9o79rijinHsx3JvHu JNpP0zb7WZjIg//Gfsc6m9LRwwolJ1yKWDoKIkpwpe7YONmYRSTOj6G7zrQl0YTw SHZsqLkCgYEAycySFRL1Wo309szlY5a7+yBZ2eE9Kn2zAZeXzcMbYAGEx7wQfvTn LQSnjjpPOPqqjbq5E5zaDBrNe920fnuPHjfVw0t/Pr5xQcwGPj5HP5cY3WdmbJha A8UHYjXUPjPX5qAvGxBB4lW7a60idBQwruuGiyEleAxgEt3ZBM/JNTsCgYEAxgmf DBoYcc6j86J3Q43DK6GvD3cJwOaeHAtzHTiqybvxxjWqCTMNv+FoOw4h0UU6RfDm mQc3gPynXX3GkuJWZPsZ2HNOMdOjCCjvcAEXb+1bFyfrXIddy7MEagIELln1tsYL UuLZLuRCZhq7QZ35aMzVAtZoyH8Dvfhp+fs52osCgYAQ099GpJsTHw1TW0ixoksw qMT1V0P7fBnmQxbkkKWCvv2sjjEt9QwmA+JZCOG8VaLNSMnQKd9A7Sc/cgBwH6uS kINh0rTcrZLSMso+fIECe34WUF4JJjczY0W3WdfGDBqv36Gt9xAXaKDFXN2noltg 6sEAbxYpyZZlXFyReyZDKwKBgGyPXaaur3PDyVCHYUWg8rp6WZLquGgMg+Pvytzb 8ZPA+ZqkVF/Sotjq4c5twtALWRR6KI7+y8hjuAOiLTbb6GxW0iY7n0PlNlwExKzr jEOJJAQfmAATHLHLosHR9STLn8zf59k6DcCM1HFQehJQXSa8EpEJpEs0hYKgKMgm leJdAoGBAMTlzIsc0UYJDOdWbpEBvg11Exrk2/foRa5GlMumgeN+z07YxfRi2KnS f6DRQYsuVCpTQatiH/f/cVz+IXbLmJoEYXvDiwG2WRNSplCYCWnEwfKvpNOAQDim dcPgEZm6Ox2TAQOCiYMdArzykck8JwE+L+PM4yxEgITD1rpRygPC -----END RSA PRIVATE KEY----- ================================================ FILE: Tests/SwiftJWTTests/certificate ================================================ -----BEGIN CERTIFICATE----- MIIDbzCCAlegAwIBAgIJAKiFtGmpl0YIMA0GCSqGSIb3DQEBCwUAME4xCzAJBgNV BAYTAklMMRMwEQYDVQQIDApTb21lLVN0YXRlMQ4wDAYDVQQHDAVIYWlmYTEMMAoG A1UECgwDSUJNMQwwCgYDVQQLDANJQk0wHhcNMTcwMTMwMTI1MTUzWhcNMTgwMTMw MTI1MTUzWjBOMQswCQYDVQQGEwJJTDETMBEGA1UECAwKU29tZS1TdGF0ZTEOMAwG A1UEBwwFSGFpZmExDDAKBgNVBAoMA0lCTTEMMAoGA1UECwwDSUJNMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnBvOjQhLaidHb8O9Z193tE4PrsOgjdGG Qt1Bm8xPNm/cYIOEY7vVFCHxG/UV6D3QBhD66XGons0/NWLYhJJwXHwHKdJbhoDE mU93SP8Rzgl/XxpE0nbhCjaMcV+DgGeNaAAZy6yHwKyBNWt7WOtW/5K8Z3Y27PWN J/vzA2PHrP/DtPjzjWkPn2J5LzLrg/Y5V2ELJ6RU1dz6Pgpdtx19NgIgms4n5+yo hq7HIaFKQ5K83iiYx2RslPDG5thJ2LneGWc+PnYtqFDQBQqBM9bvlMtfJ7OhNdle xWbaLsPOMCW+eq8c/8aQXnRFg2ttsPNc4qBIXXdUCjj0wXLu3LclCQIDAQABo1Aw TjAdBgNVHQ4EFgQUiYPVudnYqmx97CjCmZGul9xfnQkwHwYDVR0jBBgwFoAUiYPV udnYqmx97CjCmZGul9xfnQkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC AQEAjS5ZV5QpIgSWEtyD4YkXZ0Sa983lTZavLAmlWYTfoERTX8b4bH3Fk3+wRTlT 7EiTOvndQ+u4BKLNMnTAXb98Y4bnHGorZ5naCPHzLKgb8HrGnCADzTDgot/xmCDN mx3rZkdPBDiT+6XNR1ZzuDSmSXHdfMMBoXb7rprIuf6yZ+gOtVmUpuBVHBTk0zP9 QQAAh7JsD+6t+oOMR0KstKTF0jKEkVK/lCGsG3x6ePBGvT3LyO9Ego9wpdFm2PnO /flZnf4mEsauRDocKrAXIXSA/IwtwStACGvCHrpWNJipMcVHxi2bqgS3vrSbMm+R 8yY0/PDT7D1w9n1q+YPYZ7LzdQ== -----END CERTIFICATE----- ================================================ FILE: Tests/SwiftJWTTests/ec384_private_key ================================================ -----BEGIN EC PRIVATE KEY----- MIGkAgEBBDBQ6YAp5oWCF3EzJdQupQu2dD6BVf7i5QDb9wMoFicaKlnXzH9weMDz VM/W4pwLAF+gBwYFK4EEACKhZANiAAQGqeXUjuGMqj0w41MLjTFDT7oUoiFLM/Mq 8xVnMX3IJSYDUc7eWIsJHS9VUAtNFt1dHXSxRnhSBv0ct0VxITCv8W42LUutbUg+ EPzehH6ApDeKJSQxwjnwhgr0J06ThCA= -----END EC PRIVATE KEY----- ================================================ FILE: Tests/SwiftJWTTests/ec384_public_key ================================================ -----BEGIN PUBLIC KEY----- MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEBqnl1I7hjKo9MONTC40xQ0+6FKIhSzPz KvMVZzF9yCUmA1HO3liLCR0vVVALTRbdXR10sUZ4Ugb9HLdFcSEwr/FuNi1LrW1I PhD83oR+gKQ3iiUkMcI58IYK9CdOk4Qg -----END PUBLIC KEY----- ================================================ FILE: Tests/SwiftJWTTests/ec512_private_key ================================================ -----BEGIN EC PRIVATE KEY----- MIHcAgEBBEIBRS6x89l3JHzSST5kKhubFPaZweNeZ02SCbmdSh5SVrK9uB9/hjCF qC1vd6kWLPV6mONJEVhv5ZChjq02hb8xZRKgBwYFK4EEACOhgYkDgYYABAHyyYaq SAMF9Olbt3zyx2gL5123JmJPOXuJlxlvA48jU8K85aBYSJ/ZNrjOKtqHdDIASUBs HMlLaH/te3VQQ6O2sQHvFC2oh9/1wMfDchP7ImBwktdB+x1/lodGyMLzGV/uxtsj hwFbX0t7mzDLAm0USboXyclnQ65y8C1UEVOBK30WMw== -----END EC PRIVATE KEY----- ================================================ FILE: Tests/SwiftJWTTests/ec512_public_key ================================================ -----BEGIN PUBLIC KEY----- MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB8smGqkgDBfTpW7d88sdoC+ddtyZi Tzl7iZcZbwOPI1PCvOWgWEif2Ta4zirah3QyAElAbBzJS2h/7Xt1UEOjtrEB7xQt qIff9cDHw3IT+yJgcJLXQfsdf5aHRsjC8xlf7sbbI4cBW19Le5swywJtFEm6F8nJ Z0OucvAtVBFTgSt9FjM= -----END PUBLIC KEY----- ================================================ FILE: Tests/SwiftJWTTests/ecdsa_private_key ================================================ -----BEGIN EC PRIVATE KEY----- MHcCAQEEIJX+87WJ7Gh19sohyZnhxZeXYNOcuGv4Q+8MLge4UkaZoAoGCCqGSM49 AwEHoUQDQgAEikc5m6C2xtDWeeAeT18WElO37zvFOz8p4kAlhvgIHN23XIClNESg KVmLgSSq2asqiwdrU5YHbcHFkgdABM1SPA== -----END EC PRIVATE KEY----- ================================================ FILE: Tests/SwiftJWTTests/ecdsa_public_key ================================================ -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEikc5m6C2xtDWeeAeT18WElO37zvF Oz8p4kAlhvgIHN23XIClNESgKVmLgSSq2asqiwdrU5YHbcHFkgdABM1SPA== -----END PUBLIC KEY----- ================================================ FILE: Tests/SwiftJWTTests/rsa_private_key ================================================ -----BEGIN RSA PRIVATE KEY----- MIIEpgIBAAKCAQEArY09Owko87BYqQKBYeUHjq5mlvL23cPPxmLKzEoo16FD3ud30 VsuabM6FGds6YrULfBQnJrAkuLHrZtFVDQPNKsZ0Ui6721c5EEw0GDJ+NXgbej+g6 gAsJ7xedmLPLIHO40QSV64mYjTh/73TZzF/dXJaGWSAwan+fsRls0Ltn2xdw8htgA IKzH0zrEMBVFpW7RroTx5qdZAQVNB7b5S/iucBDy5pvMAre3tJ30mhpt0tZtLOL7t pphhjf4FRnHS/VHb8wN6mrUu4r+7v2ZpfzJwQbkDBjxzyCl0iDGQoQo0dMUIuE0yu i9ur9+9L5gEREuDPMRXNPIwh/dgMEWo7QIDAQABAoIBAQCb0SsgTeEOqU1wsGcpVU +rsrk43Xr3ME7jdt9M+2gf8RHWl0rkFFFfZSLIHvOR2qsVc6VsdSRgvGs6WyWrq/H a/6N2Wy46uJ2l8UG6VKwBVUTiaUXZPoUgDhQPqllwbQZBWS0+MmTatBX3C9tNO2wn skHaERc+0EMQFXJ9Sisx87yA8RlhhuEaNXqxaQzTohHSvrpoHMqkjx0RsFD9py414 KlYRKCiMyI8xkWa9FkvyYB+wwmmQwRcoxBgucpyuOWunGdqF/Hxs8b6d9qWJ66d2e N1F9JCSS7cAH1CIRTxkZTH4qrxE5iMl8LuB3Xe1Qw7s60BPmmuGB4HmLKtwQShAoG BAOFr5MEmhyuY1EdmCaxlEYLakBu4xux+WBXQ533VgHrSO6Hlk1b36AEzV0hIBWEW 8BViSQv0SOyDGPG4EhfLe6KPA2dz7ZwTl+WrZtalDYJGRytSCyI9/cNh6s1adG8zO MW+Na7sq5lqXMCGnHeN6rb/zO6aiModQBHEIVUicTcHAoGBAMUYFs5T88kuD3swLo itToe0wdKlN4ytPi9O+8hZknn2wiP81rvunhrNWwK0ixIYrUkVR/o9sDBoNTVGZ+2 0Ts3cmTFTr0/9L+eFzj1YbogtXHQaaDLhiLeMAynmSe0ItlxCafTgNUZVN3JN1XD5 ByiCRqTVAAUM1BK5J/eao89rAoGBAL05+u8AzpsUUa4Vw60Jsmdr3WjH9YR0krDNi mWhIZb4f8JpmwN4WzMWzAALJSjZPnRU6wiz6btQWVIfuGBtGb3d23euYxmPgQT0mw E30F05bWi6GEqIS0sGGTqE4hSupMup3hqW5X2FQZMD7LiXUx6HIJpy8rznTO8c+vY iUXNlAoGBAKRyMe0bPOfZp48YJ2tgdoph9eokcdHNZnogg5Gpsr5Sda+DMUOCl6Yz O0FplDOYJVU6DWEsgUoSWHrH8MTzUWEQMz1l3nt1+7dH/ElQ9IBooKA6vD/fz6udh bI68+lzAHy/6RoozCqPxYB4kqL9FMzmzbyP/8E27+djV4aPHyhbAoGBAKAKeLgkmn slJA1JlN28MfSdPhxe83wowB/w9mjpl+IDwY4X27sd9M//uWCKm/i5Sp88JJtNrgs 4Uu0GZ1PGb1/3A0Kj0ZZ/2u8f5OpsZl2x05w8inkqXgWsXd5XOVfAXoDiLoouMlkP sWBKUgg4LGfIA7Jnzi38sonojtb2Iz+y -----END RSA PRIVATE KEY----- ================================================ FILE: Tests/SwiftJWTTests/rsa_public_key ================================================ -----BEGIN RSA PUBLIC KEY----- MIIBCgKCAQEArY09Owko87BYqQKBYeUHjq5mlvL23cPPxmLKzEoo16FD3ud30Vsua bM6FGds6YrULfBQnJrAkuLHrZtFVDQPNKsZ0Ui6721c5EEw0GDJ+NXgbej+g6gAsJ 7xedmLPLIHO40QSV64mYjTh/73TZzF/dXJaGWSAwan+fsRls0Ltn2xdw8htgAIKzH 0zrEMBVFpW7RroTx5qdZAQVNB7b5S/iucBDy5pvMAre3tJ30mhpt0tZtLOL7tpphh jf4FRnHS/VHb8wN6mrUu4r+7v2ZpfzJwQbkDBjxzyCl0iDGQoQo0dMUIuE0yui9ur 9+9L5gEREuDPMRXNPIwh/dgMEWo7QIDAQAB -----END RSA PUBLIC KEY----- ================================================ FILE: docs/Classes/ClaimsMicroProfile.html ================================================ ClaimsMicroProfile Class Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

ClaimsMicroProfile

public class ClaimsMicroProfile : Claims

A class representing the MicroProfile claims as listed in MicroProfile specs.

  • Initialize a ClaimsMicroProfile

    Declaration

    Swift

    public init(
        iss: String,
        sub: String,
        exp: Date,
        iat: Date,
        jti: String,
        upn: String,
        groups: [String]
    )
  • iss

    The MP-JWT issuer. RFC7519, Section 4.1.1

    Declaration

    Swift

    public var iss: String
  • sub

    Identifies the principal that is the subject of the JWT.

    Declaration

    Swift

    public var sub: String
  • exp

    Identifies the expiration time on or after which the JWT MUST NOT be accepted for processing.

    Declaration

    Swift

    public var exp: Date
  • iat

    Identifies the time at which the JWT was issued.

    Declaration

    Swift

    public var iat: Date
  • jti

    The “jti” (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object.

    Declaration

    Swift

    public var jti: String
  • upn

    This MP-JWT custom claim is the user principal name in the java.security.Principal interface, and is the caller principal name in javax.security.enterprise.identitystore.IdentityStore. If this claim is missing, fallback to the “preferred_username”, should be attempted, and if that claim is missing, fallback to the “sub” claim should be used.

    Declaration

    Swift

    public var upn: String?
  • Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace.

    Declaration

    Swift

    public var preferred_username: String?
  • This MP-JWT custom claim is the list of group names that have been assigned to the principal of the MP-JWT. This typically will required a mapping at the application container level to application deployment roles, but a one-to-one between group names and application role names is required to be performed in addition to any other mapping.

    Declaration

    Swift

    public var groups: [String]
================================================ FILE: docs/Classes/ClaimsOpenID.html ================================================ ClaimsOpenID Class Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

ClaimsOpenID

public class ClaimsOpenID : Claims

A class representing OpenID related claims as decsribed in OpenID specs.

ID Token

  • iss

    Issuer Identifier for the Issuer of the response. The iss value is a case sensitive URL using the https scheme that contains scheme, host, and optionally, port number and path components and no query or fragment components.

    Declaration

    Swift

    public var iss: String
  • sub

    Subject Identifier. A locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client, e.g., 24400320 or AItOawmwtWwcT0k51BayewNvutrJUqsvl6qs7A4. It MUST NOT exceed 255 ASCII characters in length. The sub value is case sensitive.

    Declaration

    Swift

    public var sub: String
  • aud

    Audience(s) that this ID Token is intended for. It MUST contain the OAuth 2.0 client_id of the Relying Party as an audience value. It MAY also contain identifiers for other audiences.

    Declaration

    Swift

    public var aud: [String]
  • exp

    Expiration time on or after which the ID Token MUST NOT be accepted for processing. The processing of this parameter requires that the current date/time MUST be before the expiration date/time listed in the value. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

    Declaration

    Swift

    public var exp: Date
  • iat

    Time at which the JWT was issued.

    Declaration

    Swift

    public var iat: Date
  • Time when the End-User authentication occurred.

    Declaration

    Swift

    public var auth_time: Date?
  • String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. If present in the ID Token, Clients MUST verify that the nonce Claim Value is equal to the value of the nonce parameter sent in the Authentication Request. If present in the Authentication Request, Authorization Servers MUST include a nonce Claim in the ID Token with the Claim Value being the nonce value sent in the Authentication Request. Authorization Servers SHOULD perform no other processing on nonce values used.

    Declaration

    Swift

    public var nonce: String?
  • acr

    Authentication Context Class Reference. String specifying an Authentication Context Class Reference value that identifies the Authentication Context Class that the authentication performed satisfied. The value “0” indicates the End-User authentication did not meet the requirements of ISO/IEC 29115 level 1. Authentications with level 0 SHOULD NOT be used to authorize access to any resource of any monetary value. Parties using this claim will need to agree upon the meanings of the values used, which may be context-specific.

    Declaration

    Swift

    public var acr: String?
  • amr

    Authentication Methods References. JSON array of strings that are identifiers for authentication methods used in the authentication. For instance, values might indicate that both password and OTP authentication methods were used. Parties using this claim will need to agree upon the meanings of the values used, which may be context-specific.

    Declaration

    Swift

    public var amr: [String]?
  • azp

    Authorized party - the party to which the ID Token was issued. If present, it MUST contain the OAuth 2.0 Client ID of this party. This Claim is only needed when the ID Token has a single audience value and that audience is different than the authorized party. It MAY be included even when the authorized party is the same as the sole audience.

    Declaration

    Swift

    public var azp: String?

Standard Claims

  • End-User’s full name in displayable form including all name parts, possibly including titles and suffixes, ordered according to the End-User’s locale and preferences.

    Declaration

    Swift

    public var name: String?
  • Given name(s) or first name(s) of the End-User. Note that in some cultures, people can have multiple given names; all can be present, with the names being separated by space characters.

    Declaration

    Swift

    public var given_name: String?
  • Surname(s) or last name(s) of the End-User. Note that in some cultures, people can have multiple family names or no family name; all can be present, with the names being separated by space characters.

    Declaration

    Swift

    public var family_name: String?
  • Middle name(s) of the End-User. Note that in some cultures, people can have multiple middle names; all can be present, with the names being separated by space characters. Also note that in some cultures, middle names are not used.

    Declaration

    Swift

    public var middle_name: String?
  • Casual name of the End-User that may or may not be the same as the given_name. For instance, a nickname value of Mike might be returned alongside a given_name value of Michael.

    Declaration

    Swift

    public var nickname: String?
  • Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace.

    Declaration

    Swift

    public var preferred_username: String?
  • URL of the End-User’s profile page. The contents of this Web page SHOULD be about the End-User.

    Declaration

    Swift

    public var profile: String?
  • URL of the End-User’s profile picture. This URL MUST refer to an image file (for example, a PNG, JPEG, or GIF image file), rather than to a Web page containing an image. Note that this URL SHOULD specifically reference a profile photo of the End-User suitable for displaying when describing the End-User, rather than an arbitrary photo taken by the End-User.

    Declaration

    Swift

    public var picture: String?
  • URL of the End-User’s Web page or blog. This Web page SHOULD contain information published by the End-User or an organization that the End-User is affiliated with.

    Declaration

    Swift

    public var website: String?
  • End-User’s preferred e-mail address.

    Declaration

    Swift

    public var email: String?
  • True if the End-User’s e-mail address has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this e-mail address was controlled by the End-User at the time the verification was performed. The means by which an e-mail address is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating.

    Declaration

    Swift

    public var email_verified: Bool?
  • End-User’s gender. Values defined by this specification are female and male. Other values MAY be used when neither of the defined values are applicable.

    Declaration

    Swift

    public var gender: String?
  • End-User’s birthday, represented as an ISO 8601:2004 YYYY-MM-DD format. The year MAY be 0000, indicating that it is omitted. To represent only the year, YYYY format is allowed.

    Declaration

    Swift

    public var birthdate: String?
  • String from zoneinfo time zone database representing the End-User’s time zone. For example, Europe/Paris or America/Los_Angeles.

    Declaration

    Swift

    public var zoneinfo: String?
  • End-User’s locale, represented as a BCP47 language tag. This is typically an ISO 639-1 Alpha-2 language code in lowercase and an ISO 3166-1 Alpha-2 country code in uppercase, separated by a dash. For example, en-US or fr-CA. As a compatibility note, some implementations have used an underscore as the separator rather than a dash, for example, en_US; Relying Parties MAY choose to accept this locale syntax as well.

    Declaration

    Swift

    public var locale: String?
  • End-User’s preferred telephone number. E.164 is RECOMMENDED as the format of this Claim, for example, +1 (425) 555-1212 or +56 (2) 687 2400.

    Declaration

    Swift

    public var phone_number: String?
  • True if the End-User’s phone number has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this phone number was controlled by the End-User at the time the verification was performed. The means by which a phone number is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating. When true, the phone_number Claim MUST be in E.164 format and any extensions MUST be represented in RFC 3966 format.

    Declaration

    Swift

    public var phone_number_verified: Bool?
  • End-User’s preferred postal address.

    Declaration

    Swift

    public var address: AddressClaim?
  • Time the End-User’s information was last updated.

    Declaration

    Swift

    public var updated_at: Date?
================================================ FILE: docs/Classes/ClaimsStandardJWT.html ================================================ ClaimsStandardJWT Class Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

ClaimsStandardJWT

public class ClaimsStandardJWT : Claims

A class representing the Standard JWT claims as described in RFC7519.

  • Initialize a ClaimsStandardJWT

    Declaration

    Swift

    public init(
        iss: String? = nil,
        sub: String? = nil,
        aud: [String]? = nil,
        exp: Date? = nil,
        nbf: Date? = nil,
        iat: Date? = nil,
        jti: String? = nil
        )
  • iss

    The “iss” (issuer) claim identifies the principal that issued the JWT. The processing of this claim is generally application specific. The “iss” value is a case-sensitive.

    Declaration

    Swift

    public var iss: String?
  • sub

    The “sub” (subject) claim identifies the principal that is the subject of the JWT. The claims in a JWT are normally statements about the subject. The subject value MUST either be scoped to be locally unique in the context of the issuer or be globally unique. The processing of this claim is generally application specific. The “sub” value is case-sensitive.

    Declaration

    Swift

    public var sub: String?
  • aud

    The “aud” (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the “aud” claim when this claim is present, then the JWT MUST be rejected. The interpretation of audience values is generally application specific. The “aud” value is case-sensitive.

    Declaration

    Swift

    public var aud: [String]?
  • exp

    The “exp” (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the “exp” claim requires that the current date/time MUST be before the expiration date/time listed in the “exp” claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

    Declaration

    Swift

    public var exp: Date?
  • nbf

    The “nbf” (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing. The processing of the “nbf” claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the “nbf” claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

    Declaration

    Swift

    public var nbf: Date?
  • iat

    The “iat” (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT.

    Declaration

    Swift

    public var iat: Date?
  • jti

    The “jti” (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well. The “jti” claim can be used to prevent the JWT from being replayed. The “jti” value is case- sensitive

    Declaration

    Swift

    public var jti: String?
================================================ FILE: docs/Classes/JWTDecoder.html ================================================ JWTDecoder Class Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

JWTDecoder

public class JWTDecoder : BodyDecoder

A thread safe decoder that decodes either Data or a JWT String as a JWT instance and verifies the signiture using the provided algorithm.

Usage Example:

struct MyClaims: Claims {
   var name: String
}
let publicKey = "<PublicKey>".data(using: .utf8)!
let rsaJWTDecoder = JWTDecoder(jwtVerifier: JWTVerifier.rs256(publicKey: publicKey))
do {
   let jwt = try rsaJWTDecoder.decode(JWT<MyClaims>.self, fromString: exampleJWTString)
} catch {
   print("Failed to decode JWT: \(error)")
}

Initializers

  • Initialize a JWTDecoder instance with a single JWTVerifier.

    Declaration

    Swift

    public init(jwtVerifier: JWTVerifier)

    Parameters

    JWTVerifier

    The JWTVerifier that will be used to verify the signiture of the JWT.

    Return Value

    A new instance of JWTDecoder.

  • Initialize a JWTDecoder instance with a function to generate the JWTVerifier from the JWT kid header.

    Declaration

    Swift

    public init(keyIDToVerifier: @escaping (String) -> JWTVerifier?)

    Parameters

    keyIDToVerifier

    The function that will generate the JWTVerifier using the “kid” header.

    Return Value

    A new instance of JWTDecoder.

Decode

  • Decode a JWT instance from a JWT String.

    Throws

    JWTError.invalidJWTString if the provided String is not in the form mandated by the JWT specification.

    Throws

    JWTError.invalidKeyID if the KeyID kid header fails to generate a jwtVerifier.

    Throws

    JWTError.failedVerification if the JWTVerifier fails to verify the decoded String.

    Throws

    DecodingError if the decoder fails to decode the String as the provided type.

    Declaration

    Swift

    public func decode<T>(_ type: T.Type, fromString: String) throws -> T where T : Decodable

    Parameters

    type

    The JWT type the String will be decoded as.

    fromString

    The JWT String that will be decoded.

    Return Value

    A JWT instance of the provided type.

  • Decode a JWT instance from a utf8 encoded JWT String.

    Throws

    JWTError.invalidUTF8Data if the provided Data can’t be decoded to a String.

    Throws

    JWTError.invalidJWTString if the provided String is not in the form mandated by the JWT specification.

    Throws

    JWTError.invalidKeyID if the KeyID kid header fails to generate a JWTVerifier.

    Throws

    JWTError.failedVerification if the JWTVerifier fails to verify the decoded String.

    Throws

    DecodingError if the decoder fails to decode the String as the provided type.

    Declaration

    Swift

    public func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable

    Parameters

    type

    The JWT type the Data will be decoded as.

    data

    The utf8 encoded JWT String that will be decoded.

    Return Value

    A JWT instance of the provided type.

  • Initializes a new Data from the base64url-encoded String provided. The base64url encoding is defined in RFC4648 (https://tools.ietf.org/html/rfc4648).

    This is appropriate for reading the header or claims portion of a JWT string.

    Declaration

    Swift

    public static func data(base64urlEncoded: String) -> Data?
================================================ FILE: docs/Classes/JWTEncoder.html ================================================ JWTEncoder Class Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

JWTEncoder

public class JWTEncoder : BodyEncoder

A thread safe encoder that signs the JWT header and claims using the provided algorithm and encodes a JWT instance as either Data or a JWT String.

Usage Example:

struct MyClaims: Claims {
   var name: String
}
var jwt = JWT(claims: MyClaims(name: "John Doe"))
let privateKey = "<PrivateKey>".data(using: .utf8)!
let rsaJWTEncoder = JWTEncoder(jwtSigner: JWTSigner.rs256(privateKey: privateKey))
do {
   let jwtString = try rsaJWTEncoder.encodeToString(jwt)
} catch {
   print("Failed to encode JWT: \(error)")
}

Initializers

  • Initialize a JWTEncoder instance with a single JWTSigner.

    Declaration

    Swift

    public init(jwtSigner: JWTSigner)

    Parameters

    jwtSigner

    The JWTSigner that will be used to sign the JWT.

    Return Value

    A new instance of JWTEncoder.

  • Initialize a JWTEncoder instance with a function to generate the JWTSigner from the JWT kid header.

    Declaration

    Swift

    public init(keyIDToSigner: @escaping (String) -> JWTSigner?)

    Parameters

    keyIDToSigner

    The function to generate the JWTSigner from the JWT kid header.

    Return Value

    A new instance of JWTEncoder.

Encode

  • Encode a JWT instance into a UTF8 encoded JWT String.

    Throws

    JWTError.invalidUTF8Data if the provided Data can’t be decoded to a String.

    Throws

    JWTError.invalidKeyID if the KeyID kid header fails to generate a jwtSigner.

    Throws

    EncodingError if the encoder fails to encode the object as Data.

    Declaration

    Swift

    public func encode<T>(_ value: T) throws -> Data where T : Encodable

    Parameters

    value

    The JWT instance to be encoded as Data.

    Return Value

    The UTF8 encoded JWT String.

  • Encode a JWT instance as a JWT String.

    Throws

    JWTError.invalidKeyID if the KeyID kid header fails to generate a jwtSigner.

    Throws

    EncodingError if the encoder fails to encode the object as Data.

    Declaration

    Swift

    public func encodeToString<T>(_ value: T) throws -> String where T : Encodable

    Parameters

    value

    The JWT instance to be encoded as a JWT String.

    Return Value

    A JWT String.

  • Returns a String representation of this data, encoded in base64url format as defined in RFC4648 (https://tools.ietf.org/html/rfc4648).

    This is the appropriate format for encoding the header and claims of a JWT.

    Declaration

    Swift

    public static func base64urlEncodedString(data: Data) -> String
================================================ FILE: docs/Classes.html ================================================ Classes Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

Classes

The following classes are available globally.

JWTEncoder

  • A thread safe encoder that signs the JWT header and claims using the provided algorithm and encodes a JWT instance as either Data or a JWT String.

    Usage Example:

    struct MyClaims: Claims {
       var name: String
    }
    var jwt = JWT(claims: MyClaims(name: "John Doe"))
    let privateKey = "<PrivateKey>".data(using: .utf8)!
    let rsaJWTEncoder = JWTEncoder(jwtSigner: JWTSigner.rs256(privateKey: privateKey))
    do {
       let jwtString = try rsaJWTEncoder.encodeToString(jwt)
    } catch {
       print("Failed to encode JWT: \(error)")
    }
    
    See more

    Declaration

    Swift

    public class JWTEncoder : BodyEncoder

JWTDecoder

  • A thread safe decoder that decodes either Data or a JWT String as a JWT instance and verifies the signiture using the provided algorithm.

    Usage Example:

    struct MyClaims: Claims {
       var name: String
    }
    let publicKey = "<PublicKey>".data(using: .utf8)!
    let rsaJWTDecoder = JWTDecoder(jwtVerifier: JWTVerifier.rs256(publicKey: publicKey))
    do {
       let jwt = try rsaJWTDecoder.decode(JWT<MyClaims>.self, fromString: exampleJWTString)
    } catch {
       print("Failed to decode JWT: \(error)")
    }
    
    See more

    Declaration

    Swift

    public class JWTDecoder : BodyDecoder
================================================ FILE: docs/Protocols/Claims.html ================================================ Claims Protocol Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

Claims

public protocol Claims : Decodable, Encodable

A protocol for representing the claims on a JSON web token. https://tools.ietf.org/html/rfc7519#section-4.1

Usage Example:

struct AdminClaims: Claims {
    var sub: String
    var isAdmin: Bool
    var exp: Date?
}
 let jwt = JWT(claims: AdminClaims(sub: "Kitura", isAdmin: true, exp: Date(timeIntervalSinceNow: 3600)))
  • exp Default implementation

    The “exp” (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the “exp” claim requires that the current date/time MUST be before the expiration date/time listed in the “exp” claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

    Default Implementation

    Declaration

    Swift

    var exp: Date? { get }
  • nbf Default implementation

    The “nbf” (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing. The processing of the “nbf” claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the “nbf” claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

    Default Implementation

    Declaration

    Swift

    var nbf: Date? { get }
  • iat Default implementation

    The “iat” (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT.

    Default Implementation

    Declaration

    Swift

    var iat: Date? { get }
  • encode() Default implementation

    Encode the Claim object as a Base64 String.

    Default Implementation

    Declaration

    Swift

    func encode() throws -> String
================================================ FILE: docs/Protocols.html ================================================ Protocols Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

Protocols

The following protocols are available globally.

Claims

  • A protocol for representing the claims on a JSON web token. https://tools.ietf.org/html/rfc7519#section-4.1

    Usage Example:

    struct AdminClaims: Claims {
        var sub: String
        var isAdmin: Bool
        var exp: Date?
    }
     let jwt = JWT(claims: AdminClaims(sub: "Kitura", isAdmin: true, exp: Date(timeIntervalSinceNow: 3600)))
    
    See more

    Declaration

    Swift

    public protocol Claims : Decodable, Encodable
================================================ FILE: docs/Structs/AddressClaim.html ================================================ AddressClaim Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

AddressClaim

public struct AddressClaim : Codable

Struct representing an AddressClaim as defined in the OpenID specs.

  • Full mailing address, formatted for display or use on a mailing label. This field MAY contain multiple lines, separated by newlines. Newlines can be represented either as a carriage return/line feed pair (“\r\n”) or as a single line feed character (“\n”).

    Declaration

    Swift

    public var formatted: String?
  • Full street address component, which MAY include house number, street name, Post Office Box, and multi-line extended street address information. This field MAY contain multiple lines, separated by newlines. Newlines can be represented either as a carriage return/line feed pair (“\r\n”) or as a single line feed character (“\n”).

    Declaration

    Swift

    public var street_address: String?
  • City or locality component.

    Declaration

    Swift

    public var locality: String?
  • State, province, prefecture, or region component.

    Declaration

    Swift

    public var region: String?
  • Zip code or postal code component.

    Declaration

    Swift

    public var postal_code: String?
  • Country name component.

    Declaration

    Swift

    public var country: String?
================================================ FILE: docs/Structs/Header.html ================================================ Header Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

Header

public struct Header : Codable

A representation of a JSON Web Token header. https://tools.ietf.org/html/rfc7515#section-4.1

Usage Example:

struct MyClaims: Claims {
   var name: String
}
let myHeader = Header(kid: "keyID")
let jwt = JWT(header: myHeader, claims: MyClaims(name: "Kitura"))
  • typ

    Type Header Parameter

    Declaration

    Swift

    public var typ: String?
  • alg

    Algorithm Header Parameter

    Declaration

    Swift

    public internal(set) var alg: String? { get }
  • jku

    JSON Web Token Set URL Header Parameter

    Declaration

    Swift

    public var jku: String?
  • jwk

    JSON Web Key Header Parameter

    Declaration

    Swift

    public var jwk: String?
  • kid

    Key ID Header Parameter

    Declaration

    Swift

    public var kid: String?
  • x5u

    X.509 URL Header Parameter

    Declaration

    Swift

    public var x5u: String?
  • x5c

    X.509 Certificate Chain Header Parameter

    Declaration

    Swift

    public var x5c: [String]?
  • x5t

    X.509 Certificate SHA-1 Thumbprint Header Parameter

    Declaration

    Swift

    public var x5t: String?
  • X.509 Certificate SHA-256 Thumbprint Header Parameter

    Declaration

    Swift

    public var x5tS256: String?
  • cty

    Content Type Header Parameter

    Declaration

    Swift

    public var cty: String?
  • Critical Header Parameter

    Declaration

    Swift

    public var crit: [String]?
  • Initialize a Header instance.

    Declaration

    Swift

    public init(
        typ: String? = "JWT",
        jku: String? = nil,
        jwk: String? = nil,
        kid: String? = nil,
        x5u: String? = nil,
        x5c: [String]? = nil,
        x5t: String? = nil,
        x5tS256: String? = nil,
        cty: String? = nil,
        crit: [String]? = nil
    )

    Parameters

    typ

    The Type Header Parameter

    jku

    The JSON Web Token Set URL Header Parameter

    jwk

    The JSON Web Key Header Parameter

    kid

    The Key ID Header Parameter

    x5u

    The X.509 URL Header Parameter

    x5c

    The X.509 Certificate Chain Header Parameter

    x5t

    The X.509 Certificate SHA-1 Thumbprint Header Parameter

    x5tS256

    X.509 Certificate SHA-256 Thumbprint Header Parameter

    cty

    The Content Type Header Parameter

    crit

    The Critical Header Parameter

    Return Value

    A new instance of Header.

================================================ FILE: docs/Structs/JWT.html ================================================ JWT Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

JWT

public struct JWT<T> : Codable where T : Claims

A struct representing the Header and Claims of a JSON Web Token.

Usage Example:

struct MyClaims: Claims {
   var name: String
}
let jwt = JWT(claims: MyClaims(name: "Kitura"))
let key = "<PrivateKey>".data(using: .utf8)!
let signedJWT: String? = try? jwt.sign(using: .rs256(key: key, keyType: .privateKey))
  • The JWT header.

    Declaration

    Swift

    public var header: Header
  • The JWT claims

    Declaration

    Swift

    public var claims: T
  • Initialize a JWT instance from a Header and Claims.

    Declaration

    Swift

    public init(header: Header = Header(), claims: T)

    Parameters

    header

    A JSON Web Token header object.

    claims

    A JSON Web Token claims object.

    Return Value

    A new instance of JWT.

  • Initialize a JWT instance from a JWT String. The signature will be verified using the provided JWTVerifier. The time based standard JWT claims will be verified with validateClaims(). If the string is not a valid JWT, or the verification fails, the initializer returns nil.

    Throws

    JWTError.invalidJWTString if the provided String is not in the form mandated by the JWT specification.

    Throws

    JWTError.failedVerification if the verifier fails to verify the jwtString.

    Throws

    A DecodingError if the JSONDecoder throws an error while decoding the JWT.

    Declaration

    Swift

    public init(jwtString: String, verifier: JWTVerifier = .none) throws

    Parameters

    jwt

    A String with the encoded and signed JWT.

    verifier

    The JWTVerifier used to verify the JWT.

    Return Value

    An instance of JWT if the decoding succeeds.

  • Sign the JWT using the given algorithm and encode the header, claims and signature as a JWT String.

    Note

    This function will set header.alg field to the name of the signing algorithm.

    Throws

    An EncodingError if the JSONEncoder throws an error while encoding the JWT.

    Throws

    JWTError.osVersionToLow if not using macOS 10.12.0 (Sierra) or iOS 10.0 or higher.

    Throws

    A Signing error if the jwtSigner is unable to sign the JWT with the provided key.

    Declaration

    Swift

    public mutating func sign(using jwtSigner: JWTSigner) throws -> String

    Return Value

    A String with the encoded and signed JWT.

  • Verify the signature of the encoded JWT using the given algorithm.

    Declaration

    Swift

    public static func verify(_ jwt: String, using jwtVerifier: JWTVerifier) -> Bool

    Parameters

    jwt

    A String with the encoded and signed JWT.

    Return Value

    A Bool indicating whether the verification was successful.

  • Validate the time based standard JWT claims. This function checks that the “exp” (expiration time) is in the future and the “iat” (issued at) and “nbf” (not before) headers are in the past,

    Declaration

    Swift

    public func validateClaims(leeway: TimeInterval = 0) -> ValidateClaimsResult

    Parameters

    leeway

    The time in seconds that the JWT can be invalid but still accepted to account for clock differences.

    Return Value

    A value of ValidateClaimsResult.

================================================ FILE: docs/Structs/JWTError.html ================================================ JWTError Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

JWTError

public struct JWTError : Error, Equatable

A struct representing the different errors that can be thrown by SwiftJWT

  • A human readable description of the error.

    Declaration

    Swift

    public let localizedDescription: String
  • Error when an invalid JWT String is provided

    Declaration

    Swift

    public static let invalidJWTString: JWTError
  • Error when the JWT signiture fails verification.

    Declaration

    Swift

    public static let failedVerification: JWTError
  • Error when using RSA encryption with an OS version that is too low.

    Declaration

    Swift

    public static let osVersionToLow: JWTError
  • Error when an invalid private key is provided for RSA encryption.

    Declaration

    Swift

    public static let invalidPrivateKey: JWTError
  • Error when the provided Data cannot be decoded to a String

    Declaration

    Swift

    public static let invalidUTF8Data: JWTError
  • Error when the KeyID field kid in the JWT header fails to generate a JWTSigner or JWTVerifier

    Declaration

    Swift

    public static let invalidKeyID: JWTError
  • Error when a PEM string is provided without the expected PEM headers/footers. (e.g. —–BEGIN PRIVATE KEY—–)

    Declaration

    Swift

    public static let missingPEMHeaders: JWTError
  • Function to check if JWTErrors are equal. Required for equatable protocol.

    Declaration

    Swift

    public static func == (lhs: JWTError, rhs: JWTError) -> Bool
  • Function to enable pattern matching against generic Errors.

    Declaration

    Swift

    public static func ~= (lhs: JWTError, rhs: Error) -> Bool
================================================ FILE: docs/Structs/JWTSigner.html ================================================ JWTSigner Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

JWTSigner

public struct JWTSigner

A struct that will be used to sign the JWT Header and Claims and generate a signed JWT. For RSA and ECDSA, the provided key should be a .utf8 encoded PEM String.

Usage Example:

let pemString = """
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw
33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW
+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB
AoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS
3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5Cp
uGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE
2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0
GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0K
Su5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY
6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5
fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523
Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aP
FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==
-----END RSA PRIVATE KEY-----
"""
let privateKey = pemString.data(using: .utf8)!
let jwtSigner = JWTSigner.rs256(privateKey: privateKey)
struct MyClaims: Claims {
   var name: String
}
let jwt = JWT(claims: MyClaims(name: "Kitura"))
let signedJWT = try? jwt.sign(using: jwtSigner)
  • Initialize a JWTSigner using the RSA 256 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func rs256(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with a “BEGIN RSA PRIVATE KEY” header.

  • Initialize a JWTSigner using the RSA 384 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func rs384(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with a “BEGIN RSA PRIVATE KEY” header.

  • Initialize a JWTSigner using the RSA 512 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func rs512(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with a “BEGIN RSA PRIVATE KEY” header.

  • Initialize a JWTSigner using the RSA-PSS 256 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func ps256(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with a “BEGIN RSA PRIVATE KEY” header.

  • Initialize a JWTSigner using the RSA-PSS 384 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func ps384(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with a “BEGIN RSA PRIVATE KEY” header.

  • Initialize a JWTSigner using the RSA-PSS 512 bits algorithm and the provided privateKey. This signer requires at least a 2048 bit RSA key.

    Declaration

    Swift

    public static func ps512(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with a “BEGIN RSA PRIVATE KEY” header.

  • Initialize a JWTSigner using the HMAC 256 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func hs256(key: Data) -> JWTSigner

    Parameters

    key

    The HMAC symmetric password data.

  • Initialize a JWTSigner using the HMAC 384 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func hs384(key: Data) -> JWTSigner

    Parameters

    key

    The HMAC symmetric password data.

  • Initialize a JWTSigner using the HMAC 512 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func hs512(key: Data) -> JWTSigner

    Parameters

    key

    The HMAC symmetric password data.

  • Initialize a JWTSigner using the ECDSA SHA256 algorithm and the provided privateKey.

    Declaration

    Swift

    @available(macOS 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *)
    public static func es256(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with either a “BEGIN EC PRIVATE KEY” or “BEGIN PRIVATE KEY” header.

  • Initialize a JWTSigner using the ECDSA SHA384 algorithm and the provided privateKey.

    Declaration

    Swift

    @available(macOS 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *)
    public static func es384(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with either a “BEGIN EC PRIVATE KEY” or “BEGIN PRIVATE KEY” header.

  • Initialize a JWTSigner using the ECDSA SHA512 algorithm and the provided privateKey.

    Declaration

    Swift

    @available(macOS 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *)
    public static func es512(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with either a “BEGIN EC PRIVATE KEY” or “BEGIN PRIVATE KEY” header.

  • Initialize a JWTSigner that will not sign the JWT. This is equivelent to using the “none” alg header.

    Declaration

    Swift

    public static let none: JWTSigner
================================================ FILE: docs/Structs/JWTVerifier.html ================================================ JWTVerifier Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

JWTVerifier

public struct JWTVerifier

A struct that will be used to verify the signature of a JWT is valid for the provided Header and Claims. For RSA and ECDSA, the provided key should be a .utf8 encoded PEM String.

Usage Example:

let pemString = """
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd
UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs
HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D
o2kQ+X5xK9cipRgEKwIDAQAB
-----END PUBLIC KEY-----
"""
let signedJWT = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS2l0dXJhIn0.o2Rv_w1W6qfkldgb6FwzC3tAFEzo7WyYcLyykijCEqDbW8A7TwoFev85KGo_Bi7eNaSgZ6Q8jgkA31r8EDQWtSRg3_o5Zlq-ZCndyVeibgbyM2BMVUGcGzkUD2ikARfnb6GNGHr2waVeFSDehTN8WTLl0mGFxUE6wx5ZugR7My0"
struct MyClaims: Claims {
   var name: String
}
let jwt = JWT(claims: MyClaims(name: "Kitura"))
let publicKey = pemString.data(using: .utf8)!
let jwtVerifier = JWTVerifier.rs256(publicKey: publicKey)
let verified: Bool = jwt.verify(signedJWT, using: jwtVerifier)
  • Initialize a JWTVerifier using the RSA 256 bits algorithm and the provided publicKey.

    Declaration

    Swift

    public static func rs256(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the RSA 384 bits algorithm and the provided publicKey.

    Declaration

    Swift

    public static func rs384(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the RSA 512 bits algorithm and the provided publicKey.

    Declaration

    Swift

    public static func rs512(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the RSA 256 bits algorithm and the provided certificate.

    Declaration

    Swift

    public static func rs256(certificate: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN CERTIFICATE” header.

  • Initialize a JWTVerifier using the RSA 384 bits algorithm and the provided certificate.

    Declaration

    Swift

    public static func rs384(certificate: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN CERTIFICATE” header.

  • Initialize a JWTVerifier using the RSA 512 bits algorithm and the provided certificate.

    Declaration

    Swift

    public static func rs512(certificate: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN CERTIFICATE” header.

  • Initialize a JWTVerifier using the RSA-PSS 256 bits algorithm and the provided publicKey.

    Declaration

    Swift

    public static func ps256(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the RSA-PSS 384 bits algorithm and the provided publicKey.

    Declaration

    Swift

    public static func ps384(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the RSA-PSS 512 bits algorithm and the provided publicKey. This verifier requires at least a 2048 bit RSA key.

    Declaration

    Swift

    public static func ps512(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTSigner using the HMAC 256 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func hs256(key: Data) -> JWTVerifier

    Parameters

    key

    The HMAC symmetric password data.

  • Initialize a JWTSigner using the HMAC 384 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func hs384(key: Data) -> JWTVerifier

    Parameters

    key

    The HMAC symmetric password data.

  • Initialize a JWTSigner using the HMAC 512 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func hs512(key: Data) -> JWTVerifier

    Parameters

    key

    The HMAC symmetric password data.

  • Initialize a JWTVerifier using the ECDSA SHA 256 algorithm and the provided public key.

    Declaration

    Swift

    @available(macOS 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *)
    public static func es256(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the ECDSA SHA 384 algorithm and the provided public key.

    Declaration

    Swift

    @available(macOS 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *)
    public static func es384(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the ECDSA SHA 512 algorithm and the provided public key.

    Declaration

    Swift

    @available(macOS 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *)
    public static func es512(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier that will always return true when verifying the JWT. This is equivelent to using the “none” alg header.

    Declaration

    Swift

    public static let none: JWTVerifier
================================================ FILE: docs/Structs/ValidateClaimsResult.html ================================================ ValidateClaimsResult Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

ValidateClaimsResult

public struct ValidateClaimsResult : CustomStringConvertible, Equatable

ValidateClaimsResult list the possible results of a call to JWT.validateClaims method. In case of successful validation, .success is returned, all other cases list various problems that may occur during claims validation and indicate that the validation failed.

  • The human readable description of the ValidateClaimsResult

    Declaration

    Swift

    public let description: String
  • Successful validation.

    Declaration

    Swift

    public static let success: ValidateClaimsResult
  • Invalid Expiration claim.

    Declaration

    Swift

    public static let invalidExpiration: ValidateClaimsResult
  • Expired token: expiration time claim is in the past.

    Declaration

    Swift

    public static let expired: ValidateClaimsResult
  • Invalid Not Before claim.

    Declaration

    Swift

    public static let invalidNotBefore: ValidateClaimsResult
  • Not Before claim is in the future.

    Declaration

    Swift

    public static let notBefore: ValidateClaimsResult
  • Invalid Issued At claim.

    Declaration

    Swift

    public static let invalidIssuedAt: ValidateClaimsResult
  • Issued At claim is in the future.

    Declaration

    Swift

    public static let issuedAt: ValidateClaimsResult
  • Check if two ValidateClaimsResults are equal. Required for the Equatable protocol

    Declaration

    Swift

    public static func == (lhs: ValidateClaimsResult, rhs: ValidateClaimsResult) -> Bool
================================================ FILE: docs/Structs.html ================================================ Structures Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

Structures

The following structures are available globally.

Header

  • A representation of a JSON Web Token header. https://tools.ietf.org/html/rfc7515#section-4.1

    Usage Example:

    struct MyClaims: Claims {
       var name: String
    }
    let myHeader = Header(kid: "keyID")
    let jwt = JWT(header: myHeader, claims: MyClaims(name: "Kitura"))
    
    See more

    Declaration

    Swift

    public struct Header : Codable

JWT

  • JWT

    A struct representing the Header and Claims of a JSON Web Token.

    Usage Example:

    struct MyClaims: Claims {
       var name: String
    }
    let jwt = JWT(claims: MyClaims(name: "Kitura"))
    let key = "<PrivateKey>".data(using: .utf8)!
    let signedJWT: String? = try? jwt.sign(using: .rs256(key: key, keyType: .privateKey))
    
    See more

    Declaration

    Swift

    public struct JWT<T> : Codable where T : Claims

JWTError

  • A struct representing the different errors that can be thrown by SwiftJWT

    See more

    Declaration

    Swift

    public struct JWTError : Error, Equatable

JWTSigner

  • A struct that will be used to sign the JWT Header and Claims and generate a signed JWT. For RSA and ECDSA, the provided key should be a .utf8 encoded PEM String.

    Usage Example:

    let pemString = """
    -----BEGIN RSA PRIVATE KEY-----
    MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw
    33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW
    +jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB
    AoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS
    3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5Cp
    uGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE
    2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0
    GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0K
    Su5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY
    6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5
    fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523
    Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aP
    FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==
    -----END RSA PRIVATE KEY-----
    """
    let privateKey = pemString.data(using: .utf8)!
    let jwtSigner = JWTSigner.rs256(privateKey: privateKey)
    struct MyClaims: Claims {
       var name: String
    }
    let jwt = JWT(claims: MyClaims(name: "Kitura"))
    let signedJWT = try? jwt.sign(using: jwtSigner)
    
    See more

    Declaration

    Swift

    public struct JWTSigner

JWTVerifier

  • A struct that will be used to verify the signature of a JWT is valid for the provided Header and Claims. For RSA and ECDSA, the provided key should be a .utf8 encoded PEM String.

    Usage Example:

    let pemString = """
    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd
    UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs
    HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D
    o2kQ+X5xK9cipRgEKwIDAQAB
    -----END PUBLIC KEY-----
    """
    let signedJWT = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS2l0dXJhIn0.o2Rv_w1W6qfkldgb6FwzC3tAFEzo7WyYcLyykijCEqDbW8A7TwoFev85KGo_Bi7eNaSgZ6Q8jgkA31r8EDQWtSRg3_o5Zlq-ZCndyVeibgbyM2BMVUGcGzkUD2ikARfnb6GNGHr2waVeFSDehTN8WTLl0mGFxUE6wx5ZugR7My0"
    struct MyClaims: Claims {
       var name: String
    }
    let jwt = JWT(claims: MyClaims(name: "Kitura"))
    let publicKey = pemString.data(using: .utf8)!
    let jwtVerifier = JWTVerifier.rs256(publicKey: publicKey)
    let verified: Bool = jwt.verify(signedJWT, using: jwtVerifier)
    
    See more

    Declaration

    Swift

    public struct JWTVerifier

ValidateClaimsResult

  • ValidateClaimsResult list the possible results of a call to JWT.validateClaims method. In case of successful validation, .success is returned, all other cases list various problems that may occur during claims validation and indicate that the validation failed.

    See more

    Declaration

    Swift

    public struct ValidateClaimsResult : CustomStringConvertible, Equatable
================================================ FILE: docs/css/highlight.css ================================================ /* Credit to https://gist.github.com/wataru420/2048287 */ .highlight { /* Comment */ /* Error */ /* Keyword */ /* Operator */ /* Comment.Multiline */ /* Comment.Preproc */ /* Comment.Single */ /* Comment.Special */ /* Generic.Deleted */ /* Generic.Deleted.Specific */ /* Generic.Emph */ /* Generic.Error */ /* Generic.Heading */ /* Generic.Inserted */ /* Generic.Inserted.Specific */ /* Generic.Output */ /* Generic.Prompt */ /* Generic.Strong */ /* Generic.Subheading */ /* Generic.Traceback */ /* Keyword.Constant */ /* Keyword.Declaration */ /* Keyword.Pseudo */ /* Keyword.Reserved */ /* Keyword.Type */ /* Literal.Number */ /* Literal.String */ /* Name.Attribute */ /* Name.Builtin */ /* Name.Class */ /* Name.Constant */ /* Name.Entity */ /* Name.Exception */ /* Name.Function */ /* Name.Namespace */ /* Name.Tag */ /* Name.Variable */ /* Operator.Word */ /* Text.Whitespace */ /* Literal.Number.Float */ /* Literal.Number.Hex */ /* Literal.Number.Integer */ /* Literal.Number.Oct */ /* Literal.String.Backtick */ /* Literal.String.Char */ /* Literal.String.Doc */ /* Literal.String.Double */ /* Literal.String.Escape */ /* Literal.String.Heredoc */ /* Literal.String.Interpol */ /* Literal.String.Other */ /* Literal.String.Regex */ /* Literal.String.Single */ /* Literal.String.Symbol */ /* Name.Builtin.Pseudo */ /* Name.Variable.Class */ /* Name.Variable.Global */ /* Name.Variable.Instance */ /* Literal.Number.Integer.Long */ } .highlight .c { color: #999988; font-style: italic; } .highlight .err { color: #a61717; background-color: #e3d2d2; } .highlight .k { color: #000000; font-weight: bold; } .highlight .o { color: #000000; font-weight: bold; } .highlight .cm { color: #999988; font-style: italic; } .highlight .cp { color: #999999; font-weight: bold; } .highlight .c1 { color: #999988; font-style: italic; } .highlight .cs { color: #999999; font-weight: bold; font-style: italic; } .highlight .gd { color: #000000; background-color: #ffdddd; } .highlight .gd .x { color: #000000; background-color: #ffaaaa; } .highlight .ge { color: #000000; font-style: italic; } .highlight .gr { color: #aa0000; } .highlight .gh { color: #999999; } .highlight .gi { color: #000000; background-color: #ddffdd; } .highlight .gi .x { color: #000000; background-color: #aaffaa; } .highlight .go { color: #888888; } .highlight .gp { color: #555555; } .highlight .gs { font-weight: bold; } .highlight .gu { color: #aaaaaa; } .highlight .gt { color: #aa0000; } .highlight .kc { color: #000000; font-weight: bold; } .highlight .kd { color: #000000; font-weight: bold; } .highlight .kp { color: #000000; font-weight: bold; } .highlight .kr { color: #000000; font-weight: bold; } .highlight .kt { color: #445588; } .highlight .m { color: #009999; } .highlight .s { color: #d14; } .highlight .na { color: #008080; } .highlight .nb { color: #0086B3; } .highlight .nc { color: #445588; font-weight: bold; } .highlight .no { color: #008080; } .highlight .ni { color: #800080; } .highlight .ne { color: #990000; font-weight: bold; } .highlight .nf { color: #990000; } .highlight .nn { color: #555555; } .highlight .nt { color: #000080; } .highlight .nv { color: #008080; } .highlight .ow { color: #000000; font-weight: bold; } .highlight .w { color: #bbbbbb; } .highlight .mf { color: #009999; } .highlight .mh { color: #009999; } .highlight .mi { color: #009999; } .highlight .mo { color: #009999; } .highlight .sb { color: #d14; } .highlight .sc { color: #d14; } .highlight .sd { color: #d14; } .highlight .s2 { color: #d14; } .highlight .se { color: #d14; } .highlight .sh { color: #d14; } .highlight .si { color: #d14; } .highlight .sx { color: #d14; } .highlight .sr { color: #009926; } .highlight .s1 { color: #d14; } .highlight .ss { color: #990073; } .highlight .bp { color: #999999; } .highlight .vc { color: #008080; } .highlight .vg { color: #008080; } .highlight .vi { color: #008080; } .highlight .il { color: #009999; } ================================================ FILE: docs/css/jazzy.css ================================================ *, *:before, *:after { box-sizing: inherit; } body { margin: 0; background: #fff; color: #333; font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; letter-spacing: .2px; -webkit-font-smoothing: antialiased; box-sizing: border-box; } h1 { font-size: 2rem; font-weight: 700; margin: 1.275em 0 0.6em; } h2 { font-size: 1.75rem; font-weight: 700; margin: 1.275em 0 0.3em; } h3 { font-size: 1.5rem; font-weight: 700; margin: 1em 0 0.3em; } h4 { font-size: 1.25rem; font-weight: 700; margin: 1.275em 0 0.85em; } h5 { font-size: 1rem; font-weight: 700; margin: 1.275em 0 0.85em; } h6 { font-size: 1rem; font-weight: 700; margin: 1.275em 0 0.85em; color: #777; } p { margin: 0 0 1em; } ul, ol { padding: 0 0 0 2em; margin: 0 0 0.85em; } blockquote { margin: 0 0 0.85em; padding: 0 15px; color: #858585; border-left: 4px solid #e5e5e5; } img { max-width: 100%; } a { color: #4183c4; text-decoration: none; } a:hover, a:focus { outline: 0; text-decoration: underline; } a.discouraged { text-decoration: line-through; } a.discouraged:hover, a.discouraged:focus { text-decoration: underline line-through; } table { background: #fff; width: 100%; border-collapse: collapse; border-spacing: 0; overflow: auto; margin: 0 0 0.85em; } tr:nth-child(2n) { background-color: #fbfbfb; } th, td { padding: 6px 13px; border: 1px solid #ddd; } pre { margin: 0 0 1.275em; padding: .85em 1em; overflow: auto; background: #f7f7f7; font-size: .85em; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; } code { font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; } .item-container p > code, .item-container li > code, .top-matter p > code, .top-matter li > code { background: #f7f7f7; padding: .2em; } .item-container p > code:before, .item-container p > code:after, .item-container li > code:before, .item-container li > code:after, .top-matter p > code:before, .top-matter p > code:after, .top-matter li > code:before, .top-matter li > code:after { letter-spacing: -.2em; content: "\00a0"; } pre code { padding: 0; white-space: pre; } .content-wrapper { display: flex; flex-direction: column; } @media (min-width: 768px) { .content-wrapper { flex-direction: row; } } .header { display: flex; padding: 8px; font-size: 0.875em; background: #444; color: #999; } .header-col { margin: 0; padding: 0 8px; } .header-col--primary { flex: 1; } .header-link { color: #fff; } .header-icon { padding-right: 6px; vertical-align: -4px; height: 16px; } .breadcrumbs { font-size: 0.875em; padding: 8px 16px; margin: 0; background: #fbfbfb; border-bottom: 1px solid #ddd; } .carat { height: 10px; margin: 0 5px; } .navigation { order: 2; } @media (min-width: 768px) { .navigation { order: 1; width: 25%; max-width: 300px; padding-bottom: 64px; overflow: hidden; word-wrap: normal; background: #fbfbfb; border-right: 1px solid #ddd; } } .nav-groups { list-style-type: none; padding-left: 0; } .nav-group-name { border-bottom: 1px solid #ddd; padding: 8px 0 8px 16px; } .nav-group-name-link { color: #333; } .nav-group-tasks { margin: 8px 0; padding: 0 0 0 8px; } .nav-group-task { font-size: 1em; list-style-type: none; white-space: nowrap; } .nav-group-task-link { color: #808080; } .main-content { order: 1; } @media (min-width: 768px) { .main-content { order: 2; flex: 1; padding-bottom: 60px; } } .section { padding: 0 32px; border-bottom: 1px solid #ddd; } .section-content { max-width: 834px; margin: 0 auto; padding: 16px 0; } .section-name { color: #666; display: block; } .section-name p { margin-bottom: inherit; } .declaration .highlight { overflow-x: initial; padding: 8px 0; margin: 0; background-color: transparent; border: none; } .task-group-section { border-top: 1px solid #ddd; } .task-group { padding-top: 0px; } .task-name-container a[name]:before { content: ""; display: block; } .section-name-container { position: relative; } .section-name-container .section-name-link { position: absolute; top: 0; left: 0; bottom: 0; right: 0; margin-bottom: 0; } .section-name-container .section-name { position: relative; pointer-events: none; z-index: 1; } .section-name-container .section-name a { pointer-events: auto; } .item-container { padding: 0; } .item { padding-top: 8px; width: 100%; list-style-type: none; } .item a[name]:before { content: ""; display: block; } .item .token, .item .direct-link { display: inline-block; text-indent: -20px; padding-left: 3px; margin-left: 20px; font-size: 1rem; } .item .declaration-note { font-size: .85em; color: #808080; font-style: italic; } .pointer-container { border-bottom: 1px solid #ddd; left: -23px; padding-bottom: 13px; position: relative; width: 110%; } .pointer { left: 21px; top: 7px; display: block; position: absolute; width: 12px; height: 12px; border-left: 1px solid #ddd; border-top: 1px solid #ddd; background: #fff; transform: rotate(45deg); } .height-container { display: none; position: relative; width: 100%; overflow: hidden; } .height-container .section { background: #fff; border: 1px solid #ddd; border-top-width: 0; padding-top: 10px; padding-bottom: 5px; padding: 8px 16px; } .aside, .language { padding: 6px 12px; margin: 12px 0; border-left: 5px solid #dddddd; overflow-y: hidden; } .aside .aside-title, .language .aside-title { font-size: 9px; letter-spacing: 2px; text-transform: uppercase; padding-bottom: 0; margin: 0; color: #aaa; -webkit-user-select: none; } .aside p:last-child, .language p:last-child { margin-bottom: 0; } .language { border-left: 5px solid #cde9f4; } .language .aside-title { color: #4183c4; } .aside-warning, .aside-deprecated, .aside-unavailable { border-left: 5px solid #ff6666; } .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title { color: #ff0000; } .graybox { border-collapse: collapse; width: 100%; } .graybox p { margin: 0; word-break: break-word; min-width: 50px; } .graybox td { border: 1px solid #ddd; padding: 5px 25px 5px 10px; vertical-align: middle; } .graybox tr td:first-of-type { text-align: right; padding: 7px; vertical-align: top; word-break: normal; width: 40px; } .slightly-smaller { font-size: 0.9em; } .footer { padding: 8px 16px; background: #444; color: #ddd; font-size: 0.8em; } .footer p { margin: 8px 0; } .footer a { color: #fff; } html.dash .header, html.dash .breadcrumbs, html.dash .navigation { display: none; } html.dash .height-container { display: block; } form[role=search] input { font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; line-height: 24px; padding: 0 10px; margin: 0; border: none; border-radius: 1em; } .loading form[role=search] input { background: white url(../img/spinner.gif) center right 4px no-repeat; } form[role=search] .tt-menu { margin: 0; min-width: 300px; background: #fbfbfb; color: #333; border: 1px solid #ddd; } form[role=search] .tt-highlight { font-weight: bold; } form[role=search] .tt-suggestion { font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; padding: 0 8px; } form[role=search] .tt-suggestion span { display: table-cell; white-space: nowrap; } form[role=search] .tt-suggestion .doc-parent-name { width: 100%; text-align: right; font-weight: normal; font-size: 0.9em; padding-left: 16px; } form[role=search] .tt-suggestion:hover, form[role=search] .tt-suggestion.tt-cursor { cursor: pointer; background-color: #4183c4; color: #fff; } form[role=search] .tt-suggestion:hover .doc-parent-name, form[role=search] .tt-suggestion.tt-cursor .doc-parent-name { color: #fff; } ================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Info.plist ================================================ CFBundleIdentifier com.jazzy.swiftjwt CFBundleName SwiftJWT DocSetPlatformFamily swiftjwt isDashDocset dashIndexFilePath index.html isJavaScriptEnabled DashDocSetFamily dashtoc ================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Classes/ClaimsMicroProfile.html ================================================ ClaimsMicroProfile Class Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

ClaimsMicroProfile

public class ClaimsMicroProfile : Claims

A class representing the MicroProfile claims as listed in MicroProfile specs.

  • Initialize a ClaimsMicroProfile

    Declaration

    Swift

    public init(
        iss: String,
        sub: String,
        exp: Date,
        iat: Date,
        jti: String,
        upn: String,
        groups: [String]
    )
  • iss

    The MP-JWT issuer. RFC7519, Section 4.1.1

    Declaration

    Swift

    public var iss: String
  • sub

    Identifies the principal that is the subject of the JWT.

    Declaration

    Swift

    public var sub: String
  • exp

    Identifies the expiration time on or after which the JWT MUST NOT be accepted for processing.

    Declaration

    Swift

    public var exp: Date
  • iat

    Identifies the time at which the JWT was issued.

    Declaration

    Swift

    public var iat: Date
  • jti

    The “jti” (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object.

    Declaration

    Swift

    public var jti: String
  • upn

    This MP-JWT custom claim is the user principal name in the java.security.Principal interface, and is the caller principal name in javax.security.enterprise.identitystore.IdentityStore. If this claim is missing, fallback to the “preferred_username”, should be attempted, and if that claim is missing, fallback to the “sub” claim should be used.

    Declaration

    Swift

    public var upn: String?
  • Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace.

    Declaration

    Swift

    public var preferred_username: String?
  • This MP-JWT custom claim is the list of group names that have been assigned to the principal of the MP-JWT. This typically will required a mapping at the application container level to application deployment roles, but a one-to-one between group names and application role names is required to be performed in addition to any other mapping.

    Declaration

    Swift

    public var groups: [String]
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Classes/ClaimsOpenID.html ================================================ ClaimsOpenID Class Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

ClaimsOpenID

public class ClaimsOpenID : Claims

A class representing OpenID related claims as decsribed in OpenID specs.

ID Token

  • iss

    Issuer Identifier for the Issuer of the response. The iss value is a case sensitive URL using the https scheme that contains scheme, host, and optionally, port number and path components and no query or fragment components.

    Declaration

    Swift

    public var iss: String
  • sub

    Subject Identifier. A locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client, e.g., 24400320 or AItOawmwtWwcT0k51BayewNvutrJUqsvl6qs7A4. It MUST NOT exceed 255 ASCII characters in length. The sub value is case sensitive.

    Declaration

    Swift

    public var sub: String
  • aud

    Audience(s) that this ID Token is intended for. It MUST contain the OAuth 2.0 client_id of the Relying Party as an audience value. It MAY also contain identifiers for other audiences.

    Declaration

    Swift

    public var aud: [String]
  • exp

    Expiration time on or after which the ID Token MUST NOT be accepted for processing. The processing of this parameter requires that the current date/time MUST be before the expiration date/time listed in the value. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

    Declaration

    Swift

    public var exp: Date
  • iat

    Time at which the JWT was issued.

    Declaration

    Swift

    public var iat: Date
  • Time when the End-User authentication occurred.

    Declaration

    Swift

    public var auth_time: Date?
  • String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. If present in the ID Token, Clients MUST verify that the nonce Claim Value is equal to the value of the nonce parameter sent in the Authentication Request. If present in the Authentication Request, Authorization Servers MUST include a nonce Claim in the ID Token with the Claim Value being the nonce value sent in the Authentication Request. Authorization Servers SHOULD perform no other processing on nonce values used.

    Declaration

    Swift

    public var nonce: String?
  • acr

    Authentication Context Class Reference. String specifying an Authentication Context Class Reference value that identifies the Authentication Context Class that the authentication performed satisfied. The value “0” indicates the End-User authentication did not meet the requirements of ISO/IEC 29115 level 1. Authentications with level 0 SHOULD NOT be used to authorize access to any resource of any monetary value. Parties using this claim will need to agree upon the meanings of the values used, which may be context-specific.

    Declaration

    Swift

    public var acr: String?
  • amr

    Authentication Methods References. JSON array of strings that are identifiers for authentication methods used in the authentication. For instance, values might indicate that both password and OTP authentication methods were used. Parties using this claim will need to agree upon the meanings of the values used, which may be context-specific.

    Declaration

    Swift

    public var amr: [String]?
  • azp

    Authorized party - the party to which the ID Token was issued. If present, it MUST contain the OAuth 2.0 Client ID of this party. This Claim is only needed when the ID Token has a single audience value and that audience is different than the authorized party. It MAY be included even when the authorized party is the same as the sole audience.

    Declaration

    Swift

    public var azp: String?

Standard Claims

  • End-User’s full name in displayable form including all name parts, possibly including titles and suffixes, ordered according to the End-User’s locale and preferences.

    Declaration

    Swift

    public var name: String?
  • Given name(s) or first name(s) of the End-User. Note that in some cultures, people can have multiple given names; all can be present, with the names being separated by space characters.

    Declaration

    Swift

    public var given_name: String?
  • Surname(s) or last name(s) of the End-User. Note that in some cultures, people can have multiple family names or no family name; all can be present, with the names being separated by space characters.

    Declaration

    Swift

    public var family_name: String?
  • Middle name(s) of the End-User. Note that in some cultures, people can have multiple middle names; all can be present, with the names being separated by space characters. Also note that in some cultures, middle names are not used.

    Declaration

    Swift

    public var middle_name: String?
  • Casual name of the End-User that may or may not be the same as the given_name. For instance, a nickname value of Mike might be returned alongside a given_name value of Michael.

    Declaration

    Swift

    public var nickname: String?
  • Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace.

    Declaration

    Swift

    public var preferred_username: String?
  • URL of the End-User’s profile page. The contents of this Web page SHOULD be about the End-User.

    Declaration

    Swift

    public var profile: String?
  • URL of the End-User’s profile picture. This URL MUST refer to an image file (for example, a PNG, JPEG, or GIF image file), rather than to a Web page containing an image. Note that this URL SHOULD specifically reference a profile photo of the End-User suitable for displaying when describing the End-User, rather than an arbitrary photo taken by the End-User.

    Declaration

    Swift

    public var picture: String?
  • URL of the End-User’s Web page or blog. This Web page SHOULD contain information published by the End-User or an organization that the End-User is affiliated with.

    Declaration

    Swift

    public var website: String?
  • End-User’s preferred e-mail address.

    Declaration

    Swift

    public var email: String?
  • True if the End-User’s e-mail address has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this e-mail address was controlled by the End-User at the time the verification was performed. The means by which an e-mail address is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating.

    Declaration

    Swift

    public var email_verified: Bool?
  • End-User’s gender. Values defined by this specification are female and male. Other values MAY be used when neither of the defined values are applicable.

    Declaration

    Swift

    public var gender: String?
  • End-User’s birthday, represented as an ISO 8601:2004 YYYY-MM-DD format. The year MAY be 0000, indicating that it is omitted. To represent only the year, YYYY format is allowed.

    Declaration

    Swift

    public var birthdate: String?
  • String from zoneinfo time zone database representing the End-User’s time zone. For example, Europe/Paris or America/Los_Angeles.

    Declaration

    Swift

    public var zoneinfo: String?
  • End-User’s locale, represented as a BCP47 language tag. This is typically an ISO 639-1 Alpha-2 language code in lowercase and an ISO 3166-1 Alpha-2 country code in uppercase, separated by a dash. For example, en-US or fr-CA. As a compatibility note, some implementations have used an underscore as the separator rather than a dash, for example, en_US; Relying Parties MAY choose to accept this locale syntax as well.

    Declaration

    Swift

    public var locale: String?
  • End-User’s preferred telephone number. E.164 is RECOMMENDED as the format of this Claim, for example, +1 (425) 555-1212 or +56 (2) 687 2400.

    Declaration

    Swift

    public var phone_number: String?
  • True if the End-User’s phone number has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this phone number was controlled by the End-User at the time the verification was performed. The means by which a phone number is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating. When true, the phone_number Claim MUST be in E.164 format and any extensions MUST be represented in RFC 3966 format.

    Declaration

    Swift

    public var phone_number_verified: Bool?
  • End-User’s preferred postal address.

    Declaration

    Swift

    public var address: AddressClaim?
  • Time the End-User’s information was last updated.

    Declaration

    Swift

    public var updated_at: Date?
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Classes/ClaimsStandardJWT.html ================================================ ClaimsStandardJWT Class Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

ClaimsStandardJWT

public class ClaimsStandardJWT : Claims

A class representing the Standard JWT claims as described in RFC7519.

  • Initialize a ClaimsStandardJWT

    Declaration

    Swift

    public init(
        iss: String? = nil,
        sub: String? = nil,
        aud: [String]? = nil,
        exp: Date? = nil,
        nbf: Date? = nil,
        iat: Date? = nil,
        jti: String? = nil
        )
  • iss

    The “iss” (issuer) claim identifies the principal that issued the JWT. The processing of this claim is generally application specific. The “iss” value is a case-sensitive.

    Declaration

    Swift

    public var iss: String?
  • sub

    The “sub” (subject) claim identifies the principal that is the subject of the JWT. The claims in a JWT are normally statements about the subject. The subject value MUST either be scoped to be locally unique in the context of the issuer or be globally unique. The processing of this claim is generally application specific. The “sub” value is case-sensitive.

    Declaration

    Swift

    public var sub: String?
  • aud

    The “aud” (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the “aud” claim when this claim is present, then the JWT MUST be rejected. The interpretation of audience values is generally application specific. The “aud” value is case-sensitive.

    Declaration

    Swift

    public var aud: [String]?
  • exp

    The “exp” (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the “exp” claim requires that the current date/time MUST be before the expiration date/time listed in the “exp” claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

    Declaration

    Swift

    public var exp: Date?
  • nbf

    The “nbf” (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing. The processing of the “nbf” claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the “nbf” claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

    Declaration

    Swift

    public var nbf: Date?
  • iat

    The “iat” (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT.

    Declaration

    Swift

    public var iat: Date?
  • jti

    The “jti” (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well. The “jti” claim can be used to prevent the JWT from being replayed. The “jti” value is case- sensitive

    Declaration

    Swift

    public var jti: String?
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Classes/JWTDecoder.html ================================================ JWTDecoder Class Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

JWTDecoder

public class JWTDecoder : BodyDecoder

A thread safe decoder that decodes either Data or a JWT String as a JWT instance and verifies the signiture using the provided algorithm.

Usage Example:

struct MyClaims: Claims {
   var name: String
}
let publicKey = "<PublicKey>".data(using: .utf8)!
let rsaJWTDecoder = JWTDecoder(jwtVerifier: JWTVerifier.rs256(publicKey: publicKey))
do {
   let jwt = try rsaJWTDecoder.decode(JWT<MyClaims>.self, fromString: exampleJWTString)
} catch {
   print("Failed to decode JWT: \(error)")
}

Initializers

  • Initialize a JWTDecoder instance with a single JWTVerifier.

    Declaration

    Swift

    public init(jwtVerifier: JWTVerifier)

    Parameters

    JWTVerifier

    The JWTVerifier that will be used to verify the signiture of the JWT.

    Return Value

    A new instance of JWTDecoder.

  • Initialize a JWTDecoder instance with a function to generate the JWTVerifier from the JWT kid header.

    Declaration

    Swift

    public init(keyIDToVerifier: @escaping (String) -> JWTVerifier?)

    Parameters

    keyIDToVerifier

    The function that will generate the JWTVerifier using the “kid” header.

    Return Value

    A new instance of JWTDecoder.

Decode

  • Decode a JWT instance from a JWT String.

    Throws

    JWTError.invalidJWTString if the provided String is not in the form mandated by the JWT specification.

    Throws

    JWTError.invalidKeyID if the KeyID kid header fails to generate a jwtVerifier.

    Throws

    JWTError.failedVerification if the JWTVerifier fails to verify the decoded String.

    Throws

    DecodingError if the decoder fails to decode the String as the provided type.

    Declaration

    Swift

    public func decode<T>(_ type: T.Type, fromString: String) throws -> T where T : Decodable

    Parameters

    type

    The JWT type the String will be decoded as.

    fromString

    The JWT String that will be decoded.

    Return Value

    A JWT instance of the provided type.

  • Decode a JWT instance from a utf8 encoded JWT String.

    Throws

    JWTError.invalidUTF8Data if the provided Data can’t be decoded to a String.

    Throws

    JWTError.invalidJWTString if the provided String is not in the form mandated by the JWT specification.

    Throws

    JWTError.invalidKeyID if the KeyID kid header fails to generate a JWTVerifier.

    Throws

    JWTError.failedVerification if the JWTVerifier fails to verify the decoded String.

    Throws

    DecodingError if the decoder fails to decode the String as the provided type.

    Declaration

    Swift

    public func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable

    Parameters

    type

    The JWT type the Data will be decoded as.

    data

    The utf8 encoded JWT String that will be decoded.

    Return Value

    A JWT instance of the provided type.

  • Initializes a new Data from the base64url-encoded String provided. The base64url encoding is defined in RFC4648 (https://tools.ietf.org/html/rfc4648).

    This is appropriate for reading the header or claims portion of a JWT string.

    Declaration

    Swift

    public static func data(base64urlEncoded: String) -> Data?
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Classes/JWTEncoder.html ================================================ JWTEncoder Class Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

JWTEncoder

public class JWTEncoder : BodyEncoder

A thread safe encoder that signs the JWT header and claims using the provided algorithm and encodes a JWT instance as either Data or a JWT String.

Usage Example:

struct MyClaims: Claims {
   var name: String
}
var jwt = JWT(claims: MyClaims(name: "John Doe"))
let privateKey = "<PrivateKey>".data(using: .utf8)!
let rsaJWTEncoder = JWTEncoder(jwtSigner: JWTSigner.rs256(privateKey: privateKey))
do {
   let jwtString = try rsaJWTEncoder.encodeToString(jwt)
} catch {
   print("Failed to encode JWT: \(error)")
}

Initializers

  • Initialize a JWTEncoder instance with a single JWTSigner.

    Declaration

    Swift

    public init(jwtSigner: JWTSigner)

    Parameters

    jwtSigner

    The JWTSigner that will be used to sign the JWT.

    Return Value

    A new instance of JWTEncoder.

  • Initialize a JWTEncoder instance with a function to generate the JWTSigner from the JWT kid header.

    Declaration

    Swift

    public init(keyIDToSigner: @escaping (String) -> JWTSigner?)

    Parameters

    keyIDToSigner

    The function to generate the JWTSigner from the JWT kid header.

    Return Value

    A new instance of JWTEncoder.

Encode

  • Encode a JWT instance into a UTF8 encoded JWT String.

    Throws

    JWTError.invalidUTF8Data if the provided Data can’t be decoded to a String.

    Throws

    JWTError.invalidKeyID if the KeyID kid header fails to generate a jwtSigner.

    Throws

    EncodingError if the encoder fails to encode the object as Data.

    Declaration

    Swift

    public func encode<T>(_ value: T) throws -> Data where T : Encodable

    Parameters

    value

    The JWT instance to be encoded as Data.

    Return Value

    The UTF8 encoded JWT String.

  • Encode a JWT instance as a JWT String.

    Throws

    JWTError.invalidKeyID if the KeyID kid header fails to generate a jwtSigner.

    Throws

    EncodingError if the encoder fails to encode the object as Data.

    Declaration

    Swift

    public func encodeToString<T>(_ value: T) throws -> String where T : Encodable

    Parameters

    value

    The JWT instance to be encoded as a JWT String.

    Return Value

    A JWT String.

  • Returns a String representation of this data, encoded in base64url format as defined in RFC4648 (https://tools.ietf.org/html/rfc4648).

    This is the appropriate format for encoding the header and claims of a JWT.

    Declaration

    Swift

    public static func base64urlEncodedString(data: Data) -> String
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Classes.html ================================================ Classes Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

Classes

The following classes are available globally.

JWTEncoder

  • A thread safe encoder that signs the JWT header and claims using the provided algorithm and encodes a JWT instance as either Data or a JWT String.

    Usage Example:

    struct MyClaims: Claims {
       var name: String
    }
    var jwt = JWT(claims: MyClaims(name: "John Doe"))
    let privateKey = "<PrivateKey>".data(using: .utf8)!
    let rsaJWTEncoder = JWTEncoder(jwtSigner: JWTSigner.rs256(privateKey: privateKey))
    do {
       let jwtString = try rsaJWTEncoder.encodeToString(jwt)
    } catch {
       print("Failed to encode JWT: \(error)")
    }
    
    See more

    Declaration

    Swift

    public class JWTEncoder : BodyEncoder

JWTDecoder

  • A thread safe decoder that decodes either Data or a JWT String as a JWT instance and verifies the signiture using the provided algorithm.

    Usage Example:

    struct MyClaims: Claims {
       var name: String
    }
    let publicKey = "<PublicKey>".data(using: .utf8)!
    let rsaJWTDecoder = JWTDecoder(jwtVerifier: JWTVerifier.rs256(publicKey: publicKey))
    do {
       let jwt = try rsaJWTDecoder.decode(JWT<MyClaims>.self, fromString: exampleJWTString)
    } catch {
       print("Failed to decode JWT: \(error)")
    }
    
    See more

    Declaration

    Swift

    public class JWTDecoder : BodyDecoder
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Protocols/Claims.html ================================================ Claims Protocol Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

Claims

public protocol Claims : Decodable, Encodable

A protocol for representing the claims on a JSON web token. https://tools.ietf.org/html/rfc7519#section-4.1

Usage Example:

struct AdminClaims: Claims {
    var sub: String
    var isAdmin: Bool
    var exp: Date?
}
 let jwt = JWT(claims: AdminClaims(sub: "Kitura", isAdmin: true, exp: Date(timeIntervalSinceNow: 3600)))
  • exp Default implementation

    The “exp” (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the “exp” claim requires that the current date/time MUST be before the expiration date/time listed in the “exp” claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

    Default Implementation

    Declaration

    Swift

    var exp: Date? { get }
  • nbf Default implementation

    The “nbf” (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing. The processing of the “nbf” claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the “nbf” claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

    Default Implementation

    Declaration

    Swift

    var nbf: Date? { get }
  • iat Default implementation

    The “iat” (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT.

    Default Implementation

    Declaration

    Swift

    var iat: Date? { get }
  • encode() Default implementation

    Encode the Claim object as a Base64 String.

    Default Implementation

    Declaration

    Swift

    func encode() throws -> String
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Protocols.html ================================================ Protocols Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

Protocols

The following protocols are available globally.

Claims

  • A protocol for representing the claims on a JSON web token. https://tools.ietf.org/html/rfc7519#section-4.1

    Usage Example:

    struct AdminClaims: Claims {
        var sub: String
        var isAdmin: Bool
        var exp: Date?
    }
     let jwt = JWT(claims: AdminClaims(sub: "Kitura", isAdmin: true, exp: Date(timeIntervalSinceNow: 3600)))
    
    See more

    Declaration

    Swift

    public protocol Claims : Decodable, Encodable
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Structs/AddressClaim.html ================================================ AddressClaim Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

AddressClaim

public struct AddressClaim : Codable

Struct representing an AddressClaim as defined in the OpenID specs.

  • Full mailing address, formatted for display or use on a mailing label. This field MAY contain multiple lines, separated by newlines. Newlines can be represented either as a carriage return/line feed pair (“\r\n”) or as a single line feed character (“\n”).

    Declaration

    Swift

    public var formatted: String?
  • Full street address component, which MAY include house number, street name, Post Office Box, and multi-line extended street address information. This field MAY contain multiple lines, separated by newlines. Newlines can be represented either as a carriage return/line feed pair (“\r\n”) or as a single line feed character (“\n”).

    Declaration

    Swift

    public var street_address: String?
  • City or locality component.

    Declaration

    Swift

    public var locality: String?
  • State, province, prefecture, or region component.

    Declaration

    Swift

    public var region: String?
  • Zip code or postal code component.

    Declaration

    Swift

    public var postal_code: String?
  • Country name component.

    Declaration

    Swift

    public var country: String?
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Structs/Header.html ================================================ Header Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

Header

public struct Header : Codable

A representation of a JSON Web Token header. https://tools.ietf.org/html/rfc7515#section-4.1

Usage Example:

struct MyClaims: Claims {
   var name: String
}
let myHeader = Header(kid: "keyID")
let jwt = JWT(header: myHeader, claims: MyClaims(name: "Kitura"))
  • typ

    Type Header Parameter

    Declaration

    Swift

    public var typ: String?
  • alg

    Algorithm Header Parameter

    Declaration

    Swift

    public internal(set) var alg: String? { get }
  • jku

    JSON Web Token Set URL Header Parameter

    Declaration

    Swift

    public var jku: String?
  • jwk

    JSON Web Key Header Parameter

    Declaration

    Swift

    public var jwk: String?
  • kid

    Key ID Header Parameter

    Declaration

    Swift

    public var kid: String?
  • x5u

    X.509 URL Header Parameter

    Declaration

    Swift

    public var x5u: String?
  • x5c

    X.509 Certificate Chain Header Parameter

    Declaration

    Swift

    public var x5c: [String]?
  • x5t

    X.509 Certificate SHA-1 Thumbprint Header Parameter

    Declaration

    Swift

    public var x5t: String?
  • X.509 Certificate SHA-256 Thumbprint Header Parameter

    Declaration

    Swift

    public var x5tS256: String?
  • cty

    Content Type Header Parameter

    Declaration

    Swift

    public var cty: String?
  • Critical Header Parameter

    Declaration

    Swift

    public var crit: [String]?
  • Initialize a Header instance.

    Declaration

    Swift

    public init(
        typ: String? = "JWT",
        jku: String? = nil,
        jwk: String? = nil,
        kid: String? = nil,
        x5u: String? = nil,
        x5c: [String]? = nil,
        x5t: String? = nil,
        x5tS256: String? = nil,
        cty: String? = nil,
        crit: [String]? = nil
    )

    Parameters

    typ

    The Type Header Parameter

    jku

    The JSON Web Token Set URL Header Parameter

    jwk

    The JSON Web Key Header Parameter

    kid

    The Key ID Header Parameter

    x5u

    The X.509 URL Header Parameter

    x5c

    The X.509 Certificate Chain Header Parameter

    x5t

    The X.509 Certificate SHA-1 Thumbprint Header Parameter

    x5tS256

    X.509 Certificate SHA-256 Thumbprint Header Parameter

    cty

    The Content Type Header Parameter

    crit

    The Critical Header Parameter

    Return Value

    A new instance of Header.

================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Structs/JWT.html ================================================ JWT Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

JWT

public struct JWT<T> : Codable where T : Claims

A struct representing the Header and Claims of a JSON Web Token.

Usage Example:

struct MyClaims: Claims {
   var name: String
}
let jwt = JWT(claims: MyClaims(name: "Kitura"))
let key = "<PrivateKey>".data(using: .utf8)!
let signedJWT: String? = try? jwt.sign(using: .rs256(key: key, keyType: .privateKey))
  • The JWT header.

    Declaration

    Swift

    public var header: Header
  • The JWT claims

    Declaration

    Swift

    public var claims: T
  • Initialize a JWT instance from a Header and Claims.

    Declaration

    Swift

    public init(header: Header = Header(), claims: T)

    Parameters

    header

    A JSON Web Token header object.

    claims

    A JSON Web Token claims object.

    Return Value

    A new instance of JWT.

  • Initialize a JWT instance from a JWT String. The signature will be verified using the provided JWTVerifier. The time based standard JWT claims will be verified with validateClaims(). If the string is not a valid JWT, or the verification fails, the initializer returns nil.

    Throws

    JWTError.invalidJWTString if the provided String is not in the form mandated by the JWT specification.

    Throws

    JWTError.failedVerification if the verifier fails to verify the jwtString.

    Throws

    A DecodingError if the JSONDecoder throws an error while decoding the JWT.

    Declaration

    Swift

    public init(jwtString: String, verifier: JWTVerifier = .none) throws

    Parameters

    jwt

    A String with the encoded and signed JWT.

    verifier

    The JWTVerifier used to verify the JWT.

    Return Value

    An instance of JWT if the decoding succeeds.

  • Sign the JWT using the given algorithm and encode the header, claims and signature as a JWT String.

    Note

    This function will set header.alg field to the name of the signing algorithm.

    Throws

    An EncodingError if the JSONEncoder throws an error while encoding the JWT.

    Throws

    JWTError.osVersionToLow if not using macOS 10.12.0 (Sierra) or iOS 10.0 or higher.

    Throws

    A Signing error if the jwtSigner is unable to sign the JWT with the provided key.

    Declaration

    Swift

    public mutating func sign(using jwtSigner: JWTSigner) throws -> String

    Return Value

    A String with the encoded and signed JWT.

  • Verify the signature of the encoded JWT using the given algorithm.

    Declaration

    Swift

    public static func verify(_ jwt: String, using jwtVerifier: JWTVerifier) -> Bool

    Parameters

    jwt

    A String with the encoded and signed JWT.

    Return Value

    A Bool indicating whether the verification was successful.

  • Validate the time based standard JWT claims. This function checks that the “exp” (expiration time) is in the future and the “iat” (issued at) and “nbf” (not before) headers are in the past,

    Declaration

    Swift

    public func validateClaims(leeway: TimeInterval = 0) -> ValidateClaimsResult

    Parameters

    leeway

    The time in seconds that the JWT can be invalid but still accepted to account for clock differences.

    Return Value

    A value of ValidateClaimsResult.

================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Structs/JWTError.html ================================================ JWTError Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

JWTError

public struct JWTError : Error, Equatable

A struct representing the different errors that can be thrown by SwiftJWT

  • A human readable description of the error.

    Declaration

    Swift

    public let localizedDescription: String
  • Error when an invalid JWT String is provided

    Declaration

    Swift

    public static let invalidJWTString: JWTError
  • Error when the JWT signiture fails verification.

    Declaration

    Swift

    public static let failedVerification: JWTError
  • Error when using RSA encryption with an OS version that is too low.

    Declaration

    Swift

    public static let osVersionToLow: JWTError
  • Error when an invalid private key is provided for RSA encryption.

    Declaration

    Swift

    public static let invalidPrivateKey: JWTError
  • Error when the provided Data cannot be decoded to a String

    Declaration

    Swift

    public static let invalidUTF8Data: JWTError
  • Error when the KeyID field kid in the JWT header fails to generate a JWTSigner or JWTVerifier

    Declaration

    Swift

    public static let invalidKeyID: JWTError
  • Error when a PEM string is provided without the expected PEM headers/footers. (e.g. —–BEGIN PRIVATE KEY—–)

    Declaration

    Swift

    public static let missingPEMHeaders: JWTError
  • Function to check if JWTErrors are equal. Required for equatable protocol.

    Declaration

    Swift

    public static func == (lhs: JWTError, rhs: JWTError) -> Bool
  • Function to enable pattern matching against generic Errors.

    Declaration

    Swift

    public static func ~= (lhs: JWTError, rhs: Error) -> Bool
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Structs/JWTSigner.html ================================================ JWTSigner Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

JWTSigner

public struct JWTSigner

A struct that will be used to sign the JWT Header and Claims and generate a signed JWT. For RSA and ECDSA, the provided key should be a .utf8 encoded PEM String.

Usage Example:

let pemString = """
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw
33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW
+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB
AoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS
3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5Cp
uGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE
2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0
GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0K
Su5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY
6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5
fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523
Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aP
FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==
-----END RSA PRIVATE KEY-----
"""
let privateKey = pemString.data(using: .utf8)!
let jwtSigner = JWTSigner.rs256(privateKey: privateKey)
struct MyClaims: Claims {
   var name: String
}
let jwt = JWT(claims: MyClaims(name: "Kitura"))
let signedJWT = try? jwt.sign(using: jwtSigner)
  • Initialize a JWTSigner using the RSA 256 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func rs256(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with a “BEGIN RSA PRIVATE KEY” header.

  • Initialize a JWTSigner using the RSA 384 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func rs384(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with a “BEGIN RSA PRIVATE KEY” header.

  • Initialize a JWTSigner using the RSA 512 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func rs512(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with a “BEGIN RSA PRIVATE KEY” header.

  • Initialize a JWTSigner using the RSA-PSS 256 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func ps256(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with a “BEGIN RSA PRIVATE KEY” header.

  • Initialize a JWTSigner using the RSA-PSS 384 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func ps384(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with a “BEGIN RSA PRIVATE KEY” header.

  • Initialize a JWTSigner using the RSA-PSS 512 bits algorithm and the provided privateKey. This signer requires at least a 2048 bit RSA key.

    Declaration

    Swift

    public static func ps512(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with a “BEGIN RSA PRIVATE KEY” header.

  • Initialize a JWTSigner using the HMAC 256 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func hs256(key: Data) -> JWTSigner

    Parameters

    key

    The HMAC symmetric password data.

  • Initialize a JWTSigner using the HMAC 384 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func hs384(key: Data) -> JWTSigner

    Parameters

    key

    The HMAC symmetric password data.

  • Initialize a JWTSigner using the HMAC 512 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func hs512(key: Data) -> JWTSigner

    Parameters

    key

    The HMAC symmetric password data.

  • Initialize a JWTSigner using the ECDSA SHA256 algorithm and the provided privateKey.

    Declaration

    Swift

    @available(macOS 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *)
    public static func es256(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with either a “BEGIN EC PRIVATE KEY” or “BEGIN PRIVATE KEY” header.

  • Initialize a JWTSigner using the ECDSA SHA384 algorithm and the provided privateKey.

    Declaration

    Swift

    @available(macOS 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *)
    public static func es384(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with either a “BEGIN EC PRIVATE KEY” or “BEGIN PRIVATE KEY” header.

  • Initialize a JWTSigner using the ECDSA SHA512 algorithm and the provided privateKey.

    Declaration

    Swift

    @available(macOS 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *)
    public static func es512(privateKey: Data) -> JWTSigner

    Parameters

    privateKey

    The UTF8 encoded PEM private key, with either a “BEGIN EC PRIVATE KEY” or “BEGIN PRIVATE KEY” header.

  • Initialize a JWTSigner that will not sign the JWT. This is equivelent to using the “none” alg header.

    Declaration

    Swift

    public static let none: JWTSigner
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Structs/JWTVerifier.html ================================================ JWTVerifier Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

JWTVerifier

public struct JWTVerifier

A struct that will be used to verify the signature of a JWT is valid for the provided Header and Claims. For RSA and ECDSA, the provided key should be a .utf8 encoded PEM String.

Usage Example:

let pemString = """
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd
UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs
HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D
o2kQ+X5xK9cipRgEKwIDAQAB
-----END PUBLIC KEY-----
"""
let signedJWT = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS2l0dXJhIn0.o2Rv_w1W6qfkldgb6FwzC3tAFEzo7WyYcLyykijCEqDbW8A7TwoFev85KGo_Bi7eNaSgZ6Q8jgkA31r8EDQWtSRg3_o5Zlq-ZCndyVeibgbyM2BMVUGcGzkUD2ikARfnb6GNGHr2waVeFSDehTN8WTLl0mGFxUE6wx5ZugR7My0"
struct MyClaims: Claims {
   var name: String
}
let jwt = JWT(claims: MyClaims(name: "Kitura"))
let publicKey = pemString.data(using: .utf8)!
let jwtVerifier = JWTVerifier.rs256(publicKey: publicKey)
let verified: Bool = jwt.verify(signedJWT, using: jwtVerifier)
  • Initialize a JWTVerifier using the RSA 256 bits algorithm and the provided publicKey.

    Declaration

    Swift

    public static func rs256(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the RSA 384 bits algorithm and the provided publicKey.

    Declaration

    Swift

    public static func rs384(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the RSA 512 bits algorithm and the provided publicKey.

    Declaration

    Swift

    public static func rs512(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the RSA 256 bits algorithm and the provided certificate.

    Declaration

    Swift

    public static func rs256(certificate: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN CERTIFICATE” header.

  • Initialize a JWTVerifier using the RSA 384 bits algorithm and the provided certificate.

    Declaration

    Swift

    public static func rs384(certificate: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN CERTIFICATE” header.

  • Initialize a JWTVerifier using the RSA 512 bits algorithm and the provided certificate.

    Declaration

    Swift

    public static func rs512(certificate: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN CERTIFICATE” header.

  • Initialize a JWTVerifier using the RSA-PSS 256 bits algorithm and the provided publicKey.

    Declaration

    Swift

    public static func ps256(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the RSA-PSS 384 bits algorithm and the provided publicKey.

    Declaration

    Swift

    public static func ps384(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the RSA-PSS 512 bits algorithm and the provided publicKey. This verifier requires at least a 2048 bit RSA key.

    Declaration

    Swift

    public static func ps512(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTSigner using the HMAC 256 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func hs256(key: Data) -> JWTVerifier

    Parameters

    key

    The HMAC symmetric password data.

  • Initialize a JWTSigner using the HMAC 384 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func hs384(key: Data) -> JWTVerifier

    Parameters

    key

    The HMAC symmetric password data.

  • Initialize a JWTSigner using the HMAC 512 bits algorithm and the provided privateKey.

    Declaration

    Swift

    public static func hs512(key: Data) -> JWTVerifier

    Parameters

    key

    The HMAC symmetric password data.

  • Initialize a JWTVerifier using the ECDSA SHA 256 algorithm and the provided public key.

    Declaration

    Swift

    @available(macOS 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *)
    public static func es256(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the ECDSA SHA 384 algorithm and the provided public key.

    Declaration

    Swift

    @available(macOS 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *)
    public static func es384(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier using the ECDSA SHA 512 algorithm and the provided public key.

    Declaration

    Swift

    @available(macOS 10.13, iOS 11, tvOS 11.0, watchOS 4.0, *)
    public static func es512(publicKey: Data) -> JWTVerifier

    Parameters

    publicKey

    The UTF8 encoded PEM public key, with a “BEGIN PUBLIC KEY” header.

  • Initialize a JWTVerifier that will always return true when verifying the JWT. This is equivelent to using the “none” alg header.

    Declaration

    Swift

    public static let none: JWTVerifier
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Structs/ValidateClaimsResult.html ================================================ ValidateClaimsResult Structure Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

ValidateClaimsResult

public struct ValidateClaimsResult : CustomStringConvertible, Equatable

ValidateClaimsResult list the possible results of a call to JWT.validateClaims method. In case of successful validation, .success is returned, all other cases list various problems that may occur during claims validation and indicate that the validation failed.

  • The human readable description of the ValidateClaimsResult

    Declaration

    Swift

    public let description: String
  • Successful validation.

    Declaration

    Swift

    public static let success: ValidateClaimsResult
  • Invalid Expiration claim.

    Declaration

    Swift

    public static let invalidExpiration: ValidateClaimsResult
  • Expired token: expiration time claim is in the past.

    Declaration

    Swift

    public static let expired: ValidateClaimsResult
  • Invalid Not Before claim.

    Declaration

    Swift

    public static let invalidNotBefore: ValidateClaimsResult
  • Not Before claim is in the future.

    Declaration

    Swift

    public static let notBefore: ValidateClaimsResult
  • Invalid Issued At claim.

    Declaration

    Swift

    public static let invalidIssuedAt: ValidateClaimsResult
  • Issued At claim is in the future.

    Declaration

    Swift

    public static let issuedAt: ValidateClaimsResult
  • Check if two ValidateClaimsResults are equal. Required for the Equatable protocol

    Declaration

    Swift

    public static func == (lhs: ValidateClaimsResult, rhs: ValidateClaimsResult) -> Bool
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/Structs.html ================================================ Structures Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

Structures

The following structures are available globally.

Header

  • A representation of a JSON Web Token header. https://tools.ietf.org/html/rfc7515#section-4.1

    Usage Example:

    struct MyClaims: Claims {
       var name: String
    }
    let myHeader = Header(kid: "keyID")
    let jwt = JWT(header: myHeader, claims: MyClaims(name: "Kitura"))
    
    See more

    Declaration

    Swift

    public struct Header : Codable

JWT

  • JWT

    A struct representing the Header and Claims of a JSON Web Token.

    Usage Example:

    struct MyClaims: Claims {
       var name: String
    }
    let jwt = JWT(claims: MyClaims(name: "Kitura"))
    let key = "<PrivateKey>".data(using: .utf8)!
    let signedJWT: String? = try? jwt.sign(using: .rs256(key: key, keyType: .privateKey))
    
    See more

    Declaration

    Swift

    public struct JWT<T> : Codable where T : Claims

JWTError

  • A struct representing the different errors that can be thrown by SwiftJWT

    See more

    Declaration

    Swift

    public struct JWTError : Error, Equatable

JWTSigner

  • A struct that will be used to sign the JWT Header and Claims and generate a signed JWT. For RSA and ECDSA, the provided key should be a .utf8 encoded PEM String.

    Usage Example:

    let pemString = """
    -----BEGIN RSA PRIVATE KEY-----
    MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw
    33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW
    +jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB
    AoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS
    3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5Cp
    uGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE
    2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0
    GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0K
    Su5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY
    6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5
    fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523
    Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aP
    FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==
    -----END RSA PRIVATE KEY-----
    """
    let privateKey = pemString.data(using: .utf8)!
    let jwtSigner = JWTSigner.rs256(privateKey: privateKey)
    struct MyClaims: Claims {
       var name: String
    }
    let jwt = JWT(claims: MyClaims(name: "Kitura"))
    let signedJWT = try? jwt.sign(using: jwtSigner)
    
    See more

    Declaration

    Swift

    public struct JWTSigner

JWTVerifier

  • A struct that will be used to verify the signature of a JWT is valid for the provided Header and Claims. For RSA and ECDSA, the provided key should be a .utf8 encoded PEM String.

    Usage Example:

    let pemString = """
    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd
    UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs
    HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D
    o2kQ+X5xK9cipRgEKwIDAQAB
    -----END PUBLIC KEY-----
    """
    let signedJWT = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS2l0dXJhIn0.o2Rv_w1W6qfkldgb6FwzC3tAFEzo7WyYcLyykijCEqDbW8A7TwoFev85KGo_Bi7eNaSgZ6Q8jgkA31r8EDQWtSRg3_o5Zlq-ZCndyVeibgbyM2BMVUGcGzkUD2ikARfnb6GNGHr2waVeFSDehTN8WTLl0mGFxUE6wx5ZugR7My0"
    struct MyClaims: Claims {
       var name: String
    }
    let jwt = JWT(claims: MyClaims(name: "Kitura"))
    let publicKey = pemString.data(using: .utf8)!
    let jwtVerifier = JWTVerifier.rs256(publicKey: publicKey)
    let verified: Bool = jwt.verify(signedJWT, using: jwtVerifier)
    
    See more

    Declaration

    Swift

    public struct JWTVerifier

ValidateClaimsResult

  • ValidateClaimsResult list the possible results of a call to JWT.validateClaims method. In case of successful validation, .success is returned, all other cases list various problems that may occur during claims validation and indicate that the validation failed.

    See more

    Declaration

    Swift

    public struct ValidateClaimsResult : CustomStringConvertible, Equatable
================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/css/highlight.css ================================================ /* Credit to https://gist.github.com/wataru420/2048287 */ .highlight { /* Comment */ /* Error */ /* Keyword */ /* Operator */ /* Comment.Multiline */ /* Comment.Preproc */ /* Comment.Single */ /* Comment.Special */ /* Generic.Deleted */ /* Generic.Deleted.Specific */ /* Generic.Emph */ /* Generic.Error */ /* Generic.Heading */ /* Generic.Inserted */ /* Generic.Inserted.Specific */ /* Generic.Output */ /* Generic.Prompt */ /* Generic.Strong */ /* Generic.Subheading */ /* Generic.Traceback */ /* Keyword.Constant */ /* Keyword.Declaration */ /* Keyword.Pseudo */ /* Keyword.Reserved */ /* Keyword.Type */ /* Literal.Number */ /* Literal.String */ /* Name.Attribute */ /* Name.Builtin */ /* Name.Class */ /* Name.Constant */ /* Name.Entity */ /* Name.Exception */ /* Name.Function */ /* Name.Namespace */ /* Name.Tag */ /* Name.Variable */ /* Operator.Word */ /* Text.Whitespace */ /* Literal.Number.Float */ /* Literal.Number.Hex */ /* Literal.Number.Integer */ /* Literal.Number.Oct */ /* Literal.String.Backtick */ /* Literal.String.Char */ /* Literal.String.Doc */ /* Literal.String.Double */ /* Literal.String.Escape */ /* Literal.String.Heredoc */ /* Literal.String.Interpol */ /* Literal.String.Other */ /* Literal.String.Regex */ /* Literal.String.Single */ /* Literal.String.Symbol */ /* Name.Builtin.Pseudo */ /* Name.Variable.Class */ /* Name.Variable.Global */ /* Name.Variable.Instance */ /* Literal.Number.Integer.Long */ } .highlight .c { color: #999988; font-style: italic; } .highlight .err { color: #a61717; background-color: #e3d2d2; } .highlight .k { color: #000000; font-weight: bold; } .highlight .o { color: #000000; font-weight: bold; } .highlight .cm { color: #999988; font-style: italic; } .highlight .cp { color: #999999; font-weight: bold; } .highlight .c1 { color: #999988; font-style: italic; } .highlight .cs { color: #999999; font-weight: bold; font-style: italic; } .highlight .gd { color: #000000; background-color: #ffdddd; } .highlight .gd .x { color: #000000; background-color: #ffaaaa; } .highlight .ge { color: #000000; font-style: italic; } .highlight .gr { color: #aa0000; } .highlight .gh { color: #999999; } .highlight .gi { color: #000000; background-color: #ddffdd; } .highlight .gi .x { color: #000000; background-color: #aaffaa; } .highlight .go { color: #888888; } .highlight .gp { color: #555555; } .highlight .gs { font-weight: bold; } .highlight .gu { color: #aaaaaa; } .highlight .gt { color: #aa0000; } .highlight .kc { color: #000000; font-weight: bold; } .highlight .kd { color: #000000; font-weight: bold; } .highlight .kp { color: #000000; font-weight: bold; } .highlight .kr { color: #000000; font-weight: bold; } .highlight .kt { color: #445588; } .highlight .m { color: #009999; } .highlight .s { color: #d14; } .highlight .na { color: #008080; } .highlight .nb { color: #0086B3; } .highlight .nc { color: #445588; font-weight: bold; } .highlight .no { color: #008080; } .highlight .ni { color: #800080; } .highlight .ne { color: #990000; font-weight: bold; } .highlight .nf { color: #990000; } .highlight .nn { color: #555555; } .highlight .nt { color: #000080; } .highlight .nv { color: #008080; } .highlight .ow { color: #000000; font-weight: bold; } .highlight .w { color: #bbbbbb; } .highlight .mf { color: #009999; } .highlight .mh { color: #009999; } .highlight .mi { color: #009999; } .highlight .mo { color: #009999; } .highlight .sb { color: #d14; } .highlight .sc { color: #d14; } .highlight .sd { color: #d14; } .highlight .s2 { color: #d14; } .highlight .se { color: #d14; } .highlight .sh { color: #d14; } .highlight .si { color: #d14; } .highlight .sx { color: #d14; } .highlight .sr { color: #009926; } .highlight .s1 { color: #d14; } .highlight .ss { color: #990073; } .highlight .bp { color: #999999; } .highlight .vc { color: #008080; } .highlight .vg { color: #008080; } .highlight .vi { color: #008080; } .highlight .il { color: #009999; } ================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/css/jazzy.css ================================================ *, *:before, *:after { box-sizing: inherit; } body { margin: 0; background: #fff; color: #333; font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; letter-spacing: .2px; -webkit-font-smoothing: antialiased; box-sizing: border-box; } h1 { font-size: 2rem; font-weight: 700; margin: 1.275em 0 0.6em; } h2 { font-size: 1.75rem; font-weight: 700; margin: 1.275em 0 0.3em; } h3 { font-size: 1.5rem; font-weight: 700; margin: 1em 0 0.3em; } h4 { font-size: 1.25rem; font-weight: 700; margin: 1.275em 0 0.85em; } h5 { font-size: 1rem; font-weight: 700; margin: 1.275em 0 0.85em; } h6 { font-size: 1rem; font-weight: 700; margin: 1.275em 0 0.85em; color: #777; } p { margin: 0 0 1em; } ul, ol { padding: 0 0 0 2em; margin: 0 0 0.85em; } blockquote { margin: 0 0 0.85em; padding: 0 15px; color: #858585; border-left: 4px solid #e5e5e5; } img { max-width: 100%; } a { color: #4183c4; text-decoration: none; } a:hover, a:focus { outline: 0; text-decoration: underline; } a.discouraged { text-decoration: line-through; } a.discouraged:hover, a.discouraged:focus { text-decoration: underline line-through; } table { background: #fff; width: 100%; border-collapse: collapse; border-spacing: 0; overflow: auto; margin: 0 0 0.85em; } tr:nth-child(2n) { background-color: #fbfbfb; } th, td { padding: 6px 13px; border: 1px solid #ddd; } pre { margin: 0 0 1.275em; padding: .85em 1em; overflow: auto; background: #f7f7f7; font-size: .85em; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; } code { font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; } .item-container p > code, .item-container li > code, .top-matter p > code, .top-matter li > code { background: #f7f7f7; padding: .2em; } .item-container p > code:before, .item-container p > code:after, .item-container li > code:before, .item-container li > code:after, .top-matter p > code:before, .top-matter p > code:after, .top-matter li > code:before, .top-matter li > code:after { letter-spacing: -.2em; content: "\00a0"; } pre code { padding: 0; white-space: pre; } .content-wrapper { display: flex; flex-direction: column; } @media (min-width: 768px) { .content-wrapper { flex-direction: row; } } .header { display: flex; padding: 8px; font-size: 0.875em; background: #444; color: #999; } .header-col { margin: 0; padding: 0 8px; } .header-col--primary { flex: 1; } .header-link { color: #fff; } .header-icon { padding-right: 6px; vertical-align: -4px; height: 16px; } .breadcrumbs { font-size: 0.875em; padding: 8px 16px; margin: 0; background: #fbfbfb; border-bottom: 1px solid #ddd; } .carat { height: 10px; margin: 0 5px; } .navigation { order: 2; } @media (min-width: 768px) { .navigation { order: 1; width: 25%; max-width: 300px; padding-bottom: 64px; overflow: hidden; word-wrap: normal; background: #fbfbfb; border-right: 1px solid #ddd; } } .nav-groups { list-style-type: none; padding-left: 0; } .nav-group-name { border-bottom: 1px solid #ddd; padding: 8px 0 8px 16px; } .nav-group-name-link { color: #333; } .nav-group-tasks { margin: 8px 0; padding: 0 0 0 8px; } .nav-group-task { font-size: 1em; list-style-type: none; white-space: nowrap; } .nav-group-task-link { color: #808080; } .main-content { order: 1; } @media (min-width: 768px) { .main-content { order: 2; flex: 1; padding-bottom: 60px; } } .section { padding: 0 32px; border-bottom: 1px solid #ddd; } .section-content { max-width: 834px; margin: 0 auto; padding: 16px 0; } .section-name { color: #666; display: block; } .section-name p { margin-bottom: inherit; } .declaration .highlight { overflow-x: initial; padding: 8px 0; margin: 0; background-color: transparent; border: none; } .task-group-section { border-top: 1px solid #ddd; } .task-group { padding-top: 0px; } .task-name-container a[name]:before { content: ""; display: block; } .section-name-container { position: relative; } .section-name-container .section-name-link { position: absolute; top: 0; left: 0; bottom: 0; right: 0; margin-bottom: 0; } .section-name-container .section-name { position: relative; pointer-events: none; z-index: 1; } .section-name-container .section-name a { pointer-events: auto; } .item-container { padding: 0; } .item { padding-top: 8px; width: 100%; list-style-type: none; } .item a[name]:before { content: ""; display: block; } .item .token, .item .direct-link { display: inline-block; text-indent: -20px; padding-left: 3px; margin-left: 20px; font-size: 1rem; } .item .declaration-note { font-size: .85em; color: #808080; font-style: italic; } .pointer-container { border-bottom: 1px solid #ddd; left: -23px; padding-bottom: 13px; position: relative; width: 110%; } .pointer { left: 21px; top: 7px; display: block; position: absolute; width: 12px; height: 12px; border-left: 1px solid #ddd; border-top: 1px solid #ddd; background: #fff; transform: rotate(45deg); } .height-container { display: none; position: relative; width: 100%; overflow: hidden; } .height-container .section { background: #fff; border: 1px solid #ddd; border-top-width: 0; padding-top: 10px; padding-bottom: 5px; padding: 8px 16px; } .aside, .language { padding: 6px 12px; margin: 12px 0; border-left: 5px solid #dddddd; overflow-y: hidden; } .aside .aside-title, .language .aside-title { font-size: 9px; letter-spacing: 2px; text-transform: uppercase; padding-bottom: 0; margin: 0; color: #aaa; -webkit-user-select: none; } .aside p:last-child, .language p:last-child { margin-bottom: 0; } .language { border-left: 5px solid #cde9f4; } .language .aside-title { color: #4183c4; } .aside-warning, .aside-deprecated, .aside-unavailable { border-left: 5px solid #ff6666; } .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title { color: #ff0000; } .graybox { border-collapse: collapse; width: 100%; } .graybox p { margin: 0; word-break: break-word; min-width: 50px; } .graybox td { border: 1px solid #ddd; padding: 5px 25px 5px 10px; vertical-align: middle; } .graybox tr td:first-of-type { text-align: right; padding: 7px; vertical-align: top; word-break: normal; width: 40px; } .slightly-smaller { font-size: 0.9em; } .footer { padding: 8px 16px; background: #444; color: #ddd; font-size: 0.8em; } .footer p { margin: 8px 0; } .footer a { color: #fff; } html.dash .header, html.dash .breadcrumbs, html.dash .navigation { display: none; } html.dash .height-container { display: block; } form[role=search] input { font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; line-height: 24px; padding: 0 10px; margin: 0; border: none; border-radius: 1em; } .loading form[role=search] input { background: white url(../img/spinner.gif) center right 4px no-repeat; } form[role=search] .tt-menu { margin: 0; min-width: 300px; background: #fbfbfb; color: #333; border: 1px solid #ddd; } form[role=search] .tt-highlight { font-weight: bold; } form[role=search] .tt-suggestion { font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif; padding: 0 8px; } form[role=search] .tt-suggestion span { display: table-cell; white-space: nowrap; } form[role=search] .tt-suggestion .doc-parent-name { width: 100%; text-align: right; font-weight: normal; font-size: 0.9em; padding-left: 16px; } form[role=search] .tt-suggestion:hover, form[role=search] .tt-suggestion.tt-cursor { cursor: pointer; background-color: #4183c4; color: #fff; } form[role=search] .tt-suggestion:hover .doc-parent-name, form[role=search] .tt-suggestion.tt-cursor .doc-parent-name { color: #fff; } ================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/index.html ================================================ SwiftJWT Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

Kitura

APIDoc Build Status - Master macOS Linux Apache 2 Slack Status

SwiftJWT

An implementation of JSON Web Token using Swift. JWTs offer a lightweight and compact format for transmitting information between parties, and the information can be verified and trusted due to JWTs being digitally signed.

For more information on JSON Web Tokens, their use cases and how they work, we recommend visiting jwt.io.

Reminder: JWTs sent as JWS do not encrypt data, so never send anything sensitive or confidential in a JWT. This library does not currently support JWE.

Swift version

The latest version of Swift-JWT requires Swift 4.0 or later. You can download this version of the Swift binaries by following this link. Compatibility with other Swift versions is not guaranteed.

Usage

Swift Package Manager

Add dependencies

Add the Swift-JWT package to the dependencies within your application’s Package.swift file. Substitute "x.x.x" with the latest Swift-JWT release.

.package(url: "https://github.com/Kitura/Swift-JWT.git", from: "x.x.x")

Add SwiftJWT to your target’s dependencies:

.target(name: "example", dependencies: ["SwiftJWT"]),

Import package

import SwiftJWT

Cocoapods

To include Swift-JWT in a project using CocoaPods, add SwiftJWT to your Podfile:

pod 'SwiftJWT'

Getting Started

The JWT model

In its compact form, a JSON Web Tokens consist of three sections of Base64Url encoded JSON, separated by dots (.).
These section are: Headers, Claims and the Signature. Therefore, a JWT typically looks like the following: xxxxx.yyyyy.zzzzz

The Header struct contains the fields of the JSON Web Token header as defined by RFC7515.
The “typ” header will default to “JWT”. The “alg” header will be set to the algorithm name when you sign the JWT.
The other Header fields can be set when initializing the Header or by changing them directly on the Header object.

let myHeader = Header(kid: "KeyID1")

Claims

Claims are statements about an entity (typically, the user) and additional data. The Claims are defined by creating a Swift type that conforms to the Claims protocol. The fields of this type represent the information that will be shared using the JWT.

A list of recommended claims is defined in RFC7519.

struct MyClaims: Claims {
    let iss: String
    let sub: String
    let exp: Date
    let admin: Bool
}
let myClaims = MyClaims(iss: "Kitura", sub: "John", exp: Date(timeIntervalSinceNow: 3600), admin: true)
ClaimsExamples

This library includes some example Claims structs as defined by their online specifications:

JWT

The JWT struct represents the Header and Claims of a JSON Web Token.
You can initialize a JWT by decoding a JWT String, or by providing the JWT Header and Claims.

let myJWT = JWT(header: myHeader, claims: myClaims)

Signing and Verifying JSON web tokens

Creating public and private keys

To sign and verify a JWT using an RSA algorithm, you must provide a public and private key. This could be the contents of a .key file generated via the following Terminal commands:

$ ssh-keygen -t rsa -b 4096 -m PEM -f privateKey.key
# Don't add a passphrase
$ openssl rsa -in privateKey.key -pubout -outform PEM -out privateKey.key.pub

This will create a public and private key pair on your system, and the contents of the private key can be passed into a Swift variable using the following code:

let privateKeyPath = URL(fileURLWithPath: getAbsolutePath(relativePath: "/path/to/privateKey.key"))
let privateKey: Data = try Data(contentsOf: privateKeyPath, options: .alwaysMapped)
let publicKeyPath = URL(fileURLWithPath: getAbsolutePath(relativePath: "/path/to/publicKey.key"))
let publicKey: Data = try Data(contentsOf: publicKeyPath, options: .alwaysMapped)

For details on creating elliptic curve public and private keys, view the BlueECC README.txt.

Sign a JWT using a JWTSigner

The struct JWTSigner contains the algorithms that can be used to sign a JWT.

Initialize a JWTSigner using the static function corresponding to the desired RSA algorithm:

let jwtSigner = JWTSigner.rs256(privateKey: privateKey)

To generate a signed JWT string, call the sign function on your JWT instance, passing in a JWTSigner:

let signedJWT = try myJWT.sign(using: jwtSigner)

The resulting signedJWT will be a String of the form:

<encoded header>.<encoded claims>.<signature>

Note: The sign function sets the alg (algorithm) field of the header.

Verify a JWT using JWTVerifier

The struct JWTVerifier contains the algorithms that can be used to verify a JWT.

Initialize a JWTVerifier using the static function corresponding to the desired RSA algorithm:

let jwtVerifier = JWTVerifier.rs256(publicKey: publicKey)

To verify a signed JWT string, call the static verify function, passing in your JWT string and the JWTVerifier:

let verified = JWT<MyClaims>.verify(signedJWT, using: jwtVerifier)

The verified field will be a bool that is true if the signature is verified.

Supported Algorithms

The supported algorithms for signing and verifying JWTs are:

  • RS256 - RSASSA-PKCS1-v1_5 using SHA-256
  • RS384 - RSASSA-PKCS1-v1_5 using SHA-384
  • RS512 - RSASSA-PKCS1-v1_5 using SHA-512
  • HS256 - HMAC using using SHA-256
  • HS384 - HMAC using using SHA-384
  • HS512 - HMAC using using SHA-512
  • ES256 - ECDSA using using SHA-256 and a P-256 curve
  • ES384 - ECDSA using using SHA-384 and a P-384 curve
  • ES512 - ECDSA using using SHA-512 and a P-521 curve
  • PS256 - RSA-PSS using SHA-256
  • PS384 - RSA-PSS using SHA-384
  • PS512 - RSA-PSS using SHA-512
  • none - Don’t sign or verify the JWT

Note: ECDSA and RSA-PSS algorithms require a minimum Swift version of 4.1.

Validate claims

The validateClaims function validates the standard Date claims of a JWT instance. The following claims are validated if they are present in the Claims object:

  • exp (expiration date)
  • nbf (not before date)
  • iat (issued at date)

The method returns ValidateClaimsResult - an struct that list the various reasons for validation failure. If the validation succeeds ValidateClaimsResult.success is returned. The leeway parameter is the TimeInterval in seconds that a standard Date claim will be valid outside of the specified time. This can be used to account for clock skew between issuers and verifiers.

let validationResult = verified.validateClaims(leeway: 10)
if validationResult != .success {
    print("Claims validation failed: ", validationResult)
}

Decode a JWT from a JWT string

A JWT struct can be initialized from a JWT string. If a JWTVerifier is provided it will be used to verify the signature before initialization

let newJWT = try JWT<MyClaims>(jwtString: signedJWT, verifier: jwtVerifier)

JWTEncoder and JWTDecoder

The JWTEncoder and JWTDecoder classes encode and decode JWT Strings using the same API as JSONEncoder and JSONDecoder:

 let jwtEncoder = JWTEncoder(jwtSigner: jwtSigner)
 let jwtString = try jwtEncoder.encodeToString(myJWT)

 let jwtDecoder = JWTDecoder(jwtVerifier: jwtVerifier)
 let jwt = try jwtDecoder.decode(JWT<MyClaims>.self, fromString: jwtString)

Because JWTEncoder and JWTDecoder conform to KituraContract’s BodyEncoder and BodyDecoder protocols, they can be used as a custom coder in Codable routes for sending and receiving JWTs:

 router.encoders[MediaType(type: .application, subType: "jwt")] = { return jwtEncoder }
 router.decoders[MediaType(type: .application, subType: "jwt")] = { return jwtDecoder }

This allows for the use of JWT’s in information exchange. By sending and receiving JWT’s you can ensure the sending is who they say they are and verify the content hasn’t been tampered with.

API Documentation

For more information visit our API reference.

Community

We love to talk server-side Swift, and Kitura. Join our Slack to meet the team!

License

This library is licensed under Apache 2.0. Full license text is available in LICENSE.

================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/js/jazzy.js ================================================ window.jazzy = {'docset': false} if (typeof window.dash != 'undefined') { document.documentElement.className += ' dash' window.jazzy.docset = true } if (navigator.userAgent.match(/xcode/i)) { document.documentElement.className += ' xcode' window.jazzy.docset = true } function toggleItem($link, $content) { var animationDuration = 300; $link.toggleClass('token-open'); $content.slideToggle(animationDuration); } function itemLinkToContent($link) { return $link.parent().parent().next(); } // On doc load + hash-change, open any targetted item function openCurrentItemIfClosed() { if (window.jazzy.docset) { return; } var $link = $(`a[name="${location.hash.substring(1)}"]`).nextAll('.token'); $content = itemLinkToContent($link); if ($content.is(':hidden')) { toggleItem($link, $content); } } $(openCurrentItemIfClosed); $(window).on('hashchange', openCurrentItemIfClosed); // On item link ('token') click, toggle its discussion $('.token').on('click', function(event) { if (window.jazzy.docset) { return; } var $link = $(this); toggleItem($link, itemLinkToContent($link)); // Keeps the document from jumping to the hash. var href = $link.attr('href'); if (history.pushState) { history.pushState({}, '', href); } else { location.hash = href; } event.preventDefault(); }); // Clicks on links to the current, closed, item need to open the item $("a:not('.token')").on('click', function() { if (location == this.href) { openCurrentItemIfClosed(); } }); // KaTeX rendering if ("katex" in window) { $($('.math').each( (_, element) => { katex.render(element.textContent, element, { displayMode: $(element).hasClass('m-block'), throwOnError: false, trust: true }); })) } ================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/js/jazzy.search.js ================================================ $(function(){ var $typeahead = $('[data-typeahead]'); var $form = $typeahead.parents('form'); var searchURL = $form.attr('action'); function displayTemplate(result) { return result.name; } function suggestionTemplate(result) { var t = '
'; t += '' + result.name + ''; if (result.parent_name) { t += '' + result.parent_name + ''; } t += '
'; return t; } $typeahead.one('focus', function() { $form.addClass('loading'); $.getJSON(searchURL).then(function(searchData) { const searchIndex = lunr(function() { this.ref('url'); this.field('name'); this.field('abstract'); for (const [url, doc] of Object.entries(searchData)) { this.add({url: url, name: doc.name, abstract: doc.abstract}); } }); $typeahead.typeahead( { highlight: true, minLength: 3, autoselect: true }, { limit: 10, display: displayTemplate, templates: { suggestion: suggestionTemplate }, source: function(query, sync) { const lcSearch = query.toLowerCase(); const results = searchIndex.query(function(q) { q.term(lcSearch, { boost: 100 }); q.term(lcSearch, { boost: 10, wildcard: lunr.Query.wildcard.TRAILING }); }).map(function(result) { var doc = searchData[result.ref]; doc.url = result.ref; return doc; }); sync(results); } } ); $form.removeClass('loading'); $typeahead.trigger('focus'); }); }); var baseURL = searchURL.slice(0, -"search.json".length); $typeahead.on('typeahead:select', function(e, result) { window.location = baseURL + result.url; }); }); ================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/js/typeahead.jquery.js ================================================ /*! * typeahead.js 1.3.1 * https://github.com/corejavascript/typeahead.js * Copyright 2013-2020 Twitter, Inc. and other contributors; Licensed MIT */ (function(root, factory) { if (typeof define === "function" && define.amd) { define([ "jquery" ], function(a0) { return factory(a0); }); } else if (typeof module === "object" && module.exports) { module.exports = factory(require("jquery")); } else { factory(root["jQuery"]); } })(this, function($) { var _ = function() { "use strict"; return { isMsie: function() { return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; }, isBlankString: function(str) { return !str || /^\s*$/.test(str); }, escapeRegExChars: function(str) { return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); }, isString: function(obj) { return typeof obj === "string"; }, isNumber: function(obj) { return typeof obj === "number"; }, isArray: $.isArray, isFunction: $.isFunction, isObject: $.isPlainObject, isUndefined: function(obj) { return typeof obj === "undefined"; }, isElement: function(obj) { return !!(obj && obj.nodeType === 1); }, isJQuery: function(obj) { return obj instanceof $; }, toStr: function toStr(s) { return _.isUndefined(s) || s === null ? "" : s + ""; }, bind: $.proxy, each: function(collection, cb) { $.each(collection, reverseArgs); function reverseArgs(index, value) { return cb(value, index); } }, map: $.map, filter: $.grep, every: function(obj, test) { var result = true; if (!obj) { return result; } $.each(obj, function(key, val) { if (!(result = test.call(null, val, key, obj))) { return false; } }); return !!result; }, some: function(obj, test) { var result = false; if (!obj) { return result; } $.each(obj, function(key, val) { if (result = test.call(null, val, key, obj)) { return false; } }); return !!result; }, mixin: $.extend, identity: function(x) { return x; }, clone: function(obj) { return $.extend(true, {}, obj); }, getIdGenerator: function() { var counter = 0; return function() { return counter++; }; }, templatify: function templatify(obj) { return $.isFunction(obj) ? obj : template; function template() { return String(obj); } }, defer: function(fn) { setTimeout(fn, 0); }, debounce: function(func, wait, immediate) { var timeout, result; return function() { var context = this, args = arguments, later, callNow; later = function() { timeout = null; if (!immediate) { result = func.apply(context, args); } }; callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) { result = func.apply(context, args); } return result; }; }, throttle: function(func, wait) { var context, args, timeout, result, previous, later; previous = 0; later = function() { previous = new Date(); timeout = null; result = func.apply(context, args); }; return function() { var now = new Date(), remaining = wait - (now - previous); context = this; args = arguments; if (remaining <= 0) { clearTimeout(timeout); timeout = null; previous = now; result = func.apply(context, args); } else if (!timeout) { timeout = setTimeout(later, remaining); } return result; }; }, stringify: function(val) { return _.isString(val) ? val : JSON.stringify(val); }, guid: function() { function _p8(s) { var p = (Math.random().toString(16) + "000000000").substr(2, 8); return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p; } return "tt-" + _p8() + _p8(true) + _p8(true) + _p8(); }, noop: function() {} }; }(); var WWW = function() { "use strict"; var defaultClassNames = { wrapper: "twitter-typeahead", input: "tt-input", hint: "tt-hint", menu: "tt-menu", dataset: "tt-dataset", suggestion: "tt-suggestion", selectable: "tt-selectable", empty: "tt-empty", open: "tt-open", cursor: "tt-cursor", highlight: "tt-highlight" }; return build; function build(o) { var www, classes; classes = _.mixin({}, defaultClassNames, o); www = { css: buildCss(), classes: classes, html: buildHtml(classes), selectors: buildSelectors(classes) }; return { css: www.css, html: www.html, classes: www.classes, selectors: www.selectors, mixin: function(o) { _.mixin(o, www); } }; } function buildHtml(c) { return { wrapper: '', menu: '
' }; } function buildSelectors(classes) { var selectors = {}; _.each(classes, function(v, k) { selectors[k] = "." + v; }); return selectors; } function buildCss() { var css = { wrapper: { position: "relative", display: "inline-block" }, hint: { position: "absolute", top: "0", left: "0", borderColor: "transparent", boxShadow: "none", opacity: "1" }, input: { position: "relative", verticalAlign: "top", backgroundColor: "transparent" }, inputWithNoHint: { position: "relative", verticalAlign: "top" }, menu: { position: "absolute", top: "100%", left: "0", zIndex: "100", display: "none" }, ltr: { left: "0", right: "auto" }, rtl: { left: "auto", right: " 0" } }; if (_.isMsie()) { _.mixin(css.input, { backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" }); } return css; } }(); var EventBus = function() { "use strict"; var namespace, deprecationMap; namespace = "typeahead:"; deprecationMap = { render: "rendered", cursorchange: "cursorchanged", select: "selected", autocomplete: "autocompleted" }; function EventBus(o) { if (!o || !o.el) { $.error("EventBus initialized without el"); } this.$el = $(o.el); } _.mixin(EventBus.prototype, { _trigger: function(type, args) { var $e = $.Event(namespace + type); this.$el.trigger.call(this.$el, $e, args || []); return $e; }, before: function(type) { var args, $e; args = [].slice.call(arguments, 1); $e = this._trigger("before" + type, args); return $e.isDefaultPrevented(); }, trigger: function(type) { var deprecatedType; this._trigger(type, [].slice.call(arguments, 1)); if (deprecatedType = deprecationMap[type]) { this._trigger(deprecatedType, [].slice.call(arguments, 1)); } } }); return EventBus; }(); var EventEmitter = function() { "use strict"; var splitter = /\s+/, nextTick = getNextTick(); return { onSync: onSync, onAsync: onAsync, off: off, trigger: trigger }; function on(method, types, cb, context) { var type; if (!cb) { return this; } types = types.split(splitter); cb = context ? bindContext(cb, context) : cb; this._callbacks = this._callbacks || {}; while (type = types.shift()) { this._callbacks[type] = this._callbacks[type] || { sync: [], async: [] }; this._callbacks[type][method].push(cb); } return this; } function onAsync(types, cb, context) { return on.call(this, "async", types, cb, context); } function onSync(types, cb, context) { return on.call(this, "sync", types, cb, context); } function off(types) { var type; if (!this._callbacks) { return this; } types = types.split(splitter); while (type = types.shift()) { delete this._callbacks[type]; } return this; } function trigger(types) { var type, callbacks, args, syncFlush, asyncFlush; if (!this._callbacks) { return this; } types = types.split(splitter); args = [].slice.call(arguments, 1); while ((type = types.shift()) && (callbacks = this._callbacks[type])) { syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args)); asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args)); syncFlush() && nextTick(asyncFlush); } return this; } function getFlush(callbacks, context, args) { return flush; function flush() { var cancelled; for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) { cancelled = callbacks[i].apply(context, args) === false; } return !cancelled; } } function getNextTick() { var nextTickFn; if (window.setImmediate) { nextTickFn = function nextTickSetImmediate(fn) { setImmediate(function() { fn(); }); }; } else { nextTickFn = function nextTickSetTimeout(fn) { setTimeout(function() { fn(); }, 0); }; } return nextTickFn; } function bindContext(fn, context) { return fn.bind ? fn.bind(context) : function() { fn.apply(context, [].slice.call(arguments, 0)); }; } }(); var highlight = function(doc) { "use strict"; var defaults = { node: null, pattern: null, tagName: "strong", className: null, wordsOnly: false, caseSensitive: false, diacriticInsensitive: false }; var accented = { A: "[AaªÀ-Åà-åĀ-ąǍǎȀ-ȃȦȧᴬᵃḀḁẚẠ-ảₐ℀℁℻⒜Ⓐⓐ㍱-㍴㎀-㎄㎈㎉㎩-㎯㏂㏊㏟㏿Aa]", B: "[BbᴮᵇḂ-ḇℬ⒝Ⓑⓑ㍴㎅-㎇㏃㏈㏔㏝Bb]", C: "[CcÇçĆ-čᶜ℀ℂ℃℅℆ℭⅭⅽ⒞Ⓒⓒ㍶㎈㎉㎝㎠㎤㏄-㏇Cc]", D: "[DdĎďDŽ-džDZ-dzᴰᵈḊ-ḓⅅⅆⅮⅾ⒟Ⓓⓓ㋏㍲㍷-㍹㎗㎭-㎯㏅㏈Dd]", E: "[EeÈ-Ëè-ëĒ-ěȄ-ȇȨȩᴱᵉḘ-ḛẸ-ẽₑ℡ℯℰⅇ⒠Ⓔⓔ㉐㋍㋎Ee]", F: "[FfᶠḞḟ℉ℱ℻⒡Ⓕⓕ㎊-㎌㎙ff-fflFf]", G: "[GgĜ-ģǦǧǴǵᴳᵍḠḡℊ⒢Ⓖⓖ㋌㋍㎇㎍-㎏㎓㎬㏆㏉㏒㏿Gg]", H: "[HhĤĥȞȟʰᴴḢ-ḫẖℋ-ℎ⒣Ⓗⓗ㋌㍱㎐-㎔㏊㏋㏗Hh]", I: "[IiÌ-Ïì-ïĨ-İIJijǏǐȈ-ȋᴵᵢḬḭỈ-ịⁱℐℑℹⅈⅠ-ⅣⅥ-ⅨⅪⅫⅰ-ⅳⅵ-ⅸⅺⅻ⒤Ⓘⓘ㍺㏌㏕fiffiIi]", J: "[JjIJ-ĵLJ-njǰʲᴶⅉ⒥ⒿⓙⱼJj]", K: "[KkĶķǨǩᴷᵏḰ-ḵK⒦Ⓚⓚ㎄㎅㎉㎏㎑㎘㎞㎢㎦㎪㎸㎾㏀㏆㏍-㏏Kk]", L: "[LlĹ-ŀLJ-ljˡᴸḶḷḺ-ḽℒℓ℡Ⅼⅼ⒧Ⓛⓛ㋏㎈㎉㏐-㏓㏕㏖㏿flfflLl]", M: "[MmᴹᵐḾ-ṃ℠™ℳⅯⅿ⒨Ⓜⓜ㍷-㍹㎃㎆㎎㎒㎖㎙-㎨㎫㎳㎷㎹㎽㎿㏁㏂㏎㏐㏔-㏖㏘㏙㏞㏟Mm]", N: "[NnÑñŃ-ʼnNJ-njǸǹᴺṄ-ṋⁿℕ№⒩Ⓝⓝ㎁㎋㎚㎱㎵㎻㏌㏑Nn]", O: "[OoºÒ-Öò-öŌ-őƠơǑǒǪǫȌ-ȏȮȯᴼᵒỌ-ỏₒ℅№ℴ⒪Ⓞⓞ㍵㏇㏒㏖Oo]", P: "[PpᴾᵖṔ-ṗℙ⒫Ⓟⓟ㉐㍱㍶㎀㎊㎩-㎬㎰㎴㎺㏋㏗-㏚Pp]", Q: "[Qqℚ⒬Ⓠⓠ㏃Qq]", R: "[RrŔ-řȐ-ȓʳᴿᵣṘ-ṛṞṟ₨ℛ-ℝ⒭Ⓡⓡ㋍㍴㎭-㎯㏚㏛Rr]", S: "[SsŚ-šſȘșˢṠ-ṣ₨℁℠⒮Ⓢⓢ㎧㎨㎮-㎳㏛㏜stSs]", T: "[TtŢ-ťȚțᵀᵗṪ-ṱẗ℡™⒯Ⓣⓣ㉐㋏㎔㏏ſtstTt]", U: "[UuÙ-Üù-üŨ-ųƯưǓǔȔ-ȗᵁᵘᵤṲ-ṷỤ-ủ℆⒰Ⓤⓤ㍳㍺Uu]", V: "[VvᵛᵥṼ-ṿⅣ-Ⅷⅳ-ⅷ⒱Ⓥⓥⱽ㋎㍵㎴-㎹㏜㏞Vv]", W: "[WwŴŵʷᵂẀ-ẉẘ⒲Ⓦⓦ㎺-㎿㏝Ww]", X: "[XxˣẊ-ẍₓ℻Ⅸ-Ⅻⅸ-ⅻ⒳Ⓧⓧ㏓Xx]", Y: "[YyÝýÿŶ-ŸȲȳʸẎẏẙỲ-ỹ⒴Ⓨⓨ㏉Yy]", Z: "[ZzŹ-žDZ-dzᶻẐ-ẕℤℨ⒵Ⓩⓩ㎐-㎔Zz]" }; return function hightlight(o) { var regex; o = _.mixin({}, defaults, o); if (!o.node || !o.pattern) { return; } o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ]; regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly, o.diacriticInsensitive); traverse(o.node, hightlightTextNode); function hightlightTextNode(textNode) { var match, patternNode, wrapperNode; if (match = regex.exec(textNode.data)) { wrapperNode = doc.createElement(o.tagName); o.className && (wrapperNode.className = o.className); patternNode = textNode.splitText(match.index); patternNode.splitText(match[0].length); wrapperNode.appendChild(patternNode.cloneNode(true)); textNode.parentNode.replaceChild(wrapperNode, patternNode); } return !!match; } function traverse(el, hightlightTextNode) { var childNode, TEXT_NODE_TYPE = 3; for (var i = 0; i < el.childNodes.length; i++) { childNode = el.childNodes[i]; if (childNode.nodeType === TEXT_NODE_TYPE) { i += hightlightTextNode(childNode) ? 1 : 0; } else { traverse(childNode, hightlightTextNode); } } } }; function accent_replacer(chr) { return accented[chr.toUpperCase()] || chr; } function getRegex(patterns, caseSensitive, wordsOnly, diacriticInsensitive) { var escapedPatterns = [], regexStr; for (var i = 0, len = patterns.length; i < len; i++) { var escapedWord = _.escapeRegExChars(patterns[i]); if (diacriticInsensitive) { escapedWord = escapedWord.replace(/\S/g, accent_replacer); } escapedPatterns.push(escapedWord); } regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")"; return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i"); } }(window.document); var Input = function() { "use strict"; var specialKeyCodeMap; specialKeyCodeMap = { 9: "tab", 27: "esc", 37: "left", 39: "right", 13: "enter", 38: "up", 40: "down" }; function Input(o, www) { var id; o = o || {}; if (!o.input) { $.error("input is missing"); } www.mixin(this); this.$hint = $(o.hint); this.$input = $(o.input); this.$menu = $(o.menu); id = this.$input.attr("id") || _.guid(); this.$menu.attr("id", id + "_listbox"); this.$hint.attr({ "aria-hidden": true }); this.$input.attr({ "aria-owns": id + "_listbox", role: "combobox", "aria-autocomplete": "list", "aria-expanded": false }); this.query = this.$input.val(); this.queryWhenFocused = this.hasFocus() ? this.query : null; this.$overflowHelper = buildOverflowHelper(this.$input); this._checkLanguageDirection(); if (this.$hint.length === 0) { this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop; } this.onSync("cursorchange", this._updateDescendent); } Input.normalizeQuery = function(str) { return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " "); }; _.mixin(Input.prototype, EventEmitter, { _onBlur: function onBlur() { this.resetInputValue(); this.trigger("blurred"); }, _onFocus: function onFocus() { this.queryWhenFocused = this.query; this.trigger("focused"); }, _onKeydown: function onKeydown($e) { var keyName = specialKeyCodeMap[$e.which || $e.keyCode]; this._managePreventDefault(keyName, $e); if (keyName && this._shouldTrigger(keyName, $e)) { this.trigger(keyName + "Keyed", $e); } }, _onInput: function onInput() { this._setQuery(this.getInputValue()); this.clearHintIfInvalid(); this._checkLanguageDirection(); }, _managePreventDefault: function managePreventDefault(keyName, $e) { var preventDefault; switch (keyName) { case "up": case "down": preventDefault = !withModifier($e); break; default: preventDefault = false; } preventDefault && $e.preventDefault(); }, _shouldTrigger: function shouldTrigger(keyName, $e) { var trigger; switch (keyName) { case "tab": trigger = !withModifier($e); break; default: trigger = true; } return trigger; }, _checkLanguageDirection: function checkLanguageDirection() { var dir = (this.$input.css("direction") || "ltr").toLowerCase(); if (this.dir !== dir) { this.dir = dir; this.$hint.attr("dir", dir); this.trigger("langDirChanged", dir); } }, _setQuery: function setQuery(val, silent) { var areEquivalent, hasDifferentWhitespace; areEquivalent = areQueriesEquivalent(val, this.query); hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false; this.query = val; if (!silent && !areEquivalent) { this.trigger("queryChanged", this.query); } else if (!silent && hasDifferentWhitespace) { this.trigger("whitespaceChanged", this.query); } }, _updateDescendent: function updateDescendent(event, id) { this.$input.attr("aria-activedescendant", id); }, bind: function() { var that = this, onBlur, onFocus, onKeydown, onInput; onBlur = _.bind(this._onBlur, this); onFocus = _.bind(this._onFocus, this); onKeydown = _.bind(this._onKeydown, this); onInput = _.bind(this._onInput, this); this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown); if (!_.isMsie() || _.isMsie() > 9) { this.$input.on("input.tt", onInput); } else { this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { if (specialKeyCodeMap[$e.which || $e.keyCode]) { return; } _.defer(_.bind(that._onInput, that, $e)); }); } return this; }, focus: function focus() { this.$input.focus(); }, blur: function blur() { this.$input.blur(); }, getLangDir: function getLangDir() { return this.dir; }, getQuery: function getQuery() { return this.query || ""; }, setQuery: function setQuery(val, silent) { this.setInputValue(val); this._setQuery(val, silent); }, hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() { return this.query !== this.queryWhenFocused; }, getInputValue: function getInputValue() { return this.$input.val(); }, setInputValue: function setInputValue(value) { this.$input.val(value); this.clearHintIfInvalid(); this._checkLanguageDirection(); }, resetInputValue: function resetInputValue() { this.setInputValue(this.query); }, getHint: function getHint() { return this.$hint.val(); }, setHint: function setHint(value) { this.$hint.val(value); }, clearHint: function clearHint() { this.setHint(""); }, clearHintIfInvalid: function clearHintIfInvalid() { var val, hint, valIsPrefixOfHint, isValid; val = this.getInputValue(); hint = this.getHint(); valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow(); !isValid && this.clearHint(); }, hasFocus: function hasFocus() { return this.$input.is(":focus"); }, hasOverflow: function hasOverflow() { var constraint = this.$input.width() - 2; this.$overflowHelper.text(this.getInputValue()); return this.$overflowHelper.width() >= constraint; }, isCursorAtEnd: function() { var valueLength, selectionStart, range; valueLength = this.$input.val().length; selectionStart = this.$input[0].selectionStart; if (_.isNumber(selectionStart)) { return selectionStart === valueLength; } else if (document.selection) { range = document.selection.createRange(); range.moveStart("character", -valueLength); return valueLength === range.text.length; } return true; }, destroy: function destroy() { this.$hint.off(".tt"); this.$input.off(".tt"); this.$overflowHelper.remove(); this.$hint = this.$input = this.$overflowHelper = $("
"); }, setAriaExpanded: function setAriaExpanded(value) { this.$input.attr("aria-expanded", value); } }); return Input; function buildOverflowHelper($input) { return $('').css({ position: "absolute", visibility: "hidden", whiteSpace: "pre", fontFamily: $input.css("font-family"), fontSize: $input.css("font-size"), fontStyle: $input.css("font-style"), fontVariant: $input.css("font-variant"), fontWeight: $input.css("font-weight"), wordSpacing: $input.css("word-spacing"), letterSpacing: $input.css("letter-spacing"), textIndent: $input.css("text-indent"), textRendering: $input.css("text-rendering"), textTransform: $input.css("text-transform") }).insertAfter($input); } function areQueriesEquivalent(a, b) { return Input.normalizeQuery(a) === Input.normalizeQuery(b); } function withModifier($e) { return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey; } }(); var Dataset = function() { "use strict"; var keys, nameGenerator; keys = { dataset: "tt-selectable-dataset", val: "tt-selectable-display", obj: "tt-selectable-object" }; nameGenerator = _.getIdGenerator(); function Dataset(o, www) { o = o || {}; o.templates = o.templates || {}; o.templates.notFound = o.templates.notFound || o.templates.empty; if (!o.source) { $.error("missing source"); } if (!o.node) { $.error("missing node"); } if (o.name && !isValidName(o.name)) { $.error("invalid dataset name: " + o.name); } www.mixin(this); this.highlight = !!o.highlight; this.name = _.toStr(o.name || nameGenerator()); this.limit = o.limit || 5; this.displayFn = getDisplayFn(o.display || o.displayKey); this.templates = getTemplates(o.templates, this.displayFn); this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source; this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async; this._resetLastSuggestion(); this.$el = $(o.node).attr("role", "presentation").addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name); } Dataset.extractData = function extractData(el) { var $el = $(el); if ($el.data(keys.obj)) { return { dataset: $el.data(keys.dataset) || "", val: $el.data(keys.val) || "", obj: $el.data(keys.obj) || null }; } return null; }; _.mixin(Dataset.prototype, EventEmitter, { _overwrite: function overwrite(query, suggestions) { suggestions = suggestions || []; if (suggestions.length) { this._renderSuggestions(query, suggestions); } else if (this.async && this.templates.pending) { this._renderPending(query); } else if (!this.async && this.templates.notFound) { this._renderNotFound(query); } else { this._empty(); } this.trigger("rendered", suggestions, false, this.name); }, _append: function append(query, suggestions) { suggestions = suggestions || []; if (suggestions.length && this.$lastSuggestion.length) { this._appendSuggestions(query, suggestions); } else if (suggestions.length) { this._renderSuggestions(query, suggestions); } else if (!this.$lastSuggestion.length && this.templates.notFound) { this._renderNotFound(query); } this.trigger("rendered", suggestions, true, this.name); }, _renderSuggestions: function renderSuggestions(query, suggestions) { var $fragment; $fragment = this._getSuggestionsFragment(query, suggestions); this.$lastSuggestion = $fragment.children().last(); this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions)); }, _appendSuggestions: function appendSuggestions(query, suggestions) { var $fragment, $lastSuggestion; $fragment = this._getSuggestionsFragment(query, suggestions); $lastSuggestion = $fragment.children().last(); this.$lastSuggestion.after($fragment); this.$lastSuggestion = $lastSuggestion; }, _renderPending: function renderPending(query) { var template = this.templates.pending; this._resetLastSuggestion(); template && this.$el.html(template({ query: query, dataset: this.name })); }, _renderNotFound: function renderNotFound(query) { var template = this.templates.notFound; this._resetLastSuggestion(); template && this.$el.html(template({ query: query, dataset: this.name })); }, _empty: function empty() { this.$el.empty(); this._resetLastSuggestion(); }, _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) { var that = this, fragment; fragment = document.createDocumentFragment(); _.each(suggestions, function getSuggestionNode(suggestion) { var $el, context; context = that._injectQuery(query, suggestion); $el = $(that.templates.suggestion(context)).data(keys.dataset, that.name).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable); fragment.appendChild($el[0]); }); this.highlight && highlight({ className: this.classes.highlight, node: fragment, pattern: query }); return $(fragment); }, _getFooter: function getFooter(query, suggestions) { return this.templates.footer ? this.templates.footer({ query: query, suggestions: suggestions, dataset: this.name }) : null; }, _getHeader: function getHeader(query, suggestions) { return this.templates.header ? this.templates.header({ query: query, suggestions: suggestions, dataset: this.name }) : null; }, _resetLastSuggestion: function resetLastSuggestion() { this.$lastSuggestion = $(); }, _injectQuery: function injectQuery(query, obj) { return _.isObject(obj) ? _.mixin({ _query: query }, obj) : obj; }, update: function update(query) { var that = this, canceled = false, syncCalled = false, rendered = 0; this.cancel(); this.cancel = function cancel() { canceled = true; that.cancel = $.noop; that.async && that.trigger("asyncCanceled", query, that.name); }; this.source(query, sync, async); !syncCalled && sync([]); function sync(suggestions) { if (syncCalled) { return; } syncCalled = true; suggestions = (suggestions || []).slice(0, that.limit); rendered = suggestions.length; that._overwrite(query, suggestions); if (rendered < that.limit && that.async) { that.trigger("asyncRequested", query, that.name); } } function async(suggestions) { suggestions = suggestions || []; if (!canceled && rendered < that.limit) { that.cancel = $.noop; var idx = Math.abs(rendered - that.limit); rendered += idx; that._append(query, suggestions.slice(0, idx)); that.async && that.trigger("asyncReceived", query, that.name); } } }, cancel: $.noop, clear: function clear() { this._empty(); this.cancel(); this.trigger("cleared"); }, isEmpty: function isEmpty() { return this.$el.is(":empty"); }, destroy: function destroy() { this.$el = $("
"); } }); return Dataset; function getDisplayFn(display) { display = display || _.stringify; return _.isFunction(display) ? display : displayFn; function displayFn(obj) { return obj[display]; } } function getTemplates(templates, displayFn) { return { notFound: templates.notFound && _.templatify(templates.notFound), pending: templates.pending && _.templatify(templates.pending), header: templates.header && _.templatify(templates.header), footer: templates.footer && _.templatify(templates.footer), suggestion: templates.suggestion ? userSuggestionTemplate : suggestionTemplate }; function userSuggestionTemplate(context) { var template = templates.suggestion; return $(template(context)).attr("id", _.guid()); } function suggestionTemplate(context) { return $('
').attr("id", _.guid()).text(displayFn(context)); } } function isValidName(str) { return /^[_a-zA-Z0-9-]+$/.test(str); } }(); var Menu = function() { "use strict"; function Menu(o, www) { var that = this; o = o || {}; if (!o.node) { $.error("node is required"); } www.mixin(this); this.$node = $(o.node); this.query = null; this.datasets = _.map(o.datasets, initializeDataset); function initializeDataset(oDataset) { var node = that.$node.find(oDataset.node).first(); oDataset.node = node.length ? node : $("
").appendTo(that.$node); return new Dataset(oDataset, www); } } _.mixin(Menu.prototype, EventEmitter, { _onSelectableClick: function onSelectableClick($e) { this.trigger("selectableClicked", $($e.currentTarget)); }, _onRendered: function onRendered(type, dataset, suggestions, async) { this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); this.trigger("datasetRendered", dataset, suggestions, async); }, _onCleared: function onCleared() { this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); this.trigger("datasetCleared"); }, _propagate: function propagate() { this.trigger.apply(this, arguments); }, _allDatasetsEmpty: function allDatasetsEmpty() { return _.every(this.datasets, _.bind(function isDatasetEmpty(dataset) { var isEmpty = dataset.isEmpty(); this.$node.attr("aria-expanded", !isEmpty); return isEmpty; }, this)); }, _getSelectables: function getSelectables() { return this.$node.find(this.selectors.selectable); }, _removeCursor: function _removeCursor() { var $selectable = this.getActiveSelectable(); $selectable && $selectable.removeClass(this.classes.cursor); }, _ensureVisible: function ensureVisible($el) { var elTop, elBottom, nodeScrollTop, nodeHeight; elTop = $el.position().top; elBottom = elTop + $el.outerHeight(true); nodeScrollTop = this.$node.scrollTop(); nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10); if (elTop < 0) { this.$node.scrollTop(nodeScrollTop + elTop); } else if (nodeHeight < elBottom) { this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight)); } }, bind: function() { var that = this, onSelectableClick; onSelectableClick = _.bind(this._onSelectableClick, this); this.$node.on("click.tt", this.selectors.selectable, onSelectableClick); this.$node.on("mouseover", this.selectors.selectable, function() { that.setCursor($(this)); }); this.$node.on("mouseleave", function() { that._removeCursor(); }); _.each(this.datasets, function(dataset) { dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that); }); return this; }, isOpen: function isOpen() { return this.$node.hasClass(this.classes.open); }, open: function open() { this.$node.scrollTop(0); this.$node.addClass(this.classes.open); }, close: function close() { this.$node.attr("aria-expanded", false); this.$node.removeClass(this.classes.open); this._removeCursor(); }, setLanguageDirection: function setLanguageDirection(dir) { this.$node.attr("dir", dir); }, selectableRelativeToCursor: function selectableRelativeToCursor(delta) { var $selectables, $oldCursor, oldIndex, newIndex; $oldCursor = this.getActiveSelectable(); $selectables = this._getSelectables(); oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1; newIndex = oldIndex + delta; newIndex = (newIndex + 1) % ($selectables.length + 1) - 1; newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex; return newIndex === -1 ? null : $selectables.eq(newIndex); }, setCursor: function setCursor($selectable) { this._removeCursor(); if ($selectable = $selectable && $selectable.first()) { $selectable.addClass(this.classes.cursor); this._ensureVisible($selectable); } }, getSelectableData: function getSelectableData($el) { return $el && $el.length ? Dataset.extractData($el) : null; }, getActiveSelectable: function getActiveSelectable() { var $selectable = this._getSelectables().filter(this.selectors.cursor).first(); return $selectable.length ? $selectable : null; }, getTopSelectable: function getTopSelectable() { var $selectable = this._getSelectables().first(); return $selectable.length ? $selectable : null; }, update: function update(query) { var isValidUpdate = query !== this.query; if (isValidUpdate) { this.query = query; _.each(this.datasets, updateDataset); } return isValidUpdate; function updateDataset(dataset) { dataset.update(query); } }, empty: function empty() { _.each(this.datasets, clearDataset); this.query = null; this.$node.addClass(this.classes.empty); function clearDataset(dataset) { dataset.clear(); } }, destroy: function destroy() { this.$node.off(".tt"); this.$node = $("
"); _.each(this.datasets, destroyDataset); function destroyDataset(dataset) { dataset.destroy(); } } }); return Menu; }(); var Status = function() { "use strict"; function Status(options) { this.$el = $("", { role: "status", "aria-live": "polite" }).css({ position: "absolute", padding: "0", border: "0", height: "1px", width: "1px", "margin-bottom": "-1px", "margin-right": "-1px", overflow: "hidden", clip: "rect(0 0 0 0)", "white-space": "nowrap" }); options.$input.after(this.$el); _.each(options.menu.datasets, _.bind(function(dataset) { if (dataset.onSync) { dataset.onSync("rendered", _.bind(this.update, this)); dataset.onSync("cleared", _.bind(this.cleared, this)); } }, this)); } _.mixin(Status.prototype, { update: function update(event, suggestions) { var length = suggestions.length; var words; if (length === 1) { words = { result: "result", is: "is" }; } else { words = { result: "results", is: "are" }; } this.$el.text(length + " " + words.result + " " + words.is + " available, use up and down arrow keys to navigate."); }, cleared: function() { this.$el.text(""); } }); return Status; }(); var DefaultMenu = function() { "use strict"; var s = Menu.prototype; function DefaultMenu() { Menu.apply(this, [].slice.call(arguments, 0)); } _.mixin(DefaultMenu.prototype, Menu.prototype, { open: function open() { !this._allDatasetsEmpty() && this._show(); return s.open.apply(this, [].slice.call(arguments, 0)); }, close: function close() { this._hide(); return s.close.apply(this, [].slice.call(arguments, 0)); }, _onRendered: function onRendered() { if (this._allDatasetsEmpty()) { this._hide(); } else { this.isOpen() && this._show(); } return s._onRendered.apply(this, [].slice.call(arguments, 0)); }, _onCleared: function onCleared() { if (this._allDatasetsEmpty()) { this._hide(); } else { this.isOpen() && this._show(); } return s._onCleared.apply(this, [].slice.call(arguments, 0)); }, setLanguageDirection: function setLanguageDirection(dir) { this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl); return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0)); }, _hide: function hide() { this.$node.hide(); }, _show: function show() { this.$node.css("display", "block"); } }); return DefaultMenu; }(); var Typeahead = function() { "use strict"; function Typeahead(o, www) { var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged; o = o || {}; if (!o.input) { $.error("missing input"); } if (!o.menu) { $.error("missing menu"); } if (!o.eventBus) { $.error("missing event bus"); } www.mixin(this); this.eventBus = o.eventBus; this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; this.input = o.input; this.menu = o.menu; this.enabled = true; this.autoselect = !!o.autoselect; this.active = false; this.input.hasFocus() && this.activate(); this.dir = this.input.getLangDir(); this._hacks(); this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this); onFocused = c(this, "activate", "open", "_onFocused"); onBlurred = c(this, "deactivate", "_onBlurred"); onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed"); onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed"); onEscKeyed = c(this, "isActive", "_onEscKeyed"); onUpKeyed = c(this, "isActive", "open", "_onUpKeyed"); onDownKeyed = c(this, "isActive", "open", "_onDownKeyed"); onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed"); onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed"); onQueryChanged = c(this, "_openIfActive", "_onQueryChanged"); onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged"); this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this); } _.mixin(Typeahead.prototype, { _hacks: function hacks() { var $input, $menu; $input = this.input.$input || $("
"); $menu = this.menu.$node || $("
"); $input.on("blur.tt", function($e) { var active, isActive, hasActive; active = document.activeElement; isActive = $menu.is(active); hasActive = $menu.has(active).length > 0; if (_.isMsie() && (isActive || hasActive)) { $e.preventDefault(); $e.stopImmediatePropagation(); _.defer(function() { $input.focus(); }); } }); $menu.on("mousedown.tt", function($e) { $e.preventDefault(); }); }, _onSelectableClicked: function onSelectableClicked(type, $el) { this.select($el); }, _onDatasetCleared: function onDatasetCleared() { this._updateHint(); }, _onDatasetRendered: function onDatasetRendered(type, suggestions, async, dataset) { this._updateHint(); if (this.autoselect) { var cursorClass = this.selectors.cursor.substr(1); this.menu.$node.find(this.selectors.suggestion).first().addClass(cursorClass); } this.eventBus.trigger("render", suggestions, async, dataset); }, _onAsyncRequested: function onAsyncRequested(type, dataset, query) { this.eventBus.trigger("asyncrequest", query, dataset); }, _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) { this.eventBus.trigger("asynccancel", query, dataset); }, _onAsyncReceived: function onAsyncReceived(type, dataset, query) { this.eventBus.trigger("asyncreceive", query, dataset); }, _onFocused: function onFocused() { this._minLengthMet() && this.menu.update(this.input.getQuery()); }, _onBlurred: function onBlurred() { if (this.input.hasQueryChangedSinceLastFocus()) { this.eventBus.trigger("change", this.input.getQuery()); } }, _onEnterKeyed: function onEnterKeyed(type, $e) { var $selectable; if ($selectable = this.menu.getActiveSelectable()) { if (this.select($selectable)) { $e.preventDefault(); $e.stopPropagation(); } } else if (this.autoselect) { if (this.select(this.menu.getTopSelectable())) { $e.preventDefault(); $e.stopPropagation(); } } }, _onTabKeyed: function onTabKeyed(type, $e) { var $selectable; if ($selectable = this.menu.getActiveSelectable()) { this.select($selectable) && $e.preventDefault(); } else if (this.autoselect) { if ($selectable = this.menu.getTopSelectable()) { this.autocomplete($selectable) && $e.preventDefault(); } } }, _onEscKeyed: function onEscKeyed() { this.close(); }, _onUpKeyed: function onUpKeyed() { this.moveCursor(-1); }, _onDownKeyed: function onDownKeyed() { this.moveCursor(+1); }, _onLeftKeyed: function onLeftKeyed() { if (this.dir === "rtl" && this.input.isCursorAtEnd()) { this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable()); } }, _onRightKeyed: function onRightKeyed() { if (this.dir === "ltr" && this.input.isCursorAtEnd()) { this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable()); } }, _onQueryChanged: function onQueryChanged(e, query) { this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty(); }, _onWhitespaceChanged: function onWhitespaceChanged() { this._updateHint(); }, _onLangDirChanged: function onLangDirChanged(e, dir) { if (this.dir !== dir) { this.dir = dir; this.menu.setLanguageDirection(dir); } }, _openIfActive: function openIfActive() { this.isActive() && this.open(); }, _minLengthMet: function minLengthMet(query) { query = _.isString(query) ? query : this.input.getQuery() || ""; return query.length >= this.minLength; }, _updateHint: function updateHint() { var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match; $selectable = this.menu.getTopSelectable(); data = this.menu.getSelectableData($selectable); val = this.input.getInputValue(); if (data && !_.isBlankString(val) && !this.input.hasOverflow()) { query = Input.normalizeQuery(val); escapedQuery = _.escapeRegExChars(query); frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i"); match = frontMatchRegEx.exec(data.val); match && this.input.setHint(val + match[1]); } else { this.input.clearHint(); } }, isEnabled: function isEnabled() { return this.enabled; }, enable: function enable() { this.enabled = true; }, disable: function disable() { this.enabled = false; }, isActive: function isActive() { return this.active; }, activate: function activate() { if (this.isActive()) { return true; } else if (!this.isEnabled() || this.eventBus.before("active")) { return false; } else { this.active = true; this.eventBus.trigger("active"); return true; } }, deactivate: function deactivate() { if (!this.isActive()) { return true; } else if (this.eventBus.before("idle")) { return false; } else { this.active = false; this.close(); this.eventBus.trigger("idle"); return true; } }, isOpen: function isOpen() { return this.menu.isOpen(); }, open: function open() { if (!this.isOpen() && !this.eventBus.before("open")) { this.input.setAriaExpanded(true); this.menu.open(); this._updateHint(); this.eventBus.trigger("open"); } return this.isOpen(); }, close: function close() { if (this.isOpen() && !this.eventBus.before("close")) { this.input.setAriaExpanded(false); this.menu.close(); this.input.clearHint(); this.input.resetInputValue(); this.eventBus.trigger("close"); } return !this.isOpen(); }, setVal: function setVal(val) { this.input.setQuery(_.toStr(val)); }, getVal: function getVal() { return this.input.getQuery(); }, select: function select($selectable) { var data = this.menu.getSelectableData($selectable); if (data && !this.eventBus.before("select", data.obj, data.dataset)) { this.input.setQuery(data.val, true); this.eventBus.trigger("select", data.obj, data.dataset); this.close(); return true; } return false; }, autocomplete: function autocomplete($selectable) { var query, data, isValid; query = this.input.getQuery(); data = this.menu.getSelectableData($selectable); isValid = data && query !== data.val; if (isValid && !this.eventBus.before("autocomplete", data.obj, data.dataset)) { this.input.setQuery(data.val); this.eventBus.trigger("autocomplete", data.obj, data.dataset); return true; } return false; }, moveCursor: function moveCursor(delta) { var query, $candidate, data, suggestion, datasetName, cancelMove, id; query = this.input.getQuery(); $candidate = this.menu.selectableRelativeToCursor(delta); data = this.menu.getSelectableData($candidate); suggestion = data ? data.obj : null; datasetName = data ? data.dataset : null; id = $candidate ? $candidate.attr("id") : null; this.input.trigger("cursorchange", id); cancelMove = this._minLengthMet() && this.menu.update(query); if (!cancelMove && !this.eventBus.before("cursorchange", suggestion, datasetName)) { this.menu.setCursor($candidate); if (data) { if (typeof data.val === "string") { this.input.setInputValue(data.val); } } else { this.input.resetInputValue(); this._updateHint(); } this.eventBus.trigger("cursorchange", suggestion, datasetName); return true; } return false; }, destroy: function destroy() { this.input.destroy(); this.menu.destroy(); } }); return Typeahead; function c(ctx) { var methods = [].slice.call(arguments, 1); return function() { var args = [].slice.call(arguments); _.each(methods, function(method) { return ctx[method].apply(ctx, args); }); }; } }(); (function() { "use strict"; var old, keys, methods; old = $.fn.typeahead; keys = { www: "tt-www", attrs: "tt-attrs", typeahead: "tt-typeahead" }; methods = { initialize: function initialize(o, datasets) { var www; datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1); o = o || {}; www = WWW(o.classNames); return this.each(attach); function attach() { var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, status, typeahead, MenuConstructor; _.each(datasets, function(d) { d.highlight = !!o.highlight; }); $input = $(this); $wrapper = $(www.html.wrapper); $hint = $elOrNull(o.hint); $menu = $elOrNull(o.menu); defaultHint = o.hint !== false && !$hint; defaultMenu = o.menu !== false && !$menu; defaultHint && ($hint = buildHintFromInput($input, www)); defaultMenu && ($menu = $(www.html.menu).css(www.css.menu)); $hint && $hint.val(""); $input = prepInput($input, www); if (defaultHint || defaultMenu) { $wrapper.css(www.css.wrapper); $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint); $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null); } MenuConstructor = defaultMenu ? DefaultMenu : Menu; eventBus = new EventBus({ el: $input }); input = new Input({ hint: $hint, input: $input, menu: $menu }, www); menu = new MenuConstructor({ node: $menu, datasets: datasets }, www); status = new Status({ $input: $input, menu: menu }); typeahead = new Typeahead({ input: input, menu: menu, eventBus: eventBus, minLength: o.minLength, autoselect: o.autoselect }, www); $input.data(keys.www, www); $input.data(keys.typeahead, typeahead); } }, isEnabled: function isEnabled() { var enabled; ttEach(this.first(), function(t) { enabled = t.isEnabled(); }); return enabled; }, enable: function enable() { ttEach(this, function(t) { t.enable(); }); return this; }, disable: function disable() { ttEach(this, function(t) { t.disable(); }); return this; }, isActive: function isActive() { var active; ttEach(this.first(), function(t) { active = t.isActive(); }); return active; }, activate: function activate() { ttEach(this, function(t) { t.activate(); }); return this; }, deactivate: function deactivate() { ttEach(this, function(t) { t.deactivate(); }); return this; }, isOpen: function isOpen() { var open; ttEach(this.first(), function(t) { open = t.isOpen(); }); return open; }, open: function open() { ttEach(this, function(t) { t.open(); }); return this; }, close: function close() { ttEach(this, function(t) { t.close(); }); return this; }, select: function select(el) { var success = false, $el = $(el); ttEach(this.first(), function(t) { success = t.select($el); }); return success; }, autocomplete: function autocomplete(el) { var success = false, $el = $(el); ttEach(this.first(), function(t) { success = t.autocomplete($el); }); return success; }, moveCursor: function moveCursoe(delta) { var success = false; ttEach(this.first(), function(t) { success = t.moveCursor(delta); }); return success; }, val: function val(newVal) { var query; if (!arguments.length) { ttEach(this.first(), function(t) { query = t.getVal(); }); return query; } else { ttEach(this, function(t) { t.setVal(_.toStr(newVal)); }); return this; } }, destroy: function destroy() { ttEach(this, function(typeahead, $input) { revert($input); typeahead.destroy(); }); return this; } }; $.fn.typeahead = function(method) { if (methods[method]) { return methods[method].apply(this, [].slice.call(arguments, 1)); } else { return methods.initialize.apply(this, arguments); } }; $.fn.typeahead.noConflict = function noConflict() { $.fn.typeahead = old; return this; }; function ttEach($els, fn) { $els.each(function() { var $input = $(this), typeahead; (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input); }); } function buildHintFromInput($input, www) { return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop({ readonly: true, required: false }).removeAttr("id name placeholder").removeClass("required").attr({ spellcheck: "false", tabindex: -1 }); } function prepInput($input, www) { $input.data(keys.attrs, { dir: $input.attr("dir"), autocomplete: $input.attr("autocomplete"), spellcheck: $input.attr("spellcheck"), style: $input.attr("style") }); $input.addClass(www.classes.input).attr({ spellcheck: false }); try { !$input.attr("dir") && $input.attr("dir", "auto"); } catch (e) {} return $input; } function getBackgroundStyles($el) { return { backgroundAttachment: $el.css("background-attachment"), backgroundClip: $el.css("background-clip"), backgroundColor: $el.css("background-color"), backgroundImage: $el.css("background-image"), backgroundOrigin: $el.css("background-origin"), backgroundPosition: $el.css("background-position"), backgroundRepeat: $el.css("background-repeat"), backgroundSize: $el.css("background-size") }; } function revert($input) { var www, $wrapper; www = $input.data(keys.www); $wrapper = $input.parent().filter(www.selectors.wrapper); _.each($input.data(keys.attrs), function(val, key) { _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); }); $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input); if ($wrapper.length) { $input.detach().insertAfter($wrapper); $wrapper.remove(); } } function $elOrNull(obj) { var isValid, $el; isValid = _.isJQuery(obj) || _.isElement(obj); $el = isValid ? $(obj).first() : []; return $el.length ? $el : null; } })(); }); ================================================ FILE: docs/docsets/SwiftJWT.docset/Contents/Resources/Documents/search.json ================================================ {"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV11descriptionSSvp":{"name":"description","abstract":"

The human readable description of the ValidateClaimsResult

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV7successACvpZ":{"name":"success","abstract":"

Successful validation.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV17invalidExpirationACvpZ":{"name":"invalidExpiration","abstract":"

Invalid Expiration claim.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV7expiredACvpZ":{"name":"expired","abstract":"

Expired token: expiration time claim is in the past.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV16invalidNotBeforeACvpZ":{"name":"invalidNotBefore","abstract":"

Invalid Not Before claim.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV9notBeforeACvpZ":{"name":"notBefore","abstract":"

Not Before claim is in the future.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV15invalidIssuedAtACvpZ":{"name":"invalidIssuedAt","abstract":"

Invalid Issued At claim.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV8issuedAtACvpZ":{"name":"issuedAt","abstract":"

Issued At claim is in the future.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV2eeoiySbAC_ACtFZ":{"name":"==(_:_:)","abstract":"

Check if two ValidateClaimsResults are equal. Required for the Equatable protocol

","parent_name":"ValidateClaimsResult"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5rs2569publicKeyAC10Foundation4DataV_tFZ":{"name":"rs256(publicKey:)","abstract":"

Initialize a JWTVerifier using the RSA 256 bits algorithm and the provided publicKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5rs3849publicKeyAC10Foundation4DataV_tFZ":{"name":"rs384(publicKey:)","abstract":"

Initialize a JWTVerifier using the RSA 384 bits algorithm and the provided publicKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5rs5129publicKeyAC10Foundation4DataV_tFZ":{"name":"rs512(publicKey:)","abstract":"

Initialize a JWTVerifier using the RSA 512 bits algorithm and the provided publicKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5rs25611certificateAC10Foundation4DataV_tFZ":{"name":"rs256(certificate:)","abstract":"

Initialize a JWTVerifier using the RSA 256 bits algorithm and the provided certificate.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5rs38411certificateAC10Foundation4DataV_tFZ":{"name":"rs384(certificate:)","abstract":"

Initialize a JWTVerifier using the RSA 384 bits algorithm and the provided certificate.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5rs51211certificateAC10Foundation4DataV_tFZ":{"name":"rs512(certificate:)","abstract":"

Initialize a JWTVerifier using the RSA 512 bits algorithm and the provided certificate.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5ps2569publicKeyAC10Foundation4DataV_tFZ":{"name":"ps256(publicKey:)","abstract":"

Initialize a JWTVerifier using the RSA-PSS 256 bits algorithm and the provided publicKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5ps3849publicKeyAC10Foundation4DataV_tFZ":{"name":"ps384(publicKey:)","abstract":"

Initialize a JWTVerifier using the RSA-PSS 384 bits algorithm and the provided publicKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5ps5129publicKeyAC10Foundation4DataV_tFZ":{"name":"ps512(publicKey:)","abstract":"

Initialize a JWTVerifier using the RSA-PSS 512 bits algorithm and the provided publicKey.","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5hs2563keyAC10Foundation4DataV_tFZ":{"name":"hs256(key:)","abstract":"

Initialize a JWTSigner using the HMAC 256 bits algorithm and the provided privateKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5hs3843keyAC10Foundation4DataV_tFZ":{"name":"hs384(key:)","abstract":"

Initialize a JWTSigner using the HMAC 384 bits algorithm and the provided privateKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5hs5123keyAC10Foundation4DataV_tFZ":{"name":"hs512(key:)","abstract":"

Initialize a JWTSigner using the HMAC 512 bits algorithm and the provided privateKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5es2569publicKeyAC10Foundation4DataV_tFZ":{"name":"es256(publicKey:)","abstract":"

Initialize a JWTVerifier using the ECDSA SHA 256 algorithm and the provided public key.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5es3849publicKeyAC10Foundation4DataV_tFZ":{"name":"es384(publicKey:)","abstract":"

Initialize a JWTVerifier using the ECDSA SHA 384 algorithm and the provided public key.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5es5129publicKeyAC10Foundation4DataV_tFZ":{"name":"es512(publicKey:)","abstract":"

Initialize a JWTVerifier using the ECDSA SHA 512 algorithm and the provided public key.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV4noneACvpZ":{"name":"none","abstract":"

Initialize a JWTVerifier that will always return true when verifying the JWT. This is equivelent to using the “none” alg header.

","parent_name":"JWTVerifier"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5rs25610privateKeyAC10Foundation4DataV_tFZ":{"name":"rs256(privateKey:)","abstract":"

Initialize a JWTSigner using the RSA 256 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5rs38410privateKeyAC10Foundation4DataV_tFZ":{"name":"rs384(privateKey:)","abstract":"

Initialize a JWTSigner using the RSA 384 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5rs51210privateKeyAC10Foundation4DataV_tFZ":{"name":"rs512(privateKey:)","abstract":"

Initialize a JWTSigner using the RSA 512 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5ps25610privateKeyAC10Foundation4DataV_tFZ":{"name":"ps256(privateKey:)","abstract":"

Initialize a JWTSigner using the RSA-PSS 256 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5ps38410privateKeyAC10Foundation4DataV_tFZ":{"name":"ps384(privateKey:)","abstract":"

Initialize a JWTSigner using the RSA-PSS 384 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5ps51210privateKeyAC10Foundation4DataV_tFZ":{"name":"ps512(privateKey:)","abstract":"

Initialize a JWTSigner using the RSA-PSS 512 bits algorithm and the provided privateKey.","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5hs2563keyAC10Foundation4DataV_tFZ":{"name":"hs256(key:)","abstract":"

Initialize a JWTSigner using the HMAC 256 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5hs3843keyAC10Foundation4DataV_tFZ":{"name":"hs384(key:)","abstract":"

Initialize a JWTSigner using the HMAC 384 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5hs5123keyAC10Foundation4DataV_tFZ":{"name":"hs512(key:)","abstract":"

Initialize a JWTSigner using the HMAC 512 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5es25610privateKeyAC10Foundation4DataV_tFZ":{"name":"es256(privateKey:)","abstract":"

Initialize a JWTSigner using the ECDSA SHA256 algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5es38410privateKeyAC10Foundation4DataV_tFZ":{"name":"es384(privateKey:)","abstract":"

Initialize a JWTSigner using the ECDSA SHA384 algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5es51210privateKeyAC10Foundation4DataV_tFZ":{"name":"es512(privateKey:)","abstract":"

Initialize a JWTSigner using the ECDSA SHA512 algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV4noneACvpZ":{"name":"none","abstract":"

Initialize a JWTSigner that will not sign the JWT. This is equivelent to using the “none” alg header.

","parent_name":"JWTSigner"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV20localizedDescriptionSSvp":{"name":"localizedDescription","abstract":"

A human readable description of the error.

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV16invalidJWTStringACvpZ":{"name":"invalidJWTString","abstract":"

Error when an invalid JWT String is provided

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV18failedVerificationACvpZ":{"name":"failedVerification","abstract":"

Error when the JWT signiture fails verification.

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV14osVersionToLowACvpZ":{"name":"osVersionToLow","abstract":"

Error when using RSA encryption with an OS version that is too low.

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV17invalidPrivateKeyACvpZ":{"name":"invalidPrivateKey","abstract":"

Error when an invalid private key is provided for RSA encryption.

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV15invalidUTF8DataACvpZ":{"name":"invalidUTF8Data","abstract":"

Error when the provided Data cannot be decoded to a String

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV12invalidKeyIDACvpZ":{"name":"invalidKeyID","abstract":"

Error when the KeyID field kid in the JWT header fails to generate a JWTSigner or JWTVerifier

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV17missingPEMHeadersACvpZ":{"name":"missingPEMHeaders","abstract":"

Error when a PEM string is provided without the expected PEM headers/footers. (e.g. —–BEGIN PRIVATE KEY—–)

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV2eeoiySbAC_ACtFZ":{"name":"==(_:_:)","abstract":"

Function to check if JWTErrors are equal. Required for equatable protocol.

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV2teoiySbAC_s5Error_ptFZ":{"name":"~=(_:_:)","abstract":"

Function to enable pattern matching against generic Errors.

","parent_name":"JWTError"},"Structs/JWT.html#/s:8SwiftJWT0B0V6headerAA6HeaderVvp":{"name":"header","abstract":"

The JWT header.

","parent_name":"JWT"},"Structs/JWT.html#/s:8SwiftJWT0B0V6claimsxvp":{"name":"claims","abstract":"

The JWT claims

","parent_name":"JWT"},"Structs/JWT.html#/s:8SwiftJWT0B0V6header6claimsACyxGAA6HeaderV_xtcfc":{"name":"init(header:claims:)","abstract":"

Initialize a JWT instance from a Header and Claims.

","parent_name":"JWT"},"Structs/JWT.html#/s:8SwiftJWT0B0V9jwtString8verifierACyxGSS_AA11JWTVerifierVtKcfc":{"name":"init(jwtString:verifier:)","abstract":"

Initialize a JWT instance from a JWT String.","parent_name":"JWT"},"Structs/JWT.html#/s:8SwiftJWT0B0V4sign5usingSSAA9JWTSignerV_tKF":{"name":"sign(using:)","abstract":"

Sign the JWT using the given algorithm and encode the header, claims and signature as a JWT String.

","parent_name":"JWT"},"Structs/JWT.html#/s:8SwiftJWT0B0V6verify_5usingSbSS_AA11JWTVerifierVtFZ":{"name":"verify(_:using:)","abstract":"

Verify the signature of the encoded JWT using the given algorithm.

","parent_name":"JWT"},"Structs/JWT.html#/s:8SwiftJWT0B0V14validateClaims6leewayAA08ValidateD6ResultVSd_tF":{"name":"validateClaims(leeway:)","abstract":"

Validate the time based standard JWT claims.","parent_name":"JWT"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3typSSSgvp":{"name":"typ","abstract":"

Type Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3algSSSgvp":{"name":"alg","abstract":"

Algorithm Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3jkuSSSgvp":{"name":"jku","abstract":"

JSON Web Token Set URL Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3jwkSSSgvp":{"name":"jwk","abstract":"

JSON Web Key Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3kidSSSgvp":{"name":"kid","abstract":"

Key ID Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3x5uSSSgvp":{"name":"x5u","abstract":"

X.509 URL Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3x5cSaySSGSgvp":{"name":"x5c","abstract":"

X.509 Certificate Chain Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3x5tSSSgvp":{"name":"x5t","abstract":"

X.509 Certificate SHA-1 Thumbprint Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV7x5tS256SSSgvp":{"name":"x5tS256","abstract":"

X.509 Certificate SHA-256 Thumbprint Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3ctySSSgvp":{"name":"cty","abstract":"

Content Type Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV4critSaySSGSgvp":{"name":"crit","abstract":"

Critical Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3typ3jku3jwk3kid3x5u3x5c3x5t0J4S2563cty4critACSSSg_A4NSaySSGSgA3nPtcfc":{"name":"init(typ:jku:jwk:kid:x5u:x5c:x5t:x5tS256:cty:crit:)","abstract":"

Initialize a Header instance.

","parent_name":"Header"},"Structs/AddressClaim.html#/s:8SwiftJWT12AddressClaimV9formattedSSSgvp":{"name":"formatted","abstract":"

Full mailing address, formatted for display or use on a mailing label. This field MAY contain multiple lines, separated by newlines. Newlines can be represented either as a carriage return/line feed pair (“\\r\\n”) or as a single line feed character (“\\n”).

","parent_name":"AddressClaim"},"Structs/AddressClaim.html#/s:8SwiftJWT12AddressClaimV14street_addressSSSgvp":{"name":"street_address","abstract":"

Full street address component, which MAY include house number, street name, Post Office Box, and multi-line extended street address information. This field MAY contain multiple lines, separated by newlines. Newlines can be represented either as a carriage return/line feed pair (“\\r\\n”) or as a single line feed character (“\\n”).

","parent_name":"AddressClaim"},"Structs/AddressClaim.html#/s:8SwiftJWT12AddressClaimV8localitySSSgvp":{"name":"locality","abstract":"

City or locality component.

","parent_name":"AddressClaim"},"Structs/AddressClaim.html#/s:8SwiftJWT12AddressClaimV6regionSSSgvp":{"name":"region","abstract":"

State, province, prefecture, or region component.

","parent_name":"AddressClaim"},"Structs/AddressClaim.html#/s:8SwiftJWT12AddressClaimV11postal_codeSSSgvp":{"name":"postal_code","abstract":"

Zip code or postal code component.

","parent_name":"AddressClaim"},"Structs/AddressClaim.html#/s:8SwiftJWT12AddressClaimV7countrySSSgvp":{"name":"country","abstract":"

Country name component.

","parent_name":"AddressClaim"},"Structs/AddressClaim.html":{"name":"AddressClaim","abstract":"

Struct representing an AddressClaim as defined in the OpenID specs.

"},"Structs/Header.html":{"name":"Header","abstract":"

A representation of a JSON Web Token header."},"Structs/JWT.html":{"name":"JWT","abstract":"

A struct representing the Header and Claims of a JSON Web Token.

"},"Structs/JWTError.html":{"name":"JWTError","abstract":"

A struct representing the different errors that can be thrown by SwiftJWT

"},"Structs/JWTSigner.html":{"name":"JWTSigner","abstract":"

A struct that will be used to sign the JWT Header and Claims and generate a signed JWT."},"Structs/JWTVerifier.html":{"name":"JWTVerifier","abstract":"

A struct that will be used to verify the signature of a JWT is valid for the provided Header and Claims."},"Structs/ValidateClaimsResult.html":{"name":"ValidateClaimsResult","abstract":"

ValidateClaimsResult list the possible results of a call to JWT.validateClaims method."},"Protocols/Claims.html#/s:8SwiftJWT6ClaimsP3exp10Foundation4DateVSgvp":{"name":"exp","abstract":"

The “exp” (expiration time) claim identifies the expiration time on","parent_name":"Claims"},"Protocols/Claims.html#/s:8SwiftJWT6ClaimsP3nbf10Foundation4DateVSgvp":{"name":"nbf","abstract":"

The “nbf” (not before) claim identifies the time before which the JWT","parent_name":"Claims"},"Protocols/Claims.html#/s:8SwiftJWT6ClaimsP3iat10Foundation4DateVSgvp":{"name":"iat","abstract":"

The “iat” (issued at) claim identifies the time at which the JWT was","parent_name":"Claims"},"Protocols/Claims.html#/s:8SwiftJWT6ClaimsP6encodeSSyKF":{"name":"encode()","abstract":"

Encode the Claim object as a Base64 String.

","parent_name":"Claims"},"Protocols/Claims.html":{"name":"Claims","abstract":"

A protocol for representing the claims on a JSON web token."},"Classes/JWTDecoder.html#/s:8SwiftJWT10JWTDecoderC11jwtVerifierAcA11JWTVerifierV_tcfc":{"name":"init(jwtVerifier:)","abstract":"

Initialize a JWTDecoder instance with a single JWTVerifier.

","parent_name":"JWTDecoder"},"Classes/JWTDecoder.html#/s:8SwiftJWT10JWTDecoderC15keyIDToVerifierAcA11JWTVerifierVSgSSc_tcfc":{"name":"init(keyIDToVerifier:)","abstract":"

Initialize a JWTDecoder instance with a function to generate the JWTVerifier from the JWT kid header.

","parent_name":"JWTDecoder"},"Classes/JWTDecoder.html#/s:8SwiftJWT10JWTDecoderC6decode_10fromStringxxm_SStKSeRzlF":{"name":"decode(_:fromString:)","abstract":"

Decode a JWT instance from a JWT String.

","parent_name":"JWTDecoder"},"Classes/JWTDecoder.html#/s:8SwiftJWT10JWTDecoderC6decode_4fromxxm_10Foundation4DataVtKSeRzlF":{"name":"decode(_:from:)","abstract":"

Decode a JWT instance from a utf8 encoded JWT String.

","parent_name":"JWTDecoder"},"Classes/JWTDecoder.html#/s:8SwiftJWT10JWTDecoderC4data16base64urlEncoded10Foundation4DataVSgSS_tFZ":{"name":"data(base64urlEncoded:)","abstract":"

Initializes a new Data from the base64url-encoded String provided. The","parent_name":"JWTDecoder"},"Classes/JWTEncoder.html#/s:8SwiftJWT10JWTEncoderC9jwtSignerAcA9JWTSignerV_tcfc":{"name":"init(jwtSigner:)","abstract":"

Initialize a JWTEncoder instance with a single JWTSigner.

","parent_name":"JWTEncoder"},"Classes/JWTEncoder.html#/s:8SwiftJWT10JWTEncoderC13keyIDToSignerAcA9JWTSignerVSgSSc_tcfc":{"name":"init(keyIDToSigner:)","abstract":"

Initialize a JWTEncoder instance with a function to generate the JWTSigner from the JWT kid header.

","parent_name":"JWTEncoder"},"Classes/JWTEncoder.html#/s:8SwiftJWT10JWTEncoderC6encodey10Foundation4DataVxKSERzlF":{"name":"encode(_:)","abstract":"

Encode a JWT instance into a UTF8 encoded JWT String.

","parent_name":"JWTEncoder"},"Classes/JWTEncoder.html#/s:8SwiftJWT10JWTEncoderC14encodeToStringySSxKSERzlF":{"name":"encodeToString(_:)","abstract":"

Encode a JWT instance as a JWT String.

","parent_name":"JWTEncoder"},"Classes/JWTEncoder.html#/s:8SwiftJWT10JWTEncoderC22base64urlEncodedString4dataSS10Foundation4DataV_tFZ":{"name":"base64urlEncodedString(data:)","abstract":"

Returns a String representation of this data, encoded in base64url format","parent_name":"JWTEncoder"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3iss3sub3aud3exp3nbf3iat3jtiACSSSg_AKSaySSGSg10Foundation4DateVSgA2qKtcfc":{"name":"init(iss:sub:aud:exp:nbf:iat:jti:)","abstract":"

Initialize a ClaimsStandardJWT

","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3issSSSgvp":{"name":"iss","abstract":"

The “iss” (issuer) claim identifies the principal that issued the","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3subSSSgvp":{"name":"sub","abstract":"

The “sub” (subject) claim identifies the principal that is the","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3audSaySSGSgvp":{"name":"aud","abstract":"

The “aud” (audience) claim identifies the recipients that the JWT is","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3exp10Foundation4DateVSgvp":{"name":"exp","abstract":"

The “exp” (expiration time) claim identifies the expiration time on","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3nbf10Foundation4DateVSgvp":{"name":"nbf","abstract":"

The “nbf” (not before) claim identifies the time before which the JWT","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3iat10Foundation4DateVSgvp":{"name":"iat","abstract":"

The “iat” (issued at) claim identifies the time at which the JWT was","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3jtiSSSgvp":{"name":"jti","abstract":"

The “jti” (JWT ID) claim provides a unique identifier for the JWT.","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3iss3sub3aud3exp3iat9auth_time5nonce3acr3amr3azp4name06given_Q007family_Q007middle_Q08nickname18preferred_username7profile7picture7website5email14email_verified6gender9birthdate8zoneinfo6locale12phone_number21phone_number_verified7address10updated_atACSS_SSSaySSG10Foundation4DateVA8_A8_SgSSSgA10_A5_SgA10_A10_A10_A10_A10_A10_A10_A10_A10_A10_A10_SbSgA10_A10_A10_A10_A10_A12_AA12AddressClaimVSgA9_tcfc":{"name":"init(iss:sub:aud:exp:iat:auth_time:nonce:acr:amr:azp:name:given_name:family_name:middle_name:nickname:preferred_username:profile:picture:website:email:email_verified:gender:birthdate:zoneinfo:locale:phone_number:phone_number_verified:address:updated_at:)","abstract":"

Initalise the ClaimsOpenID

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3issSSvp":{"name":"iss","abstract":"

Issuer Identifier for the Issuer of the response. The iss value is a case sensitive URL using the https scheme that contains scheme, host, and optionally, port number and path components and no query or fragment components.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3subSSvp":{"name":"sub","abstract":"

Subject Identifier. A locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client, e.g., 24400320 or AItOawmwtWwcT0k51BayewNvutrJUqsvl6qs7A4. It MUST NOT exceed 255 ASCII characters in length. The sub value is case sensitive.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3audSaySSGvp":{"name":"aud","abstract":"

Audience(s) that this ID Token is intended for. It MUST contain the OAuth 2.0 client_id of the Relying Party as an audience value. It MAY also contain identifiers for other audiences.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3exp10Foundation4DateVvp":{"name":"exp","abstract":"

Expiration time on or after which the ID Token MUST NOT be accepted for processing. The processing of this parameter requires that the current date/time MUST be before the expiration date/time listed in the value. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3iat10Foundation4DateVvp":{"name":"iat","abstract":"

Time at which the JWT was issued.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC9auth_time10Foundation4DateVSgvp":{"name":"auth_time","abstract":"

Time when the End-User authentication occurred.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC5nonceSSSgvp":{"name":"nonce","abstract":"

String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. If present in the ID Token, Clients MUST verify that the nonce Claim Value is equal to the value of the nonce parameter sent in the Authentication Request. If present in the Authentication Request, Authorization Servers MUST include a nonce Claim in the ID Token with the Claim Value being the nonce value sent in the Authentication Request. Authorization Servers SHOULD perform no other processing on nonce values used.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3acrSSSgvp":{"name":"acr","abstract":"

Authentication Context Class Reference. String specifying an Authentication Context Class Reference value that identifies the Authentication Context Class that the authentication performed satisfied. The value “0” indicates the End-User authentication did not meet the requirements of ISO/IEC 29115 level 1. Authentications with level 0 SHOULD NOT be used to authorize access to any resource of any monetary value. Parties using this claim will need to agree upon the meanings of the values used, which may be context-specific.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3amrSaySSGSgvp":{"name":"amr","abstract":"

Authentication Methods References. JSON array of strings that are identifiers for authentication methods used in the authentication. For instance, values might indicate that both password and OTP authentication methods were used. Parties using this claim will need to agree upon the meanings of the values used, which may be context-specific.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3azpSSSgvp":{"name":"azp","abstract":"

Authorized party - the party to which the ID Token was issued. If present, it MUST contain the OAuth 2.0 Client ID of this party. This Claim is only needed when the ID Token has a single audience value and that audience is different than the authorized party. It MAY be included even when the authorized party is the same as the sole audience.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC4nameSSSgvp":{"name":"name","abstract":"

End-User’s full name in displayable form including all name parts, possibly including titles and suffixes, ordered according to the End-User’s locale and preferences.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC10given_nameSSSgvp":{"name":"given_name","abstract":"

Given name(s) or first name(s) of the End-User. Note that in some cultures, people can have multiple given names; all can be present, with the names being separated by space characters.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC11family_nameSSSgvp":{"name":"family_name","abstract":"

Surname(s) or last name(s) of the End-User. Note that in some cultures, people can have multiple family names or no family name; all can be present, with the names being separated by space characters.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC11middle_nameSSSgvp":{"name":"middle_name","abstract":"

Middle name(s) of the End-User. Note that in some cultures, people can have multiple middle names; all can be present, with the names being separated by space characters. Also note that in some cultures, middle names are not used.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC8nicknameSSSgvp":{"name":"nickname","abstract":"

Casual name of the End-User that may or may not be the same as the given_name. For instance, a nickname value of Mike might be returned alongside a given_name value of Michael.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC18preferred_usernameSSSgvp":{"name":"preferred_username","abstract":"

Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC7profileSSSgvp":{"name":"profile","abstract":"

URL of the End-User’s profile page. The contents of this Web page SHOULD be about the End-User.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC7pictureSSSgvp":{"name":"picture","abstract":"

URL of the End-User’s profile picture. This URL MUST refer to an image file (for example, a PNG, JPEG, or GIF image file), rather than to a Web page containing an image. Note that this URL SHOULD specifically reference a profile photo of the End-User suitable for displaying when describing the End-User, rather than an arbitrary photo taken by the End-User.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC7websiteSSSgvp":{"name":"website","abstract":"

URL of the End-User’s Web page or blog. This Web page SHOULD contain information published by the End-User or an organization that the End-User is affiliated with.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC5emailSSSgvp":{"name":"email","abstract":"

End-User’s preferred e-mail address.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC14email_verifiedSbSgvp":{"name":"email_verified","abstract":"

True if the End-User’s e-mail address has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this e-mail address was controlled by the End-User at the time the verification was performed. The means by which an e-mail address is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC6genderSSSgvp":{"name":"gender","abstract":"

End-User’s gender. Values defined by this specification are female and male. Other values MAY be used when neither of the defined values are applicable.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC9birthdateSSSgvp":{"name":"birthdate","abstract":"

End-User’s birthday, represented as an ISO 8601:2004 YYYY-MM-DD format. The year MAY be 0000, indicating that it is omitted. To represent only the year, YYYY format is allowed.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC8zoneinfoSSSgvp":{"name":"zoneinfo","abstract":"

String from zoneinfo time zone database representing the End-User’s time zone. For example, Europe/Paris or America/Los_Angeles.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC6localeSSSgvp":{"name":"locale","abstract":"

End-User’s locale, represented as a BCP47 language tag. This is typically an ISO 639-1 Alpha-2 language code in lowercase and an ISO 3166-1 Alpha-2 country code in uppercase, separated by a dash. For example, en-US or fr-CA. As a compatibility note, some implementations have used an underscore as the separator rather than a dash, for example, en_US; Relying Parties MAY choose to accept this locale syntax as well.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC12phone_numberSSSgvp":{"name":"phone_number","abstract":"

End-User’s preferred telephone number. E.164 is RECOMMENDED as the format of this Claim, for example, +1 (425) 555-1212 or +56 (2) 687 2400.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC21phone_number_verifiedSbSgvp":{"name":"phone_number_verified","abstract":"

True if the End-User’s phone number has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this phone number was controlled by the End-User at the time the verification was performed. The means by which a phone number is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating. When true, the phone_number Claim MUST be in E.164 format and any extensions MUST be represented in RFC 3966 format.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC7addressAA12AddressClaimVSgvp":{"name":"address","abstract":"

End-User’s preferred postal address.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC10updated_at10Foundation4DateVSgvp":{"name":"updated_at","abstract":"

Time the End-User’s information was last updated.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3iss3sub3exp3iat3jti3upn6groupsACSS_SS10Foundation4DateVAMS2SSaySSGtcfc":{"name":"init(iss:sub:exp:iat:jti:upn:groups:)","abstract":"

Initialize a ClaimsMicroProfile

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3issSSvp":{"name":"iss","abstract":"

The MP-JWT issuer. RFC7519, Section 4.1.1

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3subSSvp":{"name":"sub","abstract":"

Identifies the principal that is the subject of the JWT.

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3exp10Foundation4DateVvp":{"name":"exp","abstract":"

Identifies the expiration time on or after which the JWT MUST NOT be accepted for processing.

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3iat10Foundation4DateVvp":{"name":"iat","abstract":"

Identifies the time at which the JWT was issued.

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3jtiSSvp":{"name":"jti","abstract":"

The “jti” (JWT ID) claim provides a unique identifier for the JWT.","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3upnSSSgvp":{"name":"upn","abstract":"

This MP-JWT custom claim is the user principal name in the java.security.Principal interface, and is the caller principal name in javax.security.enterprise.identitystore.IdentityStore. If this claim is missing, fallback to the “preferred_username”, should be attempted, and if that claim is missing, fallback to the “sub” claim should be used.

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC18preferred_usernameSSSgvp":{"name":"preferred_username","abstract":"

Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace.

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC6groupsSaySSGvp":{"name":"groups","abstract":"

This MP-JWT custom claim is the list of group names that have been assigned to the principal of the MP-JWT. This typically will required a mapping at the application container level to application deployment roles, but a one-to-one between group names and application role names is required to be performed in addition to any other mapping.

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html":{"name":"ClaimsMicroProfile","abstract":"

A class representing the MicroProfile claims as listed in MicroProfile specs.

"},"Classes/ClaimsOpenID.html":{"name":"ClaimsOpenID","abstract":"

A class representing OpenID related claims as decsribed in OpenID specs.

"},"Classes/ClaimsStandardJWT.html":{"name":"ClaimsStandardJWT","abstract":"

A class representing the Standard JWT claims as described in RFC7519.

"},"Classes/JWTEncoder.html":{"name":"JWTEncoder","abstract":"

A thread safe encoder that signs the JWT header and claims using the provided algorithm and encodes a JWT instance as either Data or a JWT String.

"},"Classes/JWTDecoder.html":{"name":"JWTDecoder","abstract":"

A thread safe decoder that decodes either Data or a JWT String as a JWT instance and verifies the signiture using the provided algorithm.

"},"Classes.html":{"name":"Classes","abstract":"

The following classes are available globally.

"},"Protocols.html":{"name":"Protocols","abstract":"

The following protocols are available globally.

"},"Structs.html":{"name":"Structures","abstract":"

The following structures are available globally.

"}} ================================================ FILE: docs/index.html ================================================ SwiftJWT Reference

SwiftJWT 3.6.200 Docs (100% documented)

View on GitHub

Kitura

APIDoc Build Status - Master macOS Linux Apache 2 Slack Status

SwiftJWT

An implementation of JSON Web Token using Swift. JWTs offer a lightweight and compact format for transmitting information between parties, and the information can be verified and trusted due to JWTs being digitally signed.

For more information on JSON Web Tokens, their use cases and how they work, we recommend visiting jwt.io.

Reminder: JWTs sent as JWS do not encrypt data, so never send anything sensitive or confidential in a JWT. This library does not currently support JWE.

Swift version

The latest version of Swift-JWT requires Swift 4.0 or later. You can download this version of the Swift binaries by following this link. Compatibility with other Swift versions is not guaranteed.

Usage

Swift Package Manager

Add dependencies

Add the Swift-JWT package to the dependencies within your application’s Package.swift file. Substitute "x.x.x" with the latest Swift-JWT release.

.package(url: "https://github.com/Kitura/Swift-JWT.git", from: "x.x.x")

Add SwiftJWT to your target’s dependencies:

.target(name: "example", dependencies: ["SwiftJWT"]),

Import package

import SwiftJWT

Cocoapods

To include Swift-JWT in a project using CocoaPods, add SwiftJWT to your Podfile:

pod 'SwiftJWT'

Getting Started

The JWT model

In its compact form, a JSON Web Tokens consist of three sections of Base64Url encoded JSON, separated by dots (.).
These section are: Headers, Claims and the Signature. Therefore, a JWT typically looks like the following: xxxxx.yyyyy.zzzzz

The Header struct contains the fields of the JSON Web Token header as defined by RFC7515.
The “typ” header will default to “JWT”. The “alg” header will be set to the algorithm name when you sign the JWT.
The other Header fields can be set when initializing the Header or by changing them directly on the Header object.

let myHeader = Header(kid: "KeyID1")

Claims

Claims are statements about an entity (typically, the user) and additional data. The Claims are defined by creating a Swift type that conforms to the Claims protocol. The fields of this type represent the information that will be shared using the JWT.

A list of recommended claims is defined in RFC7519.

struct MyClaims: Claims {
    let iss: String
    let sub: String
    let exp: Date
    let admin: Bool
}
let myClaims = MyClaims(iss: "Kitura", sub: "John", exp: Date(timeIntervalSinceNow: 3600), admin: true)
ClaimsExamples

This library includes some example Claims structs as defined by their online specifications:

JWT

The JWT struct represents the Header and Claims of a JSON Web Token.
You can initialize a JWT by decoding a JWT String, or by providing the JWT Header and Claims.

let myJWT = JWT(header: myHeader, claims: myClaims)

Signing and Verifying JSON web tokens

Creating public and private keys

To sign and verify a JWT using an RSA algorithm, you must provide a public and private key. This could be the contents of a .key file generated via the following Terminal commands:

$ ssh-keygen -t rsa -b 4096 -m PEM -f privateKey.key
# Don't add a passphrase
$ openssl rsa -in privateKey.key -pubout -outform PEM -out privateKey.key.pub

This will create a public and private key pair on your system, and the contents of the private key can be passed into a Swift variable using the following code:

let privateKeyPath = URL(fileURLWithPath: getAbsolutePath(relativePath: "/path/to/privateKey.key"))
let privateKey: Data = try Data(contentsOf: privateKeyPath, options: .alwaysMapped)
let publicKeyPath = URL(fileURLWithPath: getAbsolutePath(relativePath: "/path/to/publicKey.key"))
let publicKey: Data = try Data(contentsOf: publicKeyPath, options: .alwaysMapped)

For details on creating elliptic curve public and private keys, view the BlueECC README.txt.

Sign a JWT using a JWTSigner

The struct JWTSigner contains the algorithms that can be used to sign a JWT.

Initialize a JWTSigner using the static function corresponding to the desired RSA algorithm:

let jwtSigner = JWTSigner.rs256(privateKey: privateKey)

To generate a signed JWT string, call the sign function on your JWT instance, passing in a JWTSigner:

let signedJWT = try myJWT.sign(using: jwtSigner)

The resulting signedJWT will be a String of the form:

<encoded header>.<encoded claims>.<signature>

Note: The sign function sets the alg (algorithm) field of the header.

Verify a JWT using JWTVerifier

The struct JWTVerifier contains the algorithms that can be used to verify a JWT.

Initialize a JWTVerifier using the static function corresponding to the desired RSA algorithm:

let jwtVerifier = JWTVerifier.rs256(publicKey: publicKey)

To verify a signed JWT string, call the static verify function, passing in your JWT string and the JWTVerifier:

let verified = JWT<MyClaims>.verify(signedJWT, using: jwtVerifier)

The verified field will be a bool that is true if the signature is verified.

Supported Algorithms

The supported algorithms for signing and verifying JWTs are:

  • RS256 - RSASSA-PKCS1-v1_5 using SHA-256
  • RS384 - RSASSA-PKCS1-v1_5 using SHA-384
  • RS512 - RSASSA-PKCS1-v1_5 using SHA-512
  • HS256 - HMAC using using SHA-256
  • HS384 - HMAC using using SHA-384
  • HS512 - HMAC using using SHA-512
  • ES256 - ECDSA using using SHA-256 and a P-256 curve
  • ES384 - ECDSA using using SHA-384 and a P-384 curve
  • ES512 - ECDSA using using SHA-512 and a P-521 curve
  • PS256 - RSA-PSS using SHA-256
  • PS384 - RSA-PSS using SHA-384
  • PS512 - RSA-PSS using SHA-512
  • none - Don’t sign or verify the JWT

Note: ECDSA and RSA-PSS algorithms require a minimum Swift version of 4.1.

Validate claims

The validateClaims function validates the standard Date claims of a JWT instance. The following claims are validated if they are present in the Claims object:

  • exp (expiration date)
  • nbf (not before date)
  • iat (issued at date)

The method returns ValidateClaimsResult - an struct that list the various reasons for validation failure. If the validation succeeds ValidateClaimsResult.success is returned. The leeway parameter is the TimeInterval in seconds that a standard Date claim will be valid outside of the specified time. This can be used to account for clock skew between issuers and verifiers.

let validationResult = verified.validateClaims(leeway: 10)
if validationResult != .success {
    print("Claims validation failed: ", validationResult)
}

Decode a JWT from a JWT string

A JWT struct can be initialized from a JWT string. If a JWTVerifier is provided it will be used to verify the signature before initialization

let newJWT = try JWT<MyClaims>(jwtString: signedJWT, verifier: jwtVerifier)

JWTEncoder and JWTDecoder

The JWTEncoder and JWTDecoder classes encode and decode JWT Strings using the same API as JSONEncoder and JSONDecoder:

 let jwtEncoder = JWTEncoder(jwtSigner: jwtSigner)
 let jwtString = try jwtEncoder.encodeToString(myJWT)

 let jwtDecoder = JWTDecoder(jwtVerifier: jwtVerifier)
 let jwt = try jwtDecoder.decode(JWT<MyClaims>.self, fromString: jwtString)

Because JWTEncoder and JWTDecoder conform to KituraContract’s BodyEncoder and BodyDecoder protocols, they can be used as a custom coder in Codable routes for sending and receiving JWTs:

 router.encoders[MediaType(type: .application, subType: "jwt")] = { return jwtEncoder }
 router.decoders[MediaType(type: .application, subType: "jwt")] = { return jwtDecoder }

This allows for the use of JWT’s in information exchange. By sending and receiving JWT’s you can ensure the sending is who they say they are and verify the content hasn’t been tampered with.

API Documentation

For more information visit our API reference.

Community

We love to talk server-side Swift, and Kitura. Join our Slack to meet the team!

License

This library is licensed under Apache 2.0. Full license text is available in LICENSE.

================================================ FILE: docs/js/jazzy.js ================================================ window.jazzy = {'docset': false} if (typeof window.dash != 'undefined') { document.documentElement.className += ' dash' window.jazzy.docset = true } if (navigator.userAgent.match(/xcode/i)) { document.documentElement.className += ' xcode' window.jazzy.docset = true } function toggleItem($link, $content) { var animationDuration = 300; $link.toggleClass('token-open'); $content.slideToggle(animationDuration); } function itemLinkToContent($link) { return $link.parent().parent().next(); } // On doc load + hash-change, open any targetted item function openCurrentItemIfClosed() { if (window.jazzy.docset) { return; } var $link = $(`a[name="${location.hash.substring(1)}"]`).nextAll('.token'); $content = itemLinkToContent($link); if ($content.is(':hidden')) { toggleItem($link, $content); } } $(openCurrentItemIfClosed); $(window).on('hashchange', openCurrentItemIfClosed); // On item link ('token') click, toggle its discussion $('.token').on('click', function(event) { if (window.jazzy.docset) { return; } var $link = $(this); toggleItem($link, itemLinkToContent($link)); // Keeps the document from jumping to the hash. var href = $link.attr('href'); if (history.pushState) { history.pushState({}, '', href); } else { location.hash = href; } event.preventDefault(); }); // Clicks on links to the current, closed, item need to open the item $("a:not('.token')").on('click', function() { if (location == this.href) { openCurrentItemIfClosed(); } }); // KaTeX rendering if ("katex" in window) { $($('.math').each( (_, element) => { katex.render(element.textContent, element, { displayMode: $(element).hasClass('m-block'), throwOnError: false, trust: true }); })) } ================================================ FILE: docs/js/jazzy.search.js ================================================ $(function(){ var $typeahead = $('[data-typeahead]'); var $form = $typeahead.parents('form'); var searchURL = $form.attr('action'); function displayTemplate(result) { return result.name; } function suggestionTemplate(result) { var t = '
'; t += '' + result.name + ''; if (result.parent_name) { t += '' + result.parent_name + ''; } t += '
'; return t; } $typeahead.one('focus', function() { $form.addClass('loading'); $.getJSON(searchURL).then(function(searchData) { const searchIndex = lunr(function() { this.ref('url'); this.field('name'); this.field('abstract'); for (const [url, doc] of Object.entries(searchData)) { this.add({url: url, name: doc.name, abstract: doc.abstract}); } }); $typeahead.typeahead( { highlight: true, minLength: 3, autoselect: true }, { limit: 10, display: displayTemplate, templates: { suggestion: suggestionTemplate }, source: function(query, sync) { const lcSearch = query.toLowerCase(); const results = searchIndex.query(function(q) { q.term(lcSearch, { boost: 100 }); q.term(lcSearch, { boost: 10, wildcard: lunr.Query.wildcard.TRAILING }); }).map(function(result) { var doc = searchData[result.ref]; doc.url = result.ref; return doc; }); sync(results); } } ); $form.removeClass('loading'); $typeahead.trigger('focus'); }); }); var baseURL = searchURL.slice(0, -"search.json".length); $typeahead.on('typeahead:select', function(e, result) { window.location = baseURL + result.url; }); }); ================================================ FILE: docs/js/typeahead.jquery.js ================================================ /*! * typeahead.js 1.3.1 * https://github.com/corejavascript/typeahead.js * Copyright 2013-2020 Twitter, Inc. and other contributors; Licensed MIT */ (function(root, factory) { if (typeof define === "function" && define.amd) { define([ "jquery" ], function(a0) { return factory(a0); }); } else if (typeof module === "object" && module.exports) { module.exports = factory(require("jquery")); } else { factory(root["jQuery"]); } })(this, function($) { var _ = function() { "use strict"; return { isMsie: function() { return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; }, isBlankString: function(str) { return !str || /^\s*$/.test(str); }, escapeRegExChars: function(str) { return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); }, isString: function(obj) { return typeof obj === "string"; }, isNumber: function(obj) { return typeof obj === "number"; }, isArray: $.isArray, isFunction: $.isFunction, isObject: $.isPlainObject, isUndefined: function(obj) { return typeof obj === "undefined"; }, isElement: function(obj) { return !!(obj && obj.nodeType === 1); }, isJQuery: function(obj) { return obj instanceof $; }, toStr: function toStr(s) { return _.isUndefined(s) || s === null ? "" : s + ""; }, bind: $.proxy, each: function(collection, cb) { $.each(collection, reverseArgs); function reverseArgs(index, value) { return cb(value, index); } }, map: $.map, filter: $.grep, every: function(obj, test) { var result = true; if (!obj) { return result; } $.each(obj, function(key, val) { if (!(result = test.call(null, val, key, obj))) { return false; } }); return !!result; }, some: function(obj, test) { var result = false; if (!obj) { return result; } $.each(obj, function(key, val) { if (result = test.call(null, val, key, obj)) { return false; } }); return !!result; }, mixin: $.extend, identity: function(x) { return x; }, clone: function(obj) { return $.extend(true, {}, obj); }, getIdGenerator: function() { var counter = 0; return function() { return counter++; }; }, templatify: function templatify(obj) { return $.isFunction(obj) ? obj : template; function template() { return String(obj); } }, defer: function(fn) { setTimeout(fn, 0); }, debounce: function(func, wait, immediate) { var timeout, result; return function() { var context = this, args = arguments, later, callNow; later = function() { timeout = null; if (!immediate) { result = func.apply(context, args); } }; callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) { result = func.apply(context, args); } return result; }; }, throttle: function(func, wait) { var context, args, timeout, result, previous, later; previous = 0; later = function() { previous = new Date(); timeout = null; result = func.apply(context, args); }; return function() { var now = new Date(), remaining = wait - (now - previous); context = this; args = arguments; if (remaining <= 0) { clearTimeout(timeout); timeout = null; previous = now; result = func.apply(context, args); } else if (!timeout) { timeout = setTimeout(later, remaining); } return result; }; }, stringify: function(val) { return _.isString(val) ? val : JSON.stringify(val); }, guid: function() { function _p8(s) { var p = (Math.random().toString(16) + "000000000").substr(2, 8); return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p; } return "tt-" + _p8() + _p8(true) + _p8(true) + _p8(); }, noop: function() {} }; }(); var WWW = function() { "use strict"; var defaultClassNames = { wrapper: "twitter-typeahead", input: "tt-input", hint: "tt-hint", menu: "tt-menu", dataset: "tt-dataset", suggestion: "tt-suggestion", selectable: "tt-selectable", empty: "tt-empty", open: "tt-open", cursor: "tt-cursor", highlight: "tt-highlight" }; return build; function build(o) { var www, classes; classes = _.mixin({}, defaultClassNames, o); www = { css: buildCss(), classes: classes, html: buildHtml(classes), selectors: buildSelectors(classes) }; return { css: www.css, html: www.html, classes: www.classes, selectors: www.selectors, mixin: function(o) { _.mixin(o, www); } }; } function buildHtml(c) { return { wrapper: '', menu: '
' }; } function buildSelectors(classes) { var selectors = {}; _.each(classes, function(v, k) { selectors[k] = "." + v; }); return selectors; } function buildCss() { var css = { wrapper: { position: "relative", display: "inline-block" }, hint: { position: "absolute", top: "0", left: "0", borderColor: "transparent", boxShadow: "none", opacity: "1" }, input: { position: "relative", verticalAlign: "top", backgroundColor: "transparent" }, inputWithNoHint: { position: "relative", verticalAlign: "top" }, menu: { position: "absolute", top: "100%", left: "0", zIndex: "100", display: "none" }, ltr: { left: "0", right: "auto" }, rtl: { left: "auto", right: " 0" } }; if (_.isMsie()) { _.mixin(css.input, { backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" }); } return css; } }(); var EventBus = function() { "use strict"; var namespace, deprecationMap; namespace = "typeahead:"; deprecationMap = { render: "rendered", cursorchange: "cursorchanged", select: "selected", autocomplete: "autocompleted" }; function EventBus(o) { if (!o || !o.el) { $.error("EventBus initialized without el"); } this.$el = $(o.el); } _.mixin(EventBus.prototype, { _trigger: function(type, args) { var $e = $.Event(namespace + type); this.$el.trigger.call(this.$el, $e, args || []); return $e; }, before: function(type) { var args, $e; args = [].slice.call(arguments, 1); $e = this._trigger("before" + type, args); return $e.isDefaultPrevented(); }, trigger: function(type) { var deprecatedType; this._trigger(type, [].slice.call(arguments, 1)); if (deprecatedType = deprecationMap[type]) { this._trigger(deprecatedType, [].slice.call(arguments, 1)); } } }); return EventBus; }(); var EventEmitter = function() { "use strict"; var splitter = /\s+/, nextTick = getNextTick(); return { onSync: onSync, onAsync: onAsync, off: off, trigger: trigger }; function on(method, types, cb, context) { var type; if (!cb) { return this; } types = types.split(splitter); cb = context ? bindContext(cb, context) : cb; this._callbacks = this._callbacks || {}; while (type = types.shift()) { this._callbacks[type] = this._callbacks[type] || { sync: [], async: [] }; this._callbacks[type][method].push(cb); } return this; } function onAsync(types, cb, context) { return on.call(this, "async", types, cb, context); } function onSync(types, cb, context) { return on.call(this, "sync", types, cb, context); } function off(types) { var type; if (!this._callbacks) { return this; } types = types.split(splitter); while (type = types.shift()) { delete this._callbacks[type]; } return this; } function trigger(types) { var type, callbacks, args, syncFlush, asyncFlush; if (!this._callbacks) { return this; } types = types.split(splitter); args = [].slice.call(arguments, 1); while ((type = types.shift()) && (callbacks = this._callbacks[type])) { syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args)); asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args)); syncFlush() && nextTick(asyncFlush); } return this; } function getFlush(callbacks, context, args) { return flush; function flush() { var cancelled; for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) { cancelled = callbacks[i].apply(context, args) === false; } return !cancelled; } } function getNextTick() { var nextTickFn; if (window.setImmediate) { nextTickFn = function nextTickSetImmediate(fn) { setImmediate(function() { fn(); }); }; } else { nextTickFn = function nextTickSetTimeout(fn) { setTimeout(function() { fn(); }, 0); }; } return nextTickFn; } function bindContext(fn, context) { return fn.bind ? fn.bind(context) : function() { fn.apply(context, [].slice.call(arguments, 0)); }; } }(); var highlight = function(doc) { "use strict"; var defaults = { node: null, pattern: null, tagName: "strong", className: null, wordsOnly: false, caseSensitive: false, diacriticInsensitive: false }; var accented = { A: "[AaªÀ-Åà-åĀ-ąǍǎȀ-ȃȦȧᴬᵃḀḁẚẠ-ảₐ℀℁℻⒜Ⓐⓐ㍱-㍴㎀-㎄㎈㎉㎩-㎯㏂㏊㏟㏿Aa]", B: "[BbᴮᵇḂ-ḇℬ⒝Ⓑⓑ㍴㎅-㎇㏃㏈㏔㏝Bb]", C: "[CcÇçĆ-čᶜ℀ℂ℃℅℆ℭⅭⅽ⒞Ⓒⓒ㍶㎈㎉㎝㎠㎤㏄-㏇Cc]", D: "[DdĎďDŽ-džDZ-dzᴰᵈḊ-ḓⅅⅆⅮⅾ⒟Ⓓⓓ㋏㍲㍷-㍹㎗㎭-㎯㏅㏈Dd]", E: "[EeÈ-Ëè-ëĒ-ěȄ-ȇȨȩᴱᵉḘ-ḛẸ-ẽₑ℡ℯℰⅇ⒠Ⓔⓔ㉐㋍㋎Ee]", F: "[FfᶠḞḟ℉ℱ℻⒡Ⓕⓕ㎊-㎌㎙ff-fflFf]", G: "[GgĜ-ģǦǧǴǵᴳᵍḠḡℊ⒢Ⓖⓖ㋌㋍㎇㎍-㎏㎓㎬㏆㏉㏒㏿Gg]", H: "[HhĤĥȞȟʰᴴḢ-ḫẖℋ-ℎ⒣Ⓗⓗ㋌㍱㎐-㎔㏊㏋㏗Hh]", I: "[IiÌ-Ïì-ïĨ-İIJijǏǐȈ-ȋᴵᵢḬḭỈ-ịⁱℐℑℹⅈⅠ-ⅣⅥ-ⅨⅪⅫⅰ-ⅳⅵ-ⅸⅺⅻ⒤Ⓘⓘ㍺㏌㏕fiffiIi]", J: "[JjIJ-ĵLJ-njǰʲᴶⅉ⒥ⒿⓙⱼJj]", K: "[KkĶķǨǩᴷᵏḰ-ḵK⒦Ⓚⓚ㎄㎅㎉㎏㎑㎘㎞㎢㎦㎪㎸㎾㏀㏆㏍-㏏Kk]", L: "[LlĹ-ŀLJ-ljˡᴸḶḷḺ-ḽℒℓ℡Ⅼⅼ⒧Ⓛⓛ㋏㎈㎉㏐-㏓㏕㏖㏿flfflLl]", M: "[MmᴹᵐḾ-ṃ℠™ℳⅯⅿ⒨Ⓜⓜ㍷-㍹㎃㎆㎎㎒㎖㎙-㎨㎫㎳㎷㎹㎽㎿㏁㏂㏎㏐㏔-㏖㏘㏙㏞㏟Mm]", N: "[NnÑñŃ-ʼnNJ-njǸǹᴺṄ-ṋⁿℕ№⒩Ⓝⓝ㎁㎋㎚㎱㎵㎻㏌㏑Nn]", O: "[OoºÒ-Öò-öŌ-őƠơǑǒǪǫȌ-ȏȮȯᴼᵒỌ-ỏₒ℅№ℴ⒪Ⓞⓞ㍵㏇㏒㏖Oo]", P: "[PpᴾᵖṔ-ṗℙ⒫Ⓟⓟ㉐㍱㍶㎀㎊㎩-㎬㎰㎴㎺㏋㏗-㏚Pp]", Q: "[Qqℚ⒬Ⓠⓠ㏃Qq]", R: "[RrŔ-řȐ-ȓʳᴿᵣṘ-ṛṞṟ₨ℛ-ℝ⒭Ⓡⓡ㋍㍴㎭-㎯㏚㏛Rr]", S: "[SsŚ-šſȘșˢṠ-ṣ₨℁℠⒮Ⓢⓢ㎧㎨㎮-㎳㏛㏜stSs]", T: "[TtŢ-ťȚțᵀᵗṪ-ṱẗ℡™⒯Ⓣⓣ㉐㋏㎔㏏ſtstTt]", U: "[UuÙ-Üù-üŨ-ųƯưǓǔȔ-ȗᵁᵘᵤṲ-ṷỤ-ủ℆⒰Ⓤⓤ㍳㍺Uu]", V: "[VvᵛᵥṼ-ṿⅣ-Ⅷⅳ-ⅷ⒱Ⓥⓥⱽ㋎㍵㎴-㎹㏜㏞Vv]", W: "[WwŴŵʷᵂẀ-ẉẘ⒲Ⓦⓦ㎺-㎿㏝Ww]", X: "[XxˣẊ-ẍₓ℻Ⅸ-Ⅻⅸ-ⅻ⒳Ⓧⓧ㏓Xx]", Y: "[YyÝýÿŶ-ŸȲȳʸẎẏẙỲ-ỹ⒴Ⓨⓨ㏉Yy]", Z: "[ZzŹ-žDZ-dzᶻẐ-ẕℤℨ⒵Ⓩⓩ㎐-㎔Zz]" }; return function hightlight(o) { var regex; o = _.mixin({}, defaults, o); if (!o.node || !o.pattern) { return; } o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ]; regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly, o.diacriticInsensitive); traverse(o.node, hightlightTextNode); function hightlightTextNode(textNode) { var match, patternNode, wrapperNode; if (match = regex.exec(textNode.data)) { wrapperNode = doc.createElement(o.tagName); o.className && (wrapperNode.className = o.className); patternNode = textNode.splitText(match.index); patternNode.splitText(match[0].length); wrapperNode.appendChild(patternNode.cloneNode(true)); textNode.parentNode.replaceChild(wrapperNode, patternNode); } return !!match; } function traverse(el, hightlightTextNode) { var childNode, TEXT_NODE_TYPE = 3; for (var i = 0; i < el.childNodes.length; i++) { childNode = el.childNodes[i]; if (childNode.nodeType === TEXT_NODE_TYPE) { i += hightlightTextNode(childNode) ? 1 : 0; } else { traverse(childNode, hightlightTextNode); } } } }; function accent_replacer(chr) { return accented[chr.toUpperCase()] || chr; } function getRegex(patterns, caseSensitive, wordsOnly, diacriticInsensitive) { var escapedPatterns = [], regexStr; for (var i = 0, len = patterns.length; i < len; i++) { var escapedWord = _.escapeRegExChars(patterns[i]); if (diacriticInsensitive) { escapedWord = escapedWord.replace(/\S/g, accent_replacer); } escapedPatterns.push(escapedWord); } regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")"; return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i"); } }(window.document); var Input = function() { "use strict"; var specialKeyCodeMap; specialKeyCodeMap = { 9: "tab", 27: "esc", 37: "left", 39: "right", 13: "enter", 38: "up", 40: "down" }; function Input(o, www) { var id; o = o || {}; if (!o.input) { $.error("input is missing"); } www.mixin(this); this.$hint = $(o.hint); this.$input = $(o.input); this.$menu = $(o.menu); id = this.$input.attr("id") || _.guid(); this.$menu.attr("id", id + "_listbox"); this.$hint.attr({ "aria-hidden": true }); this.$input.attr({ "aria-owns": id + "_listbox", role: "combobox", "aria-autocomplete": "list", "aria-expanded": false }); this.query = this.$input.val(); this.queryWhenFocused = this.hasFocus() ? this.query : null; this.$overflowHelper = buildOverflowHelper(this.$input); this._checkLanguageDirection(); if (this.$hint.length === 0) { this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop; } this.onSync("cursorchange", this._updateDescendent); } Input.normalizeQuery = function(str) { return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " "); }; _.mixin(Input.prototype, EventEmitter, { _onBlur: function onBlur() { this.resetInputValue(); this.trigger("blurred"); }, _onFocus: function onFocus() { this.queryWhenFocused = this.query; this.trigger("focused"); }, _onKeydown: function onKeydown($e) { var keyName = specialKeyCodeMap[$e.which || $e.keyCode]; this._managePreventDefault(keyName, $e); if (keyName && this._shouldTrigger(keyName, $e)) { this.trigger(keyName + "Keyed", $e); } }, _onInput: function onInput() { this._setQuery(this.getInputValue()); this.clearHintIfInvalid(); this._checkLanguageDirection(); }, _managePreventDefault: function managePreventDefault(keyName, $e) { var preventDefault; switch (keyName) { case "up": case "down": preventDefault = !withModifier($e); break; default: preventDefault = false; } preventDefault && $e.preventDefault(); }, _shouldTrigger: function shouldTrigger(keyName, $e) { var trigger; switch (keyName) { case "tab": trigger = !withModifier($e); break; default: trigger = true; } return trigger; }, _checkLanguageDirection: function checkLanguageDirection() { var dir = (this.$input.css("direction") || "ltr").toLowerCase(); if (this.dir !== dir) { this.dir = dir; this.$hint.attr("dir", dir); this.trigger("langDirChanged", dir); } }, _setQuery: function setQuery(val, silent) { var areEquivalent, hasDifferentWhitespace; areEquivalent = areQueriesEquivalent(val, this.query); hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false; this.query = val; if (!silent && !areEquivalent) { this.trigger("queryChanged", this.query); } else if (!silent && hasDifferentWhitespace) { this.trigger("whitespaceChanged", this.query); } }, _updateDescendent: function updateDescendent(event, id) { this.$input.attr("aria-activedescendant", id); }, bind: function() { var that = this, onBlur, onFocus, onKeydown, onInput; onBlur = _.bind(this._onBlur, this); onFocus = _.bind(this._onFocus, this); onKeydown = _.bind(this._onKeydown, this); onInput = _.bind(this._onInput, this); this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown); if (!_.isMsie() || _.isMsie() > 9) { this.$input.on("input.tt", onInput); } else { this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { if (specialKeyCodeMap[$e.which || $e.keyCode]) { return; } _.defer(_.bind(that._onInput, that, $e)); }); } return this; }, focus: function focus() { this.$input.focus(); }, blur: function blur() { this.$input.blur(); }, getLangDir: function getLangDir() { return this.dir; }, getQuery: function getQuery() { return this.query || ""; }, setQuery: function setQuery(val, silent) { this.setInputValue(val); this._setQuery(val, silent); }, hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() { return this.query !== this.queryWhenFocused; }, getInputValue: function getInputValue() { return this.$input.val(); }, setInputValue: function setInputValue(value) { this.$input.val(value); this.clearHintIfInvalid(); this._checkLanguageDirection(); }, resetInputValue: function resetInputValue() { this.setInputValue(this.query); }, getHint: function getHint() { return this.$hint.val(); }, setHint: function setHint(value) { this.$hint.val(value); }, clearHint: function clearHint() { this.setHint(""); }, clearHintIfInvalid: function clearHintIfInvalid() { var val, hint, valIsPrefixOfHint, isValid; val = this.getInputValue(); hint = this.getHint(); valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow(); !isValid && this.clearHint(); }, hasFocus: function hasFocus() { return this.$input.is(":focus"); }, hasOverflow: function hasOverflow() { var constraint = this.$input.width() - 2; this.$overflowHelper.text(this.getInputValue()); return this.$overflowHelper.width() >= constraint; }, isCursorAtEnd: function() { var valueLength, selectionStart, range; valueLength = this.$input.val().length; selectionStart = this.$input[0].selectionStart; if (_.isNumber(selectionStart)) { return selectionStart === valueLength; } else if (document.selection) { range = document.selection.createRange(); range.moveStart("character", -valueLength); return valueLength === range.text.length; } return true; }, destroy: function destroy() { this.$hint.off(".tt"); this.$input.off(".tt"); this.$overflowHelper.remove(); this.$hint = this.$input = this.$overflowHelper = $("
"); }, setAriaExpanded: function setAriaExpanded(value) { this.$input.attr("aria-expanded", value); } }); return Input; function buildOverflowHelper($input) { return $('').css({ position: "absolute", visibility: "hidden", whiteSpace: "pre", fontFamily: $input.css("font-family"), fontSize: $input.css("font-size"), fontStyle: $input.css("font-style"), fontVariant: $input.css("font-variant"), fontWeight: $input.css("font-weight"), wordSpacing: $input.css("word-spacing"), letterSpacing: $input.css("letter-spacing"), textIndent: $input.css("text-indent"), textRendering: $input.css("text-rendering"), textTransform: $input.css("text-transform") }).insertAfter($input); } function areQueriesEquivalent(a, b) { return Input.normalizeQuery(a) === Input.normalizeQuery(b); } function withModifier($e) { return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey; } }(); var Dataset = function() { "use strict"; var keys, nameGenerator; keys = { dataset: "tt-selectable-dataset", val: "tt-selectable-display", obj: "tt-selectable-object" }; nameGenerator = _.getIdGenerator(); function Dataset(o, www) { o = o || {}; o.templates = o.templates || {}; o.templates.notFound = o.templates.notFound || o.templates.empty; if (!o.source) { $.error("missing source"); } if (!o.node) { $.error("missing node"); } if (o.name && !isValidName(o.name)) { $.error("invalid dataset name: " + o.name); } www.mixin(this); this.highlight = !!o.highlight; this.name = _.toStr(o.name || nameGenerator()); this.limit = o.limit || 5; this.displayFn = getDisplayFn(o.display || o.displayKey); this.templates = getTemplates(o.templates, this.displayFn); this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source; this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async; this._resetLastSuggestion(); this.$el = $(o.node).attr("role", "presentation").addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name); } Dataset.extractData = function extractData(el) { var $el = $(el); if ($el.data(keys.obj)) { return { dataset: $el.data(keys.dataset) || "", val: $el.data(keys.val) || "", obj: $el.data(keys.obj) || null }; } return null; }; _.mixin(Dataset.prototype, EventEmitter, { _overwrite: function overwrite(query, suggestions) { suggestions = suggestions || []; if (suggestions.length) { this._renderSuggestions(query, suggestions); } else if (this.async && this.templates.pending) { this._renderPending(query); } else if (!this.async && this.templates.notFound) { this._renderNotFound(query); } else { this._empty(); } this.trigger("rendered", suggestions, false, this.name); }, _append: function append(query, suggestions) { suggestions = suggestions || []; if (suggestions.length && this.$lastSuggestion.length) { this._appendSuggestions(query, suggestions); } else if (suggestions.length) { this._renderSuggestions(query, suggestions); } else if (!this.$lastSuggestion.length && this.templates.notFound) { this._renderNotFound(query); } this.trigger("rendered", suggestions, true, this.name); }, _renderSuggestions: function renderSuggestions(query, suggestions) { var $fragment; $fragment = this._getSuggestionsFragment(query, suggestions); this.$lastSuggestion = $fragment.children().last(); this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions)); }, _appendSuggestions: function appendSuggestions(query, suggestions) { var $fragment, $lastSuggestion; $fragment = this._getSuggestionsFragment(query, suggestions); $lastSuggestion = $fragment.children().last(); this.$lastSuggestion.after($fragment); this.$lastSuggestion = $lastSuggestion; }, _renderPending: function renderPending(query) { var template = this.templates.pending; this._resetLastSuggestion(); template && this.$el.html(template({ query: query, dataset: this.name })); }, _renderNotFound: function renderNotFound(query) { var template = this.templates.notFound; this._resetLastSuggestion(); template && this.$el.html(template({ query: query, dataset: this.name })); }, _empty: function empty() { this.$el.empty(); this._resetLastSuggestion(); }, _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) { var that = this, fragment; fragment = document.createDocumentFragment(); _.each(suggestions, function getSuggestionNode(suggestion) { var $el, context; context = that._injectQuery(query, suggestion); $el = $(that.templates.suggestion(context)).data(keys.dataset, that.name).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable); fragment.appendChild($el[0]); }); this.highlight && highlight({ className: this.classes.highlight, node: fragment, pattern: query }); return $(fragment); }, _getFooter: function getFooter(query, suggestions) { return this.templates.footer ? this.templates.footer({ query: query, suggestions: suggestions, dataset: this.name }) : null; }, _getHeader: function getHeader(query, suggestions) { return this.templates.header ? this.templates.header({ query: query, suggestions: suggestions, dataset: this.name }) : null; }, _resetLastSuggestion: function resetLastSuggestion() { this.$lastSuggestion = $(); }, _injectQuery: function injectQuery(query, obj) { return _.isObject(obj) ? _.mixin({ _query: query }, obj) : obj; }, update: function update(query) { var that = this, canceled = false, syncCalled = false, rendered = 0; this.cancel(); this.cancel = function cancel() { canceled = true; that.cancel = $.noop; that.async && that.trigger("asyncCanceled", query, that.name); }; this.source(query, sync, async); !syncCalled && sync([]); function sync(suggestions) { if (syncCalled) { return; } syncCalled = true; suggestions = (suggestions || []).slice(0, that.limit); rendered = suggestions.length; that._overwrite(query, suggestions); if (rendered < that.limit && that.async) { that.trigger("asyncRequested", query, that.name); } } function async(suggestions) { suggestions = suggestions || []; if (!canceled && rendered < that.limit) { that.cancel = $.noop; var idx = Math.abs(rendered - that.limit); rendered += idx; that._append(query, suggestions.slice(0, idx)); that.async && that.trigger("asyncReceived", query, that.name); } } }, cancel: $.noop, clear: function clear() { this._empty(); this.cancel(); this.trigger("cleared"); }, isEmpty: function isEmpty() { return this.$el.is(":empty"); }, destroy: function destroy() { this.$el = $("
"); } }); return Dataset; function getDisplayFn(display) { display = display || _.stringify; return _.isFunction(display) ? display : displayFn; function displayFn(obj) { return obj[display]; } } function getTemplates(templates, displayFn) { return { notFound: templates.notFound && _.templatify(templates.notFound), pending: templates.pending && _.templatify(templates.pending), header: templates.header && _.templatify(templates.header), footer: templates.footer && _.templatify(templates.footer), suggestion: templates.suggestion ? userSuggestionTemplate : suggestionTemplate }; function userSuggestionTemplate(context) { var template = templates.suggestion; return $(template(context)).attr("id", _.guid()); } function suggestionTemplate(context) { return $('
').attr("id", _.guid()).text(displayFn(context)); } } function isValidName(str) { return /^[_a-zA-Z0-9-]+$/.test(str); } }(); var Menu = function() { "use strict"; function Menu(o, www) { var that = this; o = o || {}; if (!o.node) { $.error("node is required"); } www.mixin(this); this.$node = $(o.node); this.query = null; this.datasets = _.map(o.datasets, initializeDataset); function initializeDataset(oDataset) { var node = that.$node.find(oDataset.node).first(); oDataset.node = node.length ? node : $("
").appendTo(that.$node); return new Dataset(oDataset, www); } } _.mixin(Menu.prototype, EventEmitter, { _onSelectableClick: function onSelectableClick($e) { this.trigger("selectableClicked", $($e.currentTarget)); }, _onRendered: function onRendered(type, dataset, suggestions, async) { this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); this.trigger("datasetRendered", dataset, suggestions, async); }, _onCleared: function onCleared() { this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); this.trigger("datasetCleared"); }, _propagate: function propagate() { this.trigger.apply(this, arguments); }, _allDatasetsEmpty: function allDatasetsEmpty() { return _.every(this.datasets, _.bind(function isDatasetEmpty(dataset) { var isEmpty = dataset.isEmpty(); this.$node.attr("aria-expanded", !isEmpty); return isEmpty; }, this)); }, _getSelectables: function getSelectables() { return this.$node.find(this.selectors.selectable); }, _removeCursor: function _removeCursor() { var $selectable = this.getActiveSelectable(); $selectable && $selectable.removeClass(this.classes.cursor); }, _ensureVisible: function ensureVisible($el) { var elTop, elBottom, nodeScrollTop, nodeHeight; elTop = $el.position().top; elBottom = elTop + $el.outerHeight(true); nodeScrollTop = this.$node.scrollTop(); nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10); if (elTop < 0) { this.$node.scrollTop(nodeScrollTop + elTop); } else if (nodeHeight < elBottom) { this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight)); } }, bind: function() { var that = this, onSelectableClick; onSelectableClick = _.bind(this._onSelectableClick, this); this.$node.on("click.tt", this.selectors.selectable, onSelectableClick); this.$node.on("mouseover", this.selectors.selectable, function() { that.setCursor($(this)); }); this.$node.on("mouseleave", function() { that._removeCursor(); }); _.each(this.datasets, function(dataset) { dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that); }); return this; }, isOpen: function isOpen() { return this.$node.hasClass(this.classes.open); }, open: function open() { this.$node.scrollTop(0); this.$node.addClass(this.classes.open); }, close: function close() { this.$node.attr("aria-expanded", false); this.$node.removeClass(this.classes.open); this._removeCursor(); }, setLanguageDirection: function setLanguageDirection(dir) { this.$node.attr("dir", dir); }, selectableRelativeToCursor: function selectableRelativeToCursor(delta) { var $selectables, $oldCursor, oldIndex, newIndex; $oldCursor = this.getActiveSelectable(); $selectables = this._getSelectables(); oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1; newIndex = oldIndex + delta; newIndex = (newIndex + 1) % ($selectables.length + 1) - 1; newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex; return newIndex === -1 ? null : $selectables.eq(newIndex); }, setCursor: function setCursor($selectable) { this._removeCursor(); if ($selectable = $selectable && $selectable.first()) { $selectable.addClass(this.classes.cursor); this._ensureVisible($selectable); } }, getSelectableData: function getSelectableData($el) { return $el && $el.length ? Dataset.extractData($el) : null; }, getActiveSelectable: function getActiveSelectable() { var $selectable = this._getSelectables().filter(this.selectors.cursor).first(); return $selectable.length ? $selectable : null; }, getTopSelectable: function getTopSelectable() { var $selectable = this._getSelectables().first(); return $selectable.length ? $selectable : null; }, update: function update(query) { var isValidUpdate = query !== this.query; if (isValidUpdate) { this.query = query; _.each(this.datasets, updateDataset); } return isValidUpdate; function updateDataset(dataset) { dataset.update(query); } }, empty: function empty() { _.each(this.datasets, clearDataset); this.query = null; this.$node.addClass(this.classes.empty); function clearDataset(dataset) { dataset.clear(); } }, destroy: function destroy() { this.$node.off(".tt"); this.$node = $("
"); _.each(this.datasets, destroyDataset); function destroyDataset(dataset) { dataset.destroy(); } } }); return Menu; }(); var Status = function() { "use strict"; function Status(options) { this.$el = $("", { role: "status", "aria-live": "polite" }).css({ position: "absolute", padding: "0", border: "0", height: "1px", width: "1px", "margin-bottom": "-1px", "margin-right": "-1px", overflow: "hidden", clip: "rect(0 0 0 0)", "white-space": "nowrap" }); options.$input.after(this.$el); _.each(options.menu.datasets, _.bind(function(dataset) { if (dataset.onSync) { dataset.onSync("rendered", _.bind(this.update, this)); dataset.onSync("cleared", _.bind(this.cleared, this)); } }, this)); } _.mixin(Status.prototype, { update: function update(event, suggestions) { var length = suggestions.length; var words; if (length === 1) { words = { result: "result", is: "is" }; } else { words = { result: "results", is: "are" }; } this.$el.text(length + " " + words.result + " " + words.is + " available, use up and down arrow keys to navigate."); }, cleared: function() { this.$el.text(""); } }); return Status; }(); var DefaultMenu = function() { "use strict"; var s = Menu.prototype; function DefaultMenu() { Menu.apply(this, [].slice.call(arguments, 0)); } _.mixin(DefaultMenu.prototype, Menu.prototype, { open: function open() { !this._allDatasetsEmpty() && this._show(); return s.open.apply(this, [].slice.call(arguments, 0)); }, close: function close() { this._hide(); return s.close.apply(this, [].slice.call(arguments, 0)); }, _onRendered: function onRendered() { if (this._allDatasetsEmpty()) { this._hide(); } else { this.isOpen() && this._show(); } return s._onRendered.apply(this, [].slice.call(arguments, 0)); }, _onCleared: function onCleared() { if (this._allDatasetsEmpty()) { this._hide(); } else { this.isOpen() && this._show(); } return s._onCleared.apply(this, [].slice.call(arguments, 0)); }, setLanguageDirection: function setLanguageDirection(dir) { this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl); return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0)); }, _hide: function hide() { this.$node.hide(); }, _show: function show() { this.$node.css("display", "block"); } }); return DefaultMenu; }(); var Typeahead = function() { "use strict"; function Typeahead(o, www) { var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged; o = o || {}; if (!o.input) { $.error("missing input"); } if (!o.menu) { $.error("missing menu"); } if (!o.eventBus) { $.error("missing event bus"); } www.mixin(this); this.eventBus = o.eventBus; this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; this.input = o.input; this.menu = o.menu; this.enabled = true; this.autoselect = !!o.autoselect; this.active = false; this.input.hasFocus() && this.activate(); this.dir = this.input.getLangDir(); this._hacks(); this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this); onFocused = c(this, "activate", "open", "_onFocused"); onBlurred = c(this, "deactivate", "_onBlurred"); onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed"); onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed"); onEscKeyed = c(this, "isActive", "_onEscKeyed"); onUpKeyed = c(this, "isActive", "open", "_onUpKeyed"); onDownKeyed = c(this, "isActive", "open", "_onDownKeyed"); onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed"); onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed"); onQueryChanged = c(this, "_openIfActive", "_onQueryChanged"); onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged"); this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this); } _.mixin(Typeahead.prototype, { _hacks: function hacks() { var $input, $menu; $input = this.input.$input || $("
"); $menu = this.menu.$node || $("
"); $input.on("blur.tt", function($e) { var active, isActive, hasActive; active = document.activeElement; isActive = $menu.is(active); hasActive = $menu.has(active).length > 0; if (_.isMsie() && (isActive || hasActive)) { $e.preventDefault(); $e.stopImmediatePropagation(); _.defer(function() { $input.focus(); }); } }); $menu.on("mousedown.tt", function($e) { $e.preventDefault(); }); }, _onSelectableClicked: function onSelectableClicked(type, $el) { this.select($el); }, _onDatasetCleared: function onDatasetCleared() { this._updateHint(); }, _onDatasetRendered: function onDatasetRendered(type, suggestions, async, dataset) { this._updateHint(); if (this.autoselect) { var cursorClass = this.selectors.cursor.substr(1); this.menu.$node.find(this.selectors.suggestion).first().addClass(cursorClass); } this.eventBus.trigger("render", suggestions, async, dataset); }, _onAsyncRequested: function onAsyncRequested(type, dataset, query) { this.eventBus.trigger("asyncrequest", query, dataset); }, _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) { this.eventBus.trigger("asynccancel", query, dataset); }, _onAsyncReceived: function onAsyncReceived(type, dataset, query) { this.eventBus.trigger("asyncreceive", query, dataset); }, _onFocused: function onFocused() { this._minLengthMet() && this.menu.update(this.input.getQuery()); }, _onBlurred: function onBlurred() { if (this.input.hasQueryChangedSinceLastFocus()) { this.eventBus.trigger("change", this.input.getQuery()); } }, _onEnterKeyed: function onEnterKeyed(type, $e) { var $selectable; if ($selectable = this.menu.getActiveSelectable()) { if (this.select($selectable)) { $e.preventDefault(); $e.stopPropagation(); } } else if (this.autoselect) { if (this.select(this.menu.getTopSelectable())) { $e.preventDefault(); $e.stopPropagation(); } } }, _onTabKeyed: function onTabKeyed(type, $e) { var $selectable; if ($selectable = this.menu.getActiveSelectable()) { this.select($selectable) && $e.preventDefault(); } else if (this.autoselect) { if ($selectable = this.menu.getTopSelectable()) { this.autocomplete($selectable) && $e.preventDefault(); } } }, _onEscKeyed: function onEscKeyed() { this.close(); }, _onUpKeyed: function onUpKeyed() { this.moveCursor(-1); }, _onDownKeyed: function onDownKeyed() { this.moveCursor(+1); }, _onLeftKeyed: function onLeftKeyed() { if (this.dir === "rtl" && this.input.isCursorAtEnd()) { this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable()); } }, _onRightKeyed: function onRightKeyed() { if (this.dir === "ltr" && this.input.isCursorAtEnd()) { this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable()); } }, _onQueryChanged: function onQueryChanged(e, query) { this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty(); }, _onWhitespaceChanged: function onWhitespaceChanged() { this._updateHint(); }, _onLangDirChanged: function onLangDirChanged(e, dir) { if (this.dir !== dir) { this.dir = dir; this.menu.setLanguageDirection(dir); } }, _openIfActive: function openIfActive() { this.isActive() && this.open(); }, _minLengthMet: function minLengthMet(query) { query = _.isString(query) ? query : this.input.getQuery() || ""; return query.length >= this.minLength; }, _updateHint: function updateHint() { var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match; $selectable = this.menu.getTopSelectable(); data = this.menu.getSelectableData($selectable); val = this.input.getInputValue(); if (data && !_.isBlankString(val) && !this.input.hasOverflow()) { query = Input.normalizeQuery(val); escapedQuery = _.escapeRegExChars(query); frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i"); match = frontMatchRegEx.exec(data.val); match && this.input.setHint(val + match[1]); } else { this.input.clearHint(); } }, isEnabled: function isEnabled() { return this.enabled; }, enable: function enable() { this.enabled = true; }, disable: function disable() { this.enabled = false; }, isActive: function isActive() { return this.active; }, activate: function activate() { if (this.isActive()) { return true; } else if (!this.isEnabled() || this.eventBus.before("active")) { return false; } else { this.active = true; this.eventBus.trigger("active"); return true; } }, deactivate: function deactivate() { if (!this.isActive()) { return true; } else if (this.eventBus.before("idle")) { return false; } else { this.active = false; this.close(); this.eventBus.trigger("idle"); return true; } }, isOpen: function isOpen() { return this.menu.isOpen(); }, open: function open() { if (!this.isOpen() && !this.eventBus.before("open")) { this.input.setAriaExpanded(true); this.menu.open(); this._updateHint(); this.eventBus.trigger("open"); } return this.isOpen(); }, close: function close() { if (this.isOpen() && !this.eventBus.before("close")) { this.input.setAriaExpanded(false); this.menu.close(); this.input.clearHint(); this.input.resetInputValue(); this.eventBus.trigger("close"); } return !this.isOpen(); }, setVal: function setVal(val) { this.input.setQuery(_.toStr(val)); }, getVal: function getVal() { return this.input.getQuery(); }, select: function select($selectable) { var data = this.menu.getSelectableData($selectable); if (data && !this.eventBus.before("select", data.obj, data.dataset)) { this.input.setQuery(data.val, true); this.eventBus.trigger("select", data.obj, data.dataset); this.close(); return true; } return false; }, autocomplete: function autocomplete($selectable) { var query, data, isValid; query = this.input.getQuery(); data = this.menu.getSelectableData($selectable); isValid = data && query !== data.val; if (isValid && !this.eventBus.before("autocomplete", data.obj, data.dataset)) { this.input.setQuery(data.val); this.eventBus.trigger("autocomplete", data.obj, data.dataset); return true; } return false; }, moveCursor: function moveCursor(delta) { var query, $candidate, data, suggestion, datasetName, cancelMove, id; query = this.input.getQuery(); $candidate = this.menu.selectableRelativeToCursor(delta); data = this.menu.getSelectableData($candidate); suggestion = data ? data.obj : null; datasetName = data ? data.dataset : null; id = $candidate ? $candidate.attr("id") : null; this.input.trigger("cursorchange", id); cancelMove = this._minLengthMet() && this.menu.update(query); if (!cancelMove && !this.eventBus.before("cursorchange", suggestion, datasetName)) { this.menu.setCursor($candidate); if (data) { if (typeof data.val === "string") { this.input.setInputValue(data.val); } } else { this.input.resetInputValue(); this._updateHint(); } this.eventBus.trigger("cursorchange", suggestion, datasetName); return true; } return false; }, destroy: function destroy() { this.input.destroy(); this.menu.destroy(); } }); return Typeahead; function c(ctx) { var methods = [].slice.call(arguments, 1); return function() { var args = [].slice.call(arguments); _.each(methods, function(method) { return ctx[method].apply(ctx, args); }); }; } }(); (function() { "use strict"; var old, keys, methods; old = $.fn.typeahead; keys = { www: "tt-www", attrs: "tt-attrs", typeahead: "tt-typeahead" }; methods = { initialize: function initialize(o, datasets) { var www; datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1); o = o || {}; www = WWW(o.classNames); return this.each(attach); function attach() { var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, status, typeahead, MenuConstructor; _.each(datasets, function(d) { d.highlight = !!o.highlight; }); $input = $(this); $wrapper = $(www.html.wrapper); $hint = $elOrNull(o.hint); $menu = $elOrNull(o.menu); defaultHint = o.hint !== false && !$hint; defaultMenu = o.menu !== false && !$menu; defaultHint && ($hint = buildHintFromInput($input, www)); defaultMenu && ($menu = $(www.html.menu).css(www.css.menu)); $hint && $hint.val(""); $input = prepInput($input, www); if (defaultHint || defaultMenu) { $wrapper.css(www.css.wrapper); $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint); $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null); } MenuConstructor = defaultMenu ? DefaultMenu : Menu; eventBus = new EventBus({ el: $input }); input = new Input({ hint: $hint, input: $input, menu: $menu }, www); menu = new MenuConstructor({ node: $menu, datasets: datasets }, www); status = new Status({ $input: $input, menu: menu }); typeahead = new Typeahead({ input: input, menu: menu, eventBus: eventBus, minLength: o.minLength, autoselect: o.autoselect }, www); $input.data(keys.www, www); $input.data(keys.typeahead, typeahead); } }, isEnabled: function isEnabled() { var enabled; ttEach(this.first(), function(t) { enabled = t.isEnabled(); }); return enabled; }, enable: function enable() { ttEach(this, function(t) { t.enable(); }); return this; }, disable: function disable() { ttEach(this, function(t) { t.disable(); }); return this; }, isActive: function isActive() { var active; ttEach(this.first(), function(t) { active = t.isActive(); }); return active; }, activate: function activate() { ttEach(this, function(t) { t.activate(); }); return this; }, deactivate: function deactivate() { ttEach(this, function(t) { t.deactivate(); }); return this; }, isOpen: function isOpen() { var open; ttEach(this.first(), function(t) { open = t.isOpen(); }); return open; }, open: function open() { ttEach(this, function(t) { t.open(); }); return this; }, close: function close() { ttEach(this, function(t) { t.close(); }); return this; }, select: function select(el) { var success = false, $el = $(el); ttEach(this.first(), function(t) { success = t.select($el); }); return success; }, autocomplete: function autocomplete(el) { var success = false, $el = $(el); ttEach(this.first(), function(t) { success = t.autocomplete($el); }); return success; }, moveCursor: function moveCursoe(delta) { var success = false; ttEach(this.first(), function(t) { success = t.moveCursor(delta); }); return success; }, val: function val(newVal) { var query; if (!arguments.length) { ttEach(this.first(), function(t) { query = t.getVal(); }); return query; } else { ttEach(this, function(t) { t.setVal(_.toStr(newVal)); }); return this; } }, destroy: function destroy() { ttEach(this, function(typeahead, $input) { revert($input); typeahead.destroy(); }); return this; } }; $.fn.typeahead = function(method) { if (methods[method]) { return methods[method].apply(this, [].slice.call(arguments, 1)); } else { return methods.initialize.apply(this, arguments); } }; $.fn.typeahead.noConflict = function noConflict() { $.fn.typeahead = old; return this; }; function ttEach($els, fn) { $els.each(function() { var $input = $(this), typeahead; (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input); }); } function buildHintFromInput($input, www) { return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop({ readonly: true, required: false }).removeAttr("id name placeholder").removeClass("required").attr({ spellcheck: "false", tabindex: -1 }); } function prepInput($input, www) { $input.data(keys.attrs, { dir: $input.attr("dir"), autocomplete: $input.attr("autocomplete"), spellcheck: $input.attr("spellcheck"), style: $input.attr("style") }); $input.addClass(www.classes.input).attr({ spellcheck: false }); try { !$input.attr("dir") && $input.attr("dir", "auto"); } catch (e) {} return $input; } function getBackgroundStyles($el) { return { backgroundAttachment: $el.css("background-attachment"), backgroundClip: $el.css("background-clip"), backgroundColor: $el.css("background-color"), backgroundImage: $el.css("background-image"), backgroundOrigin: $el.css("background-origin"), backgroundPosition: $el.css("background-position"), backgroundRepeat: $el.css("background-repeat"), backgroundSize: $el.css("background-size") }; } function revert($input) { var www, $wrapper; www = $input.data(keys.www); $wrapper = $input.parent().filter(www.selectors.wrapper); _.each($input.data(keys.attrs), function(val, key) { _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); }); $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input); if ($wrapper.length) { $input.detach().insertAfter($wrapper); $wrapper.remove(); } } function $elOrNull(obj) { var isValid, $el; isValid = _.isJQuery(obj) || _.isElement(obj); $el = isValid ? $(obj).first() : []; return $el.length ? $el : null; } })(); }); ================================================ FILE: docs/search.json ================================================ {"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV11descriptionSSvp":{"name":"description","abstract":"

The human readable description of the ValidateClaimsResult

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV7successACvpZ":{"name":"success","abstract":"

Successful validation.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV17invalidExpirationACvpZ":{"name":"invalidExpiration","abstract":"

Invalid Expiration claim.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV7expiredACvpZ":{"name":"expired","abstract":"

Expired token: expiration time claim is in the past.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV16invalidNotBeforeACvpZ":{"name":"invalidNotBefore","abstract":"

Invalid Not Before claim.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV9notBeforeACvpZ":{"name":"notBefore","abstract":"

Not Before claim is in the future.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV15invalidIssuedAtACvpZ":{"name":"invalidIssuedAt","abstract":"

Invalid Issued At claim.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV8issuedAtACvpZ":{"name":"issuedAt","abstract":"

Issued At claim is in the future.

","parent_name":"ValidateClaimsResult"},"Structs/ValidateClaimsResult.html#/s:8SwiftJWT20ValidateClaimsResultV2eeoiySbAC_ACtFZ":{"name":"==(_:_:)","abstract":"

Check if two ValidateClaimsResults are equal. Required for the Equatable protocol

","parent_name":"ValidateClaimsResult"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5rs2569publicKeyAC10Foundation4DataV_tFZ":{"name":"rs256(publicKey:)","abstract":"

Initialize a JWTVerifier using the RSA 256 bits algorithm and the provided publicKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5rs3849publicKeyAC10Foundation4DataV_tFZ":{"name":"rs384(publicKey:)","abstract":"

Initialize a JWTVerifier using the RSA 384 bits algorithm and the provided publicKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5rs5129publicKeyAC10Foundation4DataV_tFZ":{"name":"rs512(publicKey:)","abstract":"

Initialize a JWTVerifier using the RSA 512 bits algorithm and the provided publicKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5rs25611certificateAC10Foundation4DataV_tFZ":{"name":"rs256(certificate:)","abstract":"

Initialize a JWTVerifier using the RSA 256 bits algorithm and the provided certificate.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5rs38411certificateAC10Foundation4DataV_tFZ":{"name":"rs384(certificate:)","abstract":"

Initialize a JWTVerifier using the RSA 384 bits algorithm and the provided certificate.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5rs51211certificateAC10Foundation4DataV_tFZ":{"name":"rs512(certificate:)","abstract":"

Initialize a JWTVerifier using the RSA 512 bits algorithm and the provided certificate.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5ps2569publicKeyAC10Foundation4DataV_tFZ":{"name":"ps256(publicKey:)","abstract":"

Initialize a JWTVerifier using the RSA-PSS 256 bits algorithm and the provided publicKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5ps3849publicKeyAC10Foundation4DataV_tFZ":{"name":"ps384(publicKey:)","abstract":"

Initialize a JWTVerifier using the RSA-PSS 384 bits algorithm and the provided publicKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5ps5129publicKeyAC10Foundation4DataV_tFZ":{"name":"ps512(publicKey:)","abstract":"

Initialize a JWTVerifier using the RSA-PSS 512 bits algorithm and the provided publicKey.","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5hs2563keyAC10Foundation4DataV_tFZ":{"name":"hs256(key:)","abstract":"

Initialize a JWTSigner using the HMAC 256 bits algorithm and the provided privateKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5hs3843keyAC10Foundation4DataV_tFZ":{"name":"hs384(key:)","abstract":"

Initialize a JWTSigner using the HMAC 384 bits algorithm and the provided privateKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5hs5123keyAC10Foundation4DataV_tFZ":{"name":"hs512(key:)","abstract":"

Initialize a JWTSigner using the HMAC 512 bits algorithm and the provided privateKey.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5es2569publicKeyAC10Foundation4DataV_tFZ":{"name":"es256(publicKey:)","abstract":"

Initialize a JWTVerifier using the ECDSA SHA 256 algorithm and the provided public key.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5es3849publicKeyAC10Foundation4DataV_tFZ":{"name":"es384(publicKey:)","abstract":"

Initialize a JWTVerifier using the ECDSA SHA 384 algorithm and the provided public key.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV5es5129publicKeyAC10Foundation4DataV_tFZ":{"name":"es512(publicKey:)","abstract":"

Initialize a JWTVerifier using the ECDSA SHA 512 algorithm and the provided public key.

","parent_name":"JWTVerifier"},"Structs/JWTVerifier.html#/s:8SwiftJWT11JWTVerifierV4noneACvpZ":{"name":"none","abstract":"

Initialize a JWTVerifier that will always return true when verifying the JWT. This is equivelent to using the “none” alg header.

","parent_name":"JWTVerifier"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5rs25610privateKeyAC10Foundation4DataV_tFZ":{"name":"rs256(privateKey:)","abstract":"

Initialize a JWTSigner using the RSA 256 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5rs38410privateKeyAC10Foundation4DataV_tFZ":{"name":"rs384(privateKey:)","abstract":"

Initialize a JWTSigner using the RSA 384 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5rs51210privateKeyAC10Foundation4DataV_tFZ":{"name":"rs512(privateKey:)","abstract":"

Initialize a JWTSigner using the RSA 512 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5ps25610privateKeyAC10Foundation4DataV_tFZ":{"name":"ps256(privateKey:)","abstract":"

Initialize a JWTSigner using the RSA-PSS 256 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5ps38410privateKeyAC10Foundation4DataV_tFZ":{"name":"ps384(privateKey:)","abstract":"

Initialize a JWTSigner using the RSA-PSS 384 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5ps51210privateKeyAC10Foundation4DataV_tFZ":{"name":"ps512(privateKey:)","abstract":"

Initialize a JWTSigner using the RSA-PSS 512 bits algorithm and the provided privateKey.","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5hs2563keyAC10Foundation4DataV_tFZ":{"name":"hs256(key:)","abstract":"

Initialize a JWTSigner using the HMAC 256 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5hs3843keyAC10Foundation4DataV_tFZ":{"name":"hs384(key:)","abstract":"

Initialize a JWTSigner using the HMAC 384 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5hs5123keyAC10Foundation4DataV_tFZ":{"name":"hs512(key:)","abstract":"

Initialize a JWTSigner using the HMAC 512 bits algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5es25610privateKeyAC10Foundation4DataV_tFZ":{"name":"es256(privateKey:)","abstract":"

Initialize a JWTSigner using the ECDSA SHA256 algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5es38410privateKeyAC10Foundation4DataV_tFZ":{"name":"es384(privateKey:)","abstract":"

Initialize a JWTSigner using the ECDSA SHA384 algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV5es51210privateKeyAC10Foundation4DataV_tFZ":{"name":"es512(privateKey:)","abstract":"

Initialize a JWTSigner using the ECDSA SHA512 algorithm and the provided privateKey.

","parent_name":"JWTSigner"},"Structs/JWTSigner.html#/s:8SwiftJWT9JWTSignerV4noneACvpZ":{"name":"none","abstract":"

Initialize a JWTSigner that will not sign the JWT. This is equivelent to using the “none” alg header.

","parent_name":"JWTSigner"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV20localizedDescriptionSSvp":{"name":"localizedDescription","abstract":"

A human readable description of the error.

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV16invalidJWTStringACvpZ":{"name":"invalidJWTString","abstract":"

Error when an invalid JWT String is provided

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV18failedVerificationACvpZ":{"name":"failedVerification","abstract":"

Error when the JWT signiture fails verification.

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV14osVersionToLowACvpZ":{"name":"osVersionToLow","abstract":"

Error when using RSA encryption with an OS version that is too low.

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV17invalidPrivateKeyACvpZ":{"name":"invalidPrivateKey","abstract":"

Error when an invalid private key is provided for RSA encryption.

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV15invalidUTF8DataACvpZ":{"name":"invalidUTF8Data","abstract":"

Error when the provided Data cannot be decoded to a String

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV12invalidKeyIDACvpZ":{"name":"invalidKeyID","abstract":"

Error when the KeyID field kid in the JWT header fails to generate a JWTSigner or JWTVerifier

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV17missingPEMHeadersACvpZ":{"name":"missingPEMHeaders","abstract":"

Error when a PEM string is provided without the expected PEM headers/footers. (e.g. —–BEGIN PRIVATE KEY—–)

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV2eeoiySbAC_ACtFZ":{"name":"==(_:_:)","abstract":"

Function to check if JWTErrors are equal. Required for equatable protocol.

","parent_name":"JWTError"},"Structs/JWTError.html#/s:8SwiftJWT8JWTErrorV2teoiySbAC_s5Error_ptFZ":{"name":"~=(_:_:)","abstract":"

Function to enable pattern matching against generic Errors.

","parent_name":"JWTError"},"Structs/JWT.html#/s:8SwiftJWT0B0V6headerAA6HeaderVvp":{"name":"header","abstract":"

The JWT header.

","parent_name":"JWT"},"Structs/JWT.html#/s:8SwiftJWT0B0V6claimsxvp":{"name":"claims","abstract":"

The JWT claims

","parent_name":"JWT"},"Structs/JWT.html#/s:8SwiftJWT0B0V6header6claimsACyxGAA6HeaderV_xtcfc":{"name":"init(header:claims:)","abstract":"

Initialize a JWT instance from a Header and Claims.

","parent_name":"JWT"},"Structs/JWT.html#/s:8SwiftJWT0B0V9jwtString8verifierACyxGSS_AA11JWTVerifierVtKcfc":{"name":"init(jwtString:verifier:)","abstract":"

Initialize a JWT instance from a JWT String.","parent_name":"JWT"},"Structs/JWT.html#/s:8SwiftJWT0B0V4sign5usingSSAA9JWTSignerV_tKF":{"name":"sign(using:)","abstract":"

Sign the JWT using the given algorithm and encode the header, claims and signature as a JWT String.

","parent_name":"JWT"},"Structs/JWT.html#/s:8SwiftJWT0B0V6verify_5usingSbSS_AA11JWTVerifierVtFZ":{"name":"verify(_:using:)","abstract":"

Verify the signature of the encoded JWT using the given algorithm.

","parent_name":"JWT"},"Structs/JWT.html#/s:8SwiftJWT0B0V14validateClaims6leewayAA08ValidateD6ResultVSd_tF":{"name":"validateClaims(leeway:)","abstract":"

Validate the time based standard JWT claims.","parent_name":"JWT"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3typSSSgvp":{"name":"typ","abstract":"

Type Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3algSSSgvp":{"name":"alg","abstract":"

Algorithm Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3jkuSSSgvp":{"name":"jku","abstract":"

JSON Web Token Set URL Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3jwkSSSgvp":{"name":"jwk","abstract":"

JSON Web Key Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3kidSSSgvp":{"name":"kid","abstract":"

Key ID Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3x5uSSSgvp":{"name":"x5u","abstract":"

X.509 URL Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3x5cSaySSGSgvp":{"name":"x5c","abstract":"

X.509 Certificate Chain Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3x5tSSSgvp":{"name":"x5t","abstract":"

X.509 Certificate SHA-1 Thumbprint Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV7x5tS256SSSgvp":{"name":"x5tS256","abstract":"

X.509 Certificate SHA-256 Thumbprint Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3ctySSSgvp":{"name":"cty","abstract":"

Content Type Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV4critSaySSGSgvp":{"name":"crit","abstract":"

Critical Header Parameter

","parent_name":"Header"},"Structs/Header.html#/s:8SwiftJWT6HeaderV3typ3jku3jwk3kid3x5u3x5c3x5t0J4S2563cty4critACSSSg_A4NSaySSGSgA3nPtcfc":{"name":"init(typ:jku:jwk:kid:x5u:x5c:x5t:x5tS256:cty:crit:)","abstract":"

Initialize a Header instance.

","parent_name":"Header"},"Structs/AddressClaim.html#/s:8SwiftJWT12AddressClaimV9formattedSSSgvp":{"name":"formatted","abstract":"

Full mailing address, formatted for display or use on a mailing label. This field MAY contain multiple lines, separated by newlines. Newlines can be represented either as a carriage return/line feed pair (“\\r\\n”) or as a single line feed character (“\\n”).

","parent_name":"AddressClaim"},"Structs/AddressClaim.html#/s:8SwiftJWT12AddressClaimV14street_addressSSSgvp":{"name":"street_address","abstract":"

Full street address component, which MAY include house number, street name, Post Office Box, and multi-line extended street address information. This field MAY contain multiple lines, separated by newlines. Newlines can be represented either as a carriage return/line feed pair (“\\r\\n”) or as a single line feed character (“\\n”).

","parent_name":"AddressClaim"},"Structs/AddressClaim.html#/s:8SwiftJWT12AddressClaimV8localitySSSgvp":{"name":"locality","abstract":"

City or locality component.

","parent_name":"AddressClaim"},"Structs/AddressClaim.html#/s:8SwiftJWT12AddressClaimV6regionSSSgvp":{"name":"region","abstract":"

State, province, prefecture, or region component.

","parent_name":"AddressClaim"},"Structs/AddressClaim.html#/s:8SwiftJWT12AddressClaimV11postal_codeSSSgvp":{"name":"postal_code","abstract":"

Zip code or postal code component.

","parent_name":"AddressClaim"},"Structs/AddressClaim.html#/s:8SwiftJWT12AddressClaimV7countrySSSgvp":{"name":"country","abstract":"

Country name component.

","parent_name":"AddressClaim"},"Structs/AddressClaim.html":{"name":"AddressClaim","abstract":"

Struct representing an AddressClaim as defined in the OpenID specs.

"},"Structs/Header.html":{"name":"Header","abstract":"

A representation of a JSON Web Token header."},"Structs/JWT.html":{"name":"JWT","abstract":"

A struct representing the Header and Claims of a JSON Web Token.

"},"Structs/JWTError.html":{"name":"JWTError","abstract":"

A struct representing the different errors that can be thrown by SwiftJWT

"},"Structs/JWTSigner.html":{"name":"JWTSigner","abstract":"

A struct that will be used to sign the JWT Header and Claims and generate a signed JWT."},"Structs/JWTVerifier.html":{"name":"JWTVerifier","abstract":"

A struct that will be used to verify the signature of a JWT is valid for the provided Header and Claims."},"Structs/ValidateClaimsResult.html":{"name":"ValidateClaimsResult","abstract":"

ValidateClaimsResult list the possible results of a call to JWT.validateClaims method."},"Protocols/Claims.html#/s:8SwiftJWT6ClaimsP3exp10Foundation4DateVSgvp":{"name":"exp","abstract":"

The “exp” (expiration time) claim identifies the expiration time on","parent_name":"Claims"},"Protocols/Claims.html#/s:8SwiftJWT6ClaimsP3nbf10Foundation4DateVSgvp":{"name":"nbf","abstract":"

The “nbf” (not before) claim identifies the time before which the JWT","parent_name":"Claims"},"Protocols/Claims.html#/s:8SwiftJWT6ClaimsP3iat10Foundation4DateVSgvp":{"name":"iat","abstract":"

The “iat” (issued at) claim identifies the time at which the JWT was","parent_name":"Claims"},"Protocols/Claims.html#/s:8SwiftJWT6ClaimsP6encodeSSyKF":{"name":"encode()","abstract":"

Encode the Claim object as a Base64 String.

","parent_name":"Claims"},"Protocols/Claims.html":{"name":"Claims","abstract":"

A protocol for representing the claims on a JSON web token."},"Classes/JWTDecoder.html#/s:8SwiftJWT10JWTDecoderC11jwtVerifierAcA11JWTVerifierV_tcfc":{"name":"init(jwtVerifier:)","abstract":"

Initialize a JWTDecoder instance with a single JWTVerifier.

","parent_name":"JWTDecoder"},"Classes/JWTDecoder.html#/s:8SwiftJWT10JWTDecoderC15keyIDToVerifierAcA11JWTVerifierVSgSSc_tcfc":{"name":"init(keyIDToVerifier:)","abstract":"

Initialize a JWTDecoder instance with a function to generate the JWTVerifier from the JWT kid header.

","parent_name":"JWTDecoder"},"Classes/JWTDecoder.html#/s:8SwiftJWT10JWTDecoderC6decode_10fromStringxxm_SStKSeRzlF":{"name":"decode(_:fromString:)","abstract":"

Decode a JWT instance from a JWT String.

","parent_name":"JWTDecoder"},"Classes/JWTDecoder.html#/s:8SwiftJWT10JWTDecoderC6decode_4fromxxm_10Foundation4DataVtKSeRzlF":{"name":"decode(_:from:)","abstract":"

Decode a JWT instance from a utf8 encoded JWT String.

","parent_name":"JWTDecoder"},"Classes/JWTDecoder.html#/s:8SwiftJWT10JWTDecoderC4data16base64urlEncoded10Foundation4DataVSgSS_tFZ":{"name":"data(base64urlEncoded:)","abstract":"

Initializes a new Data from the base64url-encoded String provided. The","parent_name":"JWTDecoder"},"Classes/JWTEncoder.html#/s:8SwiftJWT10JWTEncoderC9jwtSignerAcA9JWTSignerV_tcfc":{"name":"init(jwtSigner:)","abstract":"

Initialize a JWTEncoder instance with a single JWTSigner.

","parent_name":"JWTEncoder"},"Classes/JWTEncoder.html#/s:8SwiftJWT10JWTEncoderC13keyIDToSignerAcA9JWTSignerVSgSSc_tcfc":{"name":"init(keyIDToSigner:)","abstract":"

Initialize a JWTEncoder instance with a function to generate the JWTSigner from the JWT kid header.

","parent_name":"JWTEncoder"},"Classes/JWTEncoder.html#/s:8SwiftJWT10JWTEncoderC6encodey10Foundation4DataVxKSERzlF":{"name":"encode(_:)","abstract":"

Encode a JWT instance into a UTF8 encoded JWT String.

","parent_name":"JWTEncoder"},"Classes/JWTEncoder.html#/s:8SwiftJWT10JWTEncoderC14encodeToStringySSxKSERzlF":{"name":"encodeToString(_:)","abstract":"

Encode a JWT instance as a JWT String.

","parent_name":"JWTEncoder"},"Classes/JWTEncoder.html#/s:8SwiftJWT10JWTEncoderC22base64urlEncodedString4dataSS10Foundation4DataV_tFZ":{"name":"base64urlEncodedString(data:)","abstract":"

Returns a String representation of this data, encoded in base64url format","parent_name":"JWTEncoder"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3iss3sub3aud3exp3nbf3iat3jtiACSSSg_AKSaySSGSg10Foundation4DateVSgA2qKtcfc":{"name":"init(iss:sub:aud:exp:nbf:iat:jti:)","abstract":"

Initialize a ClaimsStandardJWT

","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3issSSSgvp":{"name":"iss","abstract":"

The “iss” (issuer) claim identifies the principal that issued the","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3subSSSgvp":{"name":"sub","abstract":"

The “sub” (subject) claim identifies the principal that is the","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3audSaySSGSgvp":{"name":"aud","abstract":"

The “aud” (audience) claim identifies the recipients that the JWT is","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3exp10Foundation4DateVSgvp":{"name":"exp","abstract":"

The “exp” (expiration time) claim identifies the expiration time on","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3nbf10Foundation4DateVSgvp":{"name":"nbf","abstract":"

The “nbf” (not before) claim identifies the time before which the JWT","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3iat10Foundation4DateVSgvp":{"name":"iat","abstract":"

The “iat” (issued at) claim identifies the time at which the JWT was","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsStandardJWT.html#/s:8SwiftJWT014ClaimsStandardB0C3jtiSSSgvp":{"name":"jti","abstract":"

The “jti” (JWT ID) claim provides a unique identifier for the JWT.","parent_name":"ClaimsStandardJWT"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3iss3sub3aud3exp3iat9auth_time5nonce3acr3amr3azp4name06given_Q007family_Q007middle_Q08nickname18preferred_username7profile7picture7website5email14email_verified6gender9birthdate8zoneinfo6locale12phone_number21phone_number_verified7address10updated_atACSS_SSSaySSG10Foundation4DateVA8_A8_SgSSSgA10_A5_SgA10_A10_A10_A10_A10_A10_A10_A10_A10_A10_A10_SbSgA10_A10_A10_A10_A10_A12_AA12AddressClaimVSgA9_tcfc":{"name":"init(iss:sub:aud:exp:iat:auth_time:nonce:acr:amr:azp:name:given_name:family_name:middle_name:nickname:preferred_username:profile:picture:website:email:email_verified:gender:birthdate:zoneinfo:locale:phone_number:phone_number_verified:address:updated_at:)","abstract":"

Initalise the ClaimsOpenID

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3issSSvp":{"name":"iss","abstract":"

Issuer Identifier for the Issuer of the response. The iss value is a case sensitive URL using the https scheme that contains scheme, host, and optionally, port number and path components and no query or fragment components.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3subSSvp":{"name":"sub","abstract":"

Subject Identifier. A locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client, e.g., 24400320 or AItOawmwtWwcT0k51BayewNvutrJUqsvl6qs7A4. It MUST NOT exceed 255 ASCII characters in length. The sub value is case sensitive.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3audSaySSGvp":{"name":"aud","abstract":"

Audience(s) that this ID Token is intended for. It MUST contain the OAuth 2.0 client_id of the Relying Party as an audience value. It MAY also contain identifiers for other audiences.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3exp10Foundation4DateVvp":{"name":"exp","abstract":"

Expiration time on or after which the ID Token MUST NOT be accepted for processing. The processing of this parameter requires that the current date/time MUST be before the expiration date/time listed in the value. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3iat10Foundation4DateVvp":{"name":"iat","abstract":"

Time at which the JWT was issued.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC9auth_time10Foundation4DateVSgvp":{"name":"auth_time","abstract":"

Time when the End-User authentication occurred.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC5nonceSSSgvp":{"name":"nonce","abstract":"

String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. If present in the ID Token, Clients MUST verify that the nonce Claim Value is equal to the value of the nonce parameter sent in the Authentication Request. If present in the Authentication Request, Authorization Servers MUST include a nonce Claim in the ID Token with the Claim Value being the nonce value sent in the Authentication Request. Authorization Servers SHOULD perform no other processing on nonce values used.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3acrSSSgvp":{"name":"acr","abstract":"

Authentication Context Class Reference. String specifying an Authentication Context Class Reference value that identifies the Authentication Context Class that the authentication performed satisfied. The value “0” indicates the End-User authentication did not meet the requirements of ISO/IEC 29115 level 1. Authentications with level 0 SHOULD NOT be used to authorize access to any resource of any monetary value. Parties using this claim will need to agree upon the meanings of the values used, which may be context-specific.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3amrSaySSGSgvp":{"name":"amr","abstract":"

Authentication Methods References. JSON array of strings that are identifiers for authentication methods used in the authentication. For instance, values might indicate that both password and OTP authentication methods were used. Parties using this claim will need to agree upon the meanings of the values used, which may be context-specific.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC3azpSSSgvp":{"name":"azp","abstract":"

Authorized party - the party to which the ID Token was issued. If present, it MUST contain the OAuth 2.0 Client ID of this party. This Claim is only needed when the ID Token has a single audience value and that audience is different than the authorized party. It MAY be included even when the authorized party is the same as the sole audience.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC4nameSSSgvp":{"name":"name","abstract":"

End-User’s full name in displayable form including all name parts, possibly including titles and suffixes, ordered according to the End-User’s locale and preferences.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC10given_nameSSSgvp":{"name":"given_name","abstract":"

Given name(s) or first name(s) of the End-User. Note that in some cultures, people can have multiple given names; all can be present, with the names being separated by space characters.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC11family_nameSSSgvp":{"name":"family_name","abstract":"

Surname(s) or last name(s) of the End-User. Note that in some cultures, people can have multiple family names or no family name; all can be present, with the names being separated by space characters.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC11middle_nameSSSgvp":{"name":"middle_name","abstract":"

Middle name(s) of the End-User. Note that in some cultures, people can have multiple middle names; all can be present, with the names being separated by space characters. Also note that in some cultures, middle names are not used.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC8nicknameSSSgvp":{"name":"nickname","abstract":"

Casual name of the End-User that may or may not be the same as the given_name. For instance, a nickname value of Mike might be returned alongside a given_name value of Michael.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC18preferred_usernameSSSgvp":{"name":"preferred_username","abstract":"

Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC7profileSSSgvp":{"name":"profile","abstract":"

URL of the End-User’s profile page. The contents of this Web page SHOULD be about the End-User.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC7pictureSSSgvp":{"name":"picture","abstract":"

URL of the End-User’s profile picture. This URL MUST refer to an image file (for example, a PNG, JPEG, or GIF image file), rather than to a Web page containing an image. Note that this URL SHOULD specifically reference a profile photo of the End-User suitable for displaying when describing the End-User, rather than an arbitrary photo taken by the End-User.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC7websiteSSSgvp":{"name":"website","abstract":"

URL of the End-User’s Web page or blog. This Web page SHOULD contain information published by the End-User or an organization that the End-User is affiliated with.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC5emailSSSgvp":{"name":"email","abstract":"

End-User’s preferred e-mail address.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC14email_verifiedSbSgvp":{"name":"email_verified","abstract":"

True if the End-User’s e-mail address has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this e-mail address was controlled by the End-User at the time the verification was performed. The means by which an e-mail address is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC6genderSSSgvp":{"name":"gender","abstract":"

End-User’s gender. Values defined by this specification are female and male. Other values MAY be used when neither of the defined values are applicable.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC9birthdateSSSgvp":{"name":"birthdate","abstract":"

End-User’s birthday, represented as an ISO 8601:2004 YYYY-MM-DD format. The year MAY be 0000, indicating that it is omitted. To represent only the year, YYYY format is allowed.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC8zoneinfoSSSgvp":{"name":"zoneinfo","abstract":"

String from zoneinfo time zone database representing the End-User’s time zone. For example, Europe/Paris or America/Los_Angeles.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC6localeSSSgvp":{"name":"locale","abstract":"

End-User’s locale, represented as a BCP47 language tag. This is typically an ISO 639-1 Alpha-2 language code in lowercase and an ISO 3166-1 Alpha-2 country code in uppercase, separated by a dash. For example, en-US or fr-CA. As a compatibility note, some implementations have used an underscore as the separator rather than a dash, for example, en_US; Relying Parties MAY choose to accept this locale syntax as well.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC12phone_numberSSSgvp":{"name":"phone_number","abstract":"

End-User’s preferred telephone number. E.164 is RECOMMENDED as the format of this Claim, for example, +1 (425) 555-1212 or +56 (2) 687 2400.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC21phone_number_verifiedSbSgvp":{"name":"phone_number_verified","abstract":"

True if the End-User’s phone number has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this phone number was controlled by the End-User at the time the verification was performed. The means by which a phone number is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating. When true, the phone_number Claim MUST be in E.164 format and any extensions MUST be represented in RFC 3966 format.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC7addressAA12AddressClaimVSgvp":{"name":"address","abstract":"

End-User’s preferred postal address.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsOpenID.html#/s:8SwiftJWT12ClaimsOpenIDC10updated_at10Foundation4DateVSgvp":{"name":"updated_at","abstract":"

Time the End-User’s information was last updated.

","parent_name":"ClaimsOpenID"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3iss3sub3exp3iat3jti3upn6groupsACSS_SS10Foundation4DateVAMS2SSaySSGtcfc":{"name":"init(iss:sub:exp:iat:jti:upn:groups:)","abstract":"

Initialize a ClaimsMicroProfile

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3issSSvp":{"name":"iss","abstract":"

The MP-JWT issuer. RFC7519, Section 4.1.1

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3subSSvp":{"name":"sub","abstract":"

Identifies the principal that is the subject of the JWT.

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3exp10Foundation4DateVvp":{"name":"exp","abstract":"

Identifies the expiration time on or after which the JWT MUST NOT be accepted for processing.

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3iat10Foundation4DateVvp":{"name":"iat","abstract":"

Identifies the time at which the JWT was issued.

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3jtiSSvp":{"name":"jti","abstract":"

The “jti” (JWT ID) claim provides a unique identifier for the JWT.","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC3upnSSSgvp":{"name":"upn","abstract":"

This MP-JWT custom claim is the user principal name in the java.security.Principal interface, and is the caller principal name in javax.security.enterprise.identitystore.IdentityStore. If this claim is missing, fallback to the “preferred_username”, should be attempted, and if that claim is missing, fallback to the “sub” claim should be used.

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC18preferred_usernameSSSgvp":{"name":"preferred_username","abstract":"

Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace.

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html#/s:8SwiftJWT18ClaimsMicroProfileC6groupsSaySSGvp":{"name":"groups","abstract":"

This MP-JWT custom claim is the list of group names that have been assigned to the principal of the MP-JWT. This typically will required a mapping at the application container level to application deployment roles, but a one-to-one between group names and application role names is required to be performed in addition to any other mapping.

","parent_name":"ClaimsMicroProfile"},"Classes/ClaimsMicroProfile.html":{"name":"ClaimsMicroProfile","abstract":"

A class representing the MicroProfile claims as listed in MicroProfile specs.

"},"Classes/ClaimsOpenID.html":{"name":"ClaimsOpenID","abstract":"

A class representing OpenID related claims as decsribed in OpenID specs.

"},"Classes/ClaimsStandardJWT.html":{"name":"ClaimsStandardJWT","abstract":"

A class representing the Standard JWT claims as described in RFC7519.

"},"Classes/JWTEncoder.html":{"name":"JWTEncoder","abstract":"

A thread safe encoder that signs the JWT header and claims using the provided algorithm and encodes a JWT instance as either Data or a JWT String.

"},"Classes/JWTDecoder.html":{"name":"JWTDecoder","abstract":"

A thread safe decoder that decodes either Data or a JWT String as a JWT instance and verifies the signiture using the provided algorithm.

"},"Classes.html":{"name":"Classes","abstract":"

The following classes are available globally.

"},"Protocols.html":{"name":"Protocols","abstract":"

The following protocols are available globally.

"},"Structs.html":{"name":"Structures","abstract":"

The following structures are available globally.

"}} ================================================ FILE: docs/undocumented.json ================================================ { "warnings": [ ], "source_directory": "/Users/dannys/projects/kitura/Swift-JWT" } ================================================ FILE: migration.md ================================================ ## Upgrading to Swift-JWT 3.0 Swift-JWT version 3.0 adds Codable conformance to JWT's for easier encoding and decoding. This release includes breaking changes to the Swift-JWT API and the following is a guide for converting from Swift-JWT 2.0 to Swift-JWT 3.0 ### Header: The `Header` struct is now Codable and has fixed fields representing the possible headers. As a result, the Header is now intialized by setting the field values: ```swift // Swift-JWT 2.0 let header = Header([.typ:"JWT", .kid:"KeyID"]) // Swift-JWT 3.0 let header = Header(typ: "JWT", kid: "KeyID") ``` These values can then accessed directly: ```swift // Swift-JWT 2.0 let keyID = header["kid"] // Swift-JWT 3.0 let keyID = header.kid ``` ### Claims: The JWT `Claims` has been changed to be a protocol. This means that instead of intializing a fixed `Claims` struct with a `[String: Any]` dictionary, you define and intialize your own object that conforms to claims. Alternatively, you can use one of the [example Claims implementations](https://github.com/Kitura/Swift-JWT/tree/master/Sources/SwiftJWT/ClaimsExamples) provided. ```swift // Swift-JWT 2.0 let myClaims = Claims(["iss":"Kitura"]) // Swift-JWT 3.0, User defined claims struct MyClaims: Claims { let sub: String } let myClaims = MyClaims(iss: "Kitura") // Swift-JWT 3.0, Using Standard Claims let myClaims = ClaimsStandardJWT(iss: "Kitura") ``` ### Algorithm: The `Algorithm` enum has been removed and replaced with `JWTSigner` and `JWTVerfier` structs. This change removes the requirement to specify the Key type and allows more signing and verifying algorithms to be added later. ```swift let privateKey = "".data(using: .utf8)! let publicKey = "".data(using: .utf8)! // Swift-JWT 2.0 let signer = Algorithm.rs256(privateKey, .privateKey) let verifier = Algorithm.rs256(publicKey, .publicKey) // Swift-JWT 3.0 let signer = JWTSigner.rs256(privateKey: privateKey) let verifier = JWTVerifier.rs256(publicKey: publicKey) ``` - The `isSupported` function has been removed. To see supported Algorithms, check the [README](https://github.com/Kitura/Swift-JWT#supported-algorithms) or inspect the initialisers for `JWTSigner` and `JWTVerifier`. ### JWT: - The `JWT` Struct is now generic over a `Claims` object. ```swift // Swift-JWT 2.0 let myJWT: JWT // Swift-JWT 3.0 let myJWT: JWT ``` - The `sign` function takes a `JWTSigner` and returns `String` instead of `String?`. ```swift // Swift-JWT 2.0 let signedJWT: String? = try jwt.sign(using: Algorithm.rs256(key, .privateKey)) // Swift-JWT 3.0 let signedJWT: String = try jwt.sign(using: JWTSigner.rs256(privateKey: key)) ``` - The `verify` function takes a `JWTVerifier` and no longer throws. ```swift // Swift-JWT 2.0 let verified = try JWT.verify(signedJWT, using: Algorithm.rs256(key, .publicKey)) // Swift-JWT 3.0 let verified = JWT.verify(signedJWT, using: JWTVerifier.rs256(publicKey: key)) ``` - The `validateClaims` function now only checks the `iat`, `exp`, and `nbf` claims are valid at the current point in time. ```swift // Swift-JWT 2.0 let validationResult = jwt.validateClaims(issuer: "issuer", audience: "clientID") // Swift-JWT 3.0 let validationResult = jwt.validateClaims() let validateOthers = jwt.iss == "issuer" && jwt.aud == "clientID" ``` The `encode()` function has been removed. To encode a JWT without signing it use the `none` JWTSigner: ```swift // Swift-JWT 2.0 let encodedJWT = try jwt.encoded() // Swift-JWT 3.0 let encodedJWT = try jwt.sign(using: .none) ``` The `decode()` function has been replaced with an init from String: ```swift // Swift-JWT 2.0 let decodedJWT = try JWT.decode(encodedJWT) // Swift-JWT 3.0 let decodedJWT = try JWT(jwtString: encodedJWT) ``` ## Removed APIs As a result of the new API, a number of types are now redundant and have been removed. These include: - `Supported` - `Base64URL` - `Hash` - `RSAKeyType` - `ClaimKeys`