Initial commit
This commit is contained in:
177
Pods/SwiftJWT/LICENSE
generated
Normal file
177
Pods/SwiftJWT/LICENSE
generated
Normal file
@ -0,0 +1,177 @@
|
||||
|
||||
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
|
||||
245
Pods/SwiftJWT/README.md
generated
Normal file
245
Pods/SwiftJWT/README.md
generated
Normal file
@ -0,0 +1,245 @@
|
||||
<p align="center">
|
||||
<a href="http://kitura.io/">
|
||||
<img src="https://raw.githubusercontent.com/IBM-Swift/Kitura/master/Sources/Kitura/resources/kitura-bird.svg?sanitize=true" height="100" alt="Kitura">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
<p align="center">
|
||||
<a href="https://ibm-swift.github.io/Swift-JWT/index.html">
|
||||
<img src="https://img.shields.io/badge/apidoc-SwiftJWT-1FBCE4.svg?style=flat" alt="APIDoc">
|
||||
</a>
|
||||
<a href="https://travis-ci.org/IBM-Swift/Swift-JWT">
|
||||
<img src="https://travis-ci.org/IBM-Swift/Swift-JWT.svg?branch=master" alt="Build Status - Master">
|
||||
</a>
|
||||
<img src="https://img.shields.io/badge/os-macOS-green.svg?style=flat" alt="macOS">
|
||||
<img src="https://img.shields.io/badge/os-linux-green.svg?style=flat" alt="Linux">
|
||||
<img src="https://img.shields.io/badge/license-Apache2-blue.svg?style=flat" alt="Apache 2">
|
||||
<a href="http://swift-at-ibm-slack.mybluemix.net/">
|
||||
<img src="http://swift-at-ibm-slack.mybluemix.net/badge.svg" alt="Slack Status">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
# 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 4.0** 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/IBM-Swift/Swift-JWT/releases).
|
||||
```swift
|
||||
.package(url: "https://github.com/IBM-Swift/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/IBM-Swift/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:
|
||||
```
|
||||
<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:
|
||||
|
||||
```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<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.
|
||||
|
||||
```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<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:
|
||||
|
||||
```swift
|
||||
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](https://github.com/IBM-Swift/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://ibm-swift.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/IBM-Swift/Swift-JWT/blob/master/LICENSE).
|
||||
110
Pods/SwiftJWT/Sources/SwiftJWT/BlueECDSA.swift
generated
Normal file
110
Pods/SwiftJWT/Sources/SwiftJWT/BlueECDSA.swift
generated
Normal file
@ -0,0 +1,110 @@
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
}
|
||||
}
|
||||
85
Pods/SwiftJWT/Sources/SwiftJWT/BlueHMAC.swift
generated
Normal file
85
Pods/SwiftJWT/Sources/SwiftJWT/BlueHMAC.swift
generated
Normal file
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
}
|
||||
}
|
||||
128
Pods/SwiftJWT/Sources/SwiftJWT/BlueRSA.swift
generated
Normal file
128
Pods/SwiftJWT/Sources/SwiftJWT/BlueRSA.swift
generated
Normal file
@ -0,0 +1,128 @@
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
}
|
||||
}
|
||||
84
Pods/SwiftJWT/Sources/SwiftJWT/Claims.swift
generated
Normal file
84
Pods/SwiftJWT/Sources/SwiftJWT/Claims.swift
generated
Normal file
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
}
|
||||
85
Pods/SwiftJWT/Sources/SwiftJWT/ClaimsExamples/ClaimsMicroProfile.swift
generated
Normal file
85
Pods/SwiftJWT/Sources/SwiftJWT/ClaimsExamples/ClaimsMicroProfile.swift
generated
Normal file
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* 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]
|
||||
}
|
||||
200
Pods/SwiftJWT/Sources/SwiftJWT/ClaimsExamples/ClaimsOpenID.swift
generated
Normal file
200
Pods/SwiftJWT/Sources/SwiftJWT/ClaimsExamples/ClaimsOpenID.swift
generated
Normal file
@ -0,0 +1,200 @@
|
||||
/**
|
||||
* 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?
|
||||
|
||||
}
|
||||
108
Pods/SwiftJWT/Sources/SwiftJWT/ClaimsExamples/ClaimsStandardJWT.swift
generated
Normal file
108
Pods/SwiftJWT/Sources/SwiftJWT/ClaimsExamples/ClaimsStandardJWT.swift
generated
Normal file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* 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?
|
||||
}
|
||||
50
Pods/SwiftJWT/Sources/SwiftJWT/Data+Base64URLEncoded.swift
generated
Normal file
50
Pods/SwiftJWT/Sources/SwiftJWT/Data+Base64URLEncoded.swift
generated
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
}
|
||||
102
Pods/SwiftJWT/Sources/SwiftJWT/Header.swift
generated
Normal file
102
Pods/SwiftJWT/Sources/SwiftJWT/Header.swift
generated
Normal file
@ -0,0 +1,102 @@
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
}
|
||||
139
Pods/SwiftJWT/Sources/SwiftJWT/JWT.swift
generated
Normal file
139
Pods/SwiftJWT/Sources/SwiftJWT/JWT.swift
generated
Normal file
@ -0,0 +1,139 @@
|
||||
/**
|
||||
* 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 = "<PrivateKey>".data(using: .utf8)!
|
||||
let signedJWT: String? = try? jwt.sign(using: .rs256(key: key, keyType: .privateKey))
|
||||
```
|
||||
*/
|
||||
|
||||
public struct JWT<T: Claims>: 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
|
||||
}
|
||||
}
|
||||
|
||||
286
Pods/SwiftJWT/Sources/SwiftJWT/JWTDecoder.swift
generated
Normal file
286
Pods/SwiftJWT/Sources/SwiftJWT/JWTDecoder.swift
generated
Normal file
@ -0,0 +1,286 @@
|
||||
/**
|
||||
* 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 = "<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)")
|
||||
}
|
||||
```
|
||||
*/
|
||||
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<T : Decodable>(_ 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<T : Decodable>(_ 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<MyClaims> 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<T: Decodable>(_ type: T.Type) throws -> T {
|
||||
return try type.init(from: self)
|
||||
}
|
||||
|
||||
// JWT should only be a Keyed container
|
||||
func container<Key : CodingKey>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
|
||||
let container = _JWTKeyedDecodingContainer<Key>(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<Key: CodingKey>: 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<T : Decodable>(_ 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<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> 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<T: Decodable>(_ 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<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {
|
||||
return try decoder.container(keyedBy: type)
|
||||
}
|
||||
|
||||
func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
|
||||
return self
|
||||
}
|
||||
|
||||
func superDecoder() throws -> Decoder {
|
||||
return decoder
|
||||
}
|
||||
}
|
||||
234
Pods/SwiftJWT/Sources/SwiftJWT/JWTEncoder.swift
generated
Normal file
234
Pods/SwiftJWT/Sources/SwiftJWT/JWTEncoder.swift
generated
Normal file
@ -0,0 +1,234 @@
|
||||
/**
|
||||
* 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 = "<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<T : Encodable>(_ 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<T : Encodable>(_ 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<MyClaims> struct:
|
||||
```
|
||||
enum MyStructKeys: String, CodingKey {
|
||||
case header, claims
|
||||
}
|
||||
extension JWT<MyClaims>: 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<Key : CodingKey>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> {
|
||||
let container = _JWTKeyedEncodingContainer<Key>(encoder: self, codingPath: self.codingPath)
|
||||
return KeyedEncodingContainer(container)
|
||||
}
|
||||
|
||||
private struct _JWTKeyedEncodingContainer<Key: CodingKey>: 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<T : Encodable>(_ 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<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> 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<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
|
||||
return encoder.container(keyedBy: keyType)
|
||||
}
|
||||
|
||||
func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
|
||||
return self
|
||||
}
|
||||
|
||||
func superEncoder() -> Encoder {
|
||||
return encoder
|
||||
}
|
||||
|
||||
func encodeNil() throws {}
|
||||
|
||||
func encode<T>(_ value: T) throws where T : Encodable {
|
||||
throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath, debugDescription: "JWTEncoder can only encode JWT tokens"))
|
||||
}
|
||||
}
|
||||
}
|
||||
66
Pods/SwiftJWT/Sources/SwiftJWT/JWTError.swift
generated
Normal file
66
Pods/SwiftJWT/Sources/SwiftJWT/JWTError.swift
generated
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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: Error, Equatable {
|
||||
|
||||
/// A human readable description of the error.
|
||||
public let localizedDescription: 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(localizedDescription: "Input was not a valid JWT String", internalError: .invalidJWTString)
|
||||
|
||||
/// Error when the JWT signiture fails verification.
|
||||
public static let failedVerification = JWTError(localizedDescription: "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(localizedDescription: "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(localizedDescription: "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(localizedDescription: "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(localizedDescription: "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(localizedDescription: "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
|
||||
}
|
||||
}
|
||||
147
Pods/SwiftJWT/Sources/SwiftJWT/JWTSigner.swift
generated
Normal file
147
Pods/SwiftJWT/Sources/SwiftJWT/JWTSigner.swift
generated
Normal file
@ -0,0 +1,147 @@
|
||||
/**
|
||||
* 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())
|
||||
}
|
||||
|
||||
152
Pods/SwiftJWT/Sources/SwiftJWT/JWTVerifier.swift
generated
Normal file
152
Pods/SwiftJWT/Sources/SwiftJWT/JWTVerifier.swift
generated
Normal file
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* 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())
|
||||
}
|
||||
32
Pods/SwiftJWT/Sources/SwiftJWT/NoneAlgorithm.swift
generated
Normal file
32
Pods/SwiftJWT/Sources/SwiftJWT/NoneAlgorithm.swift
generated
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
}
|
||||
29
Pods/SwiftJWT/Sources/SwiftJWT/RSAKeyType.swift
generated
Normal file
29
Pods/SwiftJWT/Sources/SwiftJWT/RSAKeyType.swift
generated
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
20
Pods/SwiftJWT/Sources/SwiftJWT/SignerAlgorithm.swift
generated
Normal file
20
Pods/SwiftJWT/Sources/SwiftJWT/SignerAlgorithm.swift
generated
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
52
Pods/SwiftJWT/Sources/SwiftJWT/ValidateClaimsResult.swift
generated
Normal file
52
Pods/SwiftJWT/Sources/SwiftJWT/ValidateClaimsResult.swift
generated
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
}
|
||||
21
Pods/SwiftJWT/Sources/SwiftJWT/VerifierAlgorithm.swift
generated
Normal file
21
Pods/SwiftJWT/Sources/SwiftJWT/VerifierAlgorithm.swift
generated
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user