vapor/jwt 266
Vapor JWT provider
Vapor implementation for Apple's PassKit server requirements.
🖋 Swift ORM framework (queries, models, and relations) for building NoSQL and SQL database integrations.
*️⃣ Build SQL queries in Swift. Extensible, protocol-based design that supports DQL, DML, and DDL.
💧 A server-side Swift web framework.
issue commentvapor/jwt
Allow configuration of URIs in JWT helpers
I have created a pull request to solve this issue. It uses a separate Lock to reset the EndpointCache when the URI is modified.
comment created time in a month
PR opened vapor/jwt
<!-- 🚀 Thank you for contributing! -->
<!-- Describe your changes clearly and use examples if possible. -->
<!-- When this PR is merged, the title and body will be --> <!-- used to generate a release automatically. --> This PR closes #134. It exposes the URIs for the JWKS endpoints in the JWT-helpers for Apple, Microsoft and Google.
pr created time in a month
PR opened vapor/jwt-kit
<!-- 🚀 Thank you for contributing! -->
Not sure if I'm correct on this, but the issue failure message from a Microsoft token said Token not provided by Apple. Additionally unified error message between 3 vendors
<!-- Describe your changes clearly and use examples if possible. -->
- Unify messaging for issuer
JWTError.claimVerificationFailurefor Apple/Microsoft/Google:Token not provided by INSERT_VENDOR - change Microsoft message saying
Token not provided by AppletoToken not provided by Microsoft
<!-- When this PR is merged, the title and body will be --> Unify Vendor Claim Verification Failure Message
<!-- used to generate a release automatically. -->
pr created time in a month
issue commentvapor/jwt
Allow configuration of URIs in JWT helpers
If you set the app identifier to use Applications storage, you can wrap it in a lock, similar to how the HTTP Client works https://github.com/vapor/vapor/blob/master/Sources/Vapor/HTTP/Client/Application%2BHTTP%2BClient.swift#L19-L38
comment created time in 2 months
push eventvapor/jwt-kit
commit sha b9c8950be2530c5f55407fca723c960eae88a95f
Delete FUNDING.yml (#48)
push time in 2 months
PR merged vapor/jwt-kit
Migrate funding to the file in the central org repo
pr closed time in 2 months
push eventvapor/jwt
commit sha 7a416550b424350e4788ff5880ccc90803ddca90
Delete FUNDING.yml (#135)
push time in 2 months
PR merged vapor/jwt
Migrate funding to the file in the central org repo
pr closed time in 2 months
PR opened vapor/jwt-kit
Migrate funding to the file in the central org repo
pr created time in 2 months
PR opened vapor/jwt
Migrate funding to the file in the central org repo
pr created time in 2 months
issue openedvapor/jwt-kit
Hello there 👋 I would like to use this library with Cocoapods.
if you want I can help.
created time in 2 months
issue commentvapor/jwt
Allow configuration of URIs in JWT helpers
On further reflection, I think the current implementation of setting the applicationIdentifier is also not thread-safe.
I turned on Thread Sanitizer and wrote a small test to verify this:
func testDataRace() throws {
let app = Application(.testing)
defer { app.shutdown() }
let exp = expectation(description: "data race")
(0...10).forEach { _ in
DispatchQueue.global().async { app.jwt.microsoft.applicationIdentifier = "" }
}
DispatchQueue.global().async { exp.fulfill() }
waitForExpectations(timeout: 1, handler: nil)
}
This produces the expected runtime-exception: runtime: Threading Issues: Data race in (extension in JWT):Vapor.Application.JWT.Apple.applicationIdentifier.setter : Swift.Optional<Swift.String> at 0x7b1000039300
However, as mentioned above, in practice this probably isn't a problem, because setting the applicationIdentifier (and Endpoint-URI) more than once wouldn't make sense anyway.
For the case of the jwksEndpoint however, it may be a little bit more dangerous because changing the URI would necessarily invalidate the EndpointCache.
This leaves us with the options to either (a) expose an jwksEndpoint similar to the applicationIdentifier and ignore potential threading problems, (b) wrap everything in locks or (c) do a bigger refactor of the whole thing (there is a lot of duplicated code anyway) with the current problems in mind.
I would be happy to help with the implementation if you have a preference.
comment created time in 2 months
issue commentvapor/jwt
Allow configuration of URIs in JWT helpers
Of course, the problem is more complicated than I first thought 😉. The JWT- and Microsoft-structs are recreated on every access and all data is stored in the respective Storage-class. However, the URI cannot be stored in the storage, because it is already needed in the initializer of the storage itself.
I see several possibilities to overcome this problem:
- Store the URI in a static variable on the Mircosoft-struct such that it can be set like this:
Application.JWT.Microsoft.jwksEndpoint = "...". This is simple, but afaik setting of the static variable is not thread-safe. In practice this probably isn't a problem, because setting the URI makes only sense once during the configuration of the app anyway. - We could add a second storage / configuration class, just to store the URI. This should be clean, but very verbose and adds a lot of duplicated code.
- We could add a new additional initializer with the URI as a parameter to the extension. E.g.:
extension Application.JWT {
public func microsoft(jwksEndpoint: URI) -> Microsoft { ... }
...
}
This way, we do not have to store the URI. But we would also have to parametrize the microsoft-extension on Request.JWT such that it passes the parameter when accessing the signers:
extension Request.JWT {
public func microsoft(jwksEndpoint: URI) -> Microsoft { ... }
...
}
For (1) and (2) there is the additional constraint that a user must configure the URI before the applicationIdentifier. Otherwise it would have no effect. Perhaps we could log a warning if this happens, similar to how it is done in HTTPServer.Configuration.
If we would go down the road of (3) and parametrize the extensions on Request.JWT, one could probably go further and unify the Apple, Google and Microsoft-extensions as well. E.g., by passing a complete configuration struct.
Of course there are also other possibilities, such as requiring an explicit initialization of the storage before the first request. But this would then probably break API compatibility.
I would love to hear your thoughts on this.
comment created time in 2 months
issue commentvapor/jwt
Allow configuration of URIs in JWT helpers
Thanks for your replay. I am happy to do the PR.
comment created time in 2 months
issue commentvapor/jwt
Allow configuration of URIs in JWT helpers
I think this could be a useful enhancement. If you're happy to do the PR feel free otherwise we can add it to the backlog
comment created time in 2 months
issue closedvapor/jwt-kit
Can't verify with JWKSigner using an EC key
I may be doing something wrong here. I copied the test code from the "Add ECDSAKey support to JWKS" commit.
There are 2 issues here. First, if I replace the x, y, and privateKey values with the values from another p384 ec key, it throws an error Unable to interpret x as BN when I try to create the signer. So, instead I create the signer with a PEM and it works.
The next issue is when I try to verify, it throws: unknown kid: JWKIdentifier(string: "vapor")
` func testVerifyingECDSAKeyUsingJWK() throws { struct Foo: JWTPayload { var bar: Int func verify(using signer: JWTSigner) throws { } }
//Tried both of these
//https://mkjwk.org
//openssl ecparam -name secp384r1 -genkey -noout | docker run -i danedmunds/pem-to-jwk:latest
// Replace x,y and d from the test with new values
let x = "3an5PvBSbJHrpSJUfwTKGw45eOXIlyHWEnoxK7QU2Z2WIlpBnH2af_qLfp0sOK7d"
let y = "08OPOmWn509MbNqjLxA-0TRI_TDuq9Htj-kxcTDszsdXyROFXdaaOpngHlD6vt7b"
let privateKey = "hbSA78pRzIflWhTdl_plFvWRpqqD-c2NQji4U3pFqV6pWFCEZGT-O7eA0OIVVfLv"
// Creating the signer this way throws Unable to interpret x as BN
// let privateSigner = JWTSigner.es384(key: try ECDSAKey(parameters: .init(x: x, y: y), curve: .p384, privateKey: privateKey)) // let jwt = try privateSigner.sign(Foo(bar: 42), kid: "vapor")
let privatePEMKey = """
-----BEGIN PRIVATE KEY-----
ME4CAQAwEAYHKoZIzj0CAQYFK4EEACIENzA1AgEBBDDdqfk+8FJskeulIlR/BMob
Djl45ciXIdYSejErtBTZnZYiWkGcfZp/+ot+nSw4rt0=
-----END PRIVATE KEY-----
"""
let privatePEMSigner = JWTSigner.es256(key: try! ECDSAKey.private(pem: privatePEMKey))
let jwt = try privatePEMSigner.sign(Foo(bar: 42), kid: "vapor")
// verify using jwks without alg
let jwksString = """
{
"keys": [
{
"kty": "EC",
"use": "sig",
"kid": "vapor",
"x": "\(x)",
"y": "\(y)"
}
]
}
"""
let signers = JWTSigners()
try signers.use(jwksJSON: jwksString)
// If I create the signer with PEM, I get this far.
// However, verify() throws: unknown kid: JWKIdentifier(string: "vapor")
let foo = try signers.verify(jwt, as: Foo.self)
XCTAssertEqual(foo.bar, 42)
}`
closed time in 3 months
saltzmanjoelhissue openedvapor/jwt-kit
Error when trying to create or verify with EC keys
I may be doing something wrong here. I copied the test code from the "Add ECDSAKey support to JWKS" commit.
There are 2 issues here. First, if I replace the x, y, and privateKey values with the values from another p384 ec key, it throws an error Unable to interpret x as BN when I try to create the signer. So, instead I create the signer with a PEM and it works.
The next issue is when I try to verify, it throws: unknown kid: JWKIdentifier(string: "vapor")
` func testVerifyingECDSAKeyUsingJWK() throws { struct Foo: JWTPayload { var bar: Int func verify(using signer: JWTSigner) throws { } }
//Tried both of these
//https://mkjwk.org
//openssl ecparam -name secp384r1 -genkey -noout | docker run -i danedmunds/pem-to-jwk:latest
// Replace x,y and d from the test with new values
let x = "3an5PvBSbJHrpSJUfwTKGw45eOXIlyHWEnoxK7QU2Z2WIlpBnH2af_qLfp0sOK7d"
let y = "08OPOmWn509MbNqjLxA-0TRI_TDuq9Htj-kxcTDszsdXyROFXdaaOpngHlD6vt7b"
let privateKey = "hbSA78pRzIflWhTdl_plFvWRpqqD-c2NQji4U3pFqV6pWFCEZGT-O7eA0OIVVfLv"
// Creating the signer this way throws Unable to interpret x as BN
// let privateSigner = JWTSigner.es384(key: try ECDSAKey(parameters: .init(x: x, y: y), curve: .p384, privateKey: privateKey)) // let jwt = try privateSigner.sign(Foo(bar: 42), kid: "vapor")
let privatePEMKey = """
-----BEGIN PRIVATE KEY-----
ME4CAQAwEAYHKoZIzj0CAQYFK4EEACIENzA1AgEBBDDdqfk+8FJskeulIlR/BMob
Djl45ciXIdYSejErtBTZnZYiWkGcfZp/+ot+nSw4rt0=
-----END PRIVATE KEY-----
"""
let privatePEMSigner = JWTSigner.es256(key: try! ECDSAKey.private(pem: privatePEMKey))
let jwt = try privatePEMSigner.sign(Foo(bar: 42), kid: "vapor")
// verify using jwks without alg
let jwksString = """
{
"keys": [
{
"kty": "EC",
"use": "sig",
"kid": "vapor",
"x": "\(x)",
"y": "\(y)"
}
]
}
"""
let signers = JWTSigners()
try signers.use(jwksJSON: jwksString)
// If I create the signer with PEM, I get this far.
// However, verify() throws: unknown kid: JWKIdentifier(string: "vapor")
let foo = try signers.verify(jwt, as: Foo.self)
XCTAssertEqual(foo.bar, 42)
}`
created time in 3 months
issue openedvapor/jwt-kit
Can't verify with JWKSigner using an EC key
I may be doing something wrong here. I copied the test code from the "Add ECDSAKey support to JWKS" commit.
There are 2 issues here. First, if I replace the x, y, and privateKey values with the values from another p384 ec key, it throws an error Unable to interpret x as BN when I try to create the signer. So, instead I create the signer with a PEM and it works.
The next issue is when I try to verify, it throws: unknown kid: JWKIdentifier(string: "vapor")
` func testVerifyingECDSAKeyUsingJWK() throws { struct Foo: JWTPayload { var bar: Int func verify(using signer: JWTSigner) throws { } }
//Tried both of these
//https://mkjwk.org
//openssl ecparam -name secp384r1 -genkey -noout | docker run -i danedmunds/pem-to-jwk:latest
// Replace x,y and d from the test with new values
let x = "3an5PvBSbJHrpSJUfwTKGw45eOXIlyHWEnoxK7QU2Z2WIlpBnH2af_qLfp0sOK7d"
let y = "08OPOmWn509MbNqjLxA-0TRI_TDuq9Htj-kxcTDszsdXyROFXdaaOpngHlD6vt7b"
let privateKey = "hbSA78pRzIflWhTdl_plFvWRpqqD-c2NQji4U3pFqV6pWFCEZGT-O7eA0OIVVfLv"
// Creating the signer this way throws Unable to interpret x as BN
// let privateSigner = JWTSigner.es384(key: try ECDSAKey(parameters: .init(x: x, y: y), curve: .p384, privateKey: privateKey)) // let jwt = try privateSigner.sign(Foo(bar: 42), kid: "vapor")
let privatePEMKey = """
-----BEGIN PRIVATE KEY-----
ME4CAQAwEAYHKoZIzj0CAQYFK4EEACIENzA1AgEBBDDdqfk+8FJskeulIlR/BMob
Djl45ciXIdYSejErtBTZnZYiWkGcfZp/+ot+nSw4rt0=
-----END PRIVATE KEY-----
"""
let privatePEMSigner = JWTSigner.es256(key: try! ECDSAKey.private(pem: privatePEMKey))
let jwt = try privatePEMSigner.sign(Foo(bar: 42), kid: "vapor")
// verify using jwks without alg
let jwksString = """
{
"keys": [
{
"kty": "EC",
"use": "sig",
"kid": "vapor",
"x": "\(x)",
"y": "\(y)"
}
]
}
"""
let signers = JWTSigners()
try signers.use(jwksJSON: jwksString)
// If I create the signer with PEM, I get this far.
// However, verify() throws: unknown kid: JWKIdentifier(string: "vapor")
let foo = try signers.verify(jwt, as: Foo.self)
XCTAssertEqual(foo.bar, 42)
}`
created time in 3 months
issue openedvapor/jwt
Allow configuration of URIs in JWT helpers
I am facing the problem that I need to specify another URI to get the JWKS for the Microsoft issuer. It is currently hardcoded to "https://login.microsoftonline.com/common/discovery/keys", but I need the "v2.0"-version at "https://login.microsoftonline.com/common/discovery/v2.0/keys".
The only waythat I found to work around this issue is to copy and rename all of the JWT-Microsoft helpers (in JWT+Micorsoft.swift) and change the URI in the copy.
I would prefer it, if I could only change the URI without having to need to copy the whole other logic.
Therefore, I propose to add another public property (e.g. named jwksEndpoint) similar to applicationIdentifier that can be changed via app.jwt.microsoft.jwksEndpoint.
The same could be done for the Apple and Google helpers.
created time in 3 months
issue commentvapor-community/PassKit
Sorry, I'm new to Vapor. It Looks like I needed to add it as a package to an existing project and not to run it by itself.
comment created time in 3 months
issue closedvapor-community/PassKit
Thanks for this great effort. There is this build error in Xcode 12:
'ASN1_ENCODING_st' has different definitions in different modules; first difference is definition in module 'CNIOBoringSSL' found field
closed time in 3 months
appfactoryCoissue openedvapor-community/PassKit
Thanks for this great effort. There is this build error in Xcode 12:
'ASN1_ENCODING_st' has different definitions in different modules; first difference is definition in module 'CNIOBoringSSL' found field
created time in 3 months