crystal-community / jwt Goto Github PK
View Code? Open in Web Editor NEWJWT implementation in Crystal
License: MIT License
JWT implementation in Crystal
License: MIT License
Are there any plans to support the ES algorithms?
Hey there!
Thanks for creating this shard; we need more great shards like this.
I'm trying to generate a JWT for Google OAuth2 but I'm hitting the following unhandled exception:
Unhandled exception: Invalid EVP_PKEY: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag (OpenSSL::PKey::PKeyError)
from lib/openssl_ext/src/openssl_ext/pkey.cr:9:7 in 'initialize'
from lib/openssl_ext/src/openssl_ext/pkey.cr:8:5 in 'new'
from lib/openssl_ext/src/openssl_ext/pkey.cr:28:11 in 'new'
from lib/openssl_ext/src/openssl_ext/pkey.cr:18:7 in 'new'
from lib/openssl_ext/src/openssl_ext/pkey.cr:16:5 in 'new'
from lib/jwt/src/jwt.cr:102:34 in 'sign'
from lib/jwt/src/jwt.cr:88:17 in 'encoded_signature'
from lib/jwt/src/jwt.cr:25:5 in 'encode'
from src/google-jwt-test.cr:13:5 in 'run'
from src/google-jwt-test.cr:31:1 in '__crystal_main'
from /usr/local/Cellar/crystal/0.29.0/src/crystal/main.cr:97:5 in 'main_user_code'
from /usr/local/Cellar/crystal/0.29.0/src/crystal/main.cr:86:7 in 'main'
from /usr/local/Cellar/crystal/0.29.0/src/crystal/main.cr:106:3 in 'main'
Code:
require "http/client"
require "jwt"
module Google::Jwt::Test
extend self
GOOGLE_CLIENT_ID = "foo.apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET = "bar"
GOOGLE_SCOPE = "https://www.googleapis.com/auth/devstorage.read_only"
def run
token = JWT.encode(
{"foo" => "bar"},
GOOGLE_CLIENT_SECRET,
JWT::Algorithm::RS256,
iss: GOOGLE_CLIENT_ID,
scope: GOOGLE_SCOPE,
aud: "https://www.googleapis.com/oauth2/v4/token",
exp: (Time.now + 1.hour).to_unix,
iat: Time.now.to_unix,
)
end
end
Google::Jwt::Test.run
System:
Crystal 0.29.0 (2019-06-06)
LLVM: 6.0.1
Default target: x86_64-apple-macosx
I'll try on my linux machine later. Could this be due to the OpenSSL version of the OS? (LibreSSL 2.6.5
in this case).
EDIT: Same thing on Manjaro.
Any ideas?
Regards,
James.
Any update on RSA
algorithm support?
JWT.decode currently returns payload as Hash(String, JSON::Type). JWT.decode must return payload as Hash(String, JSON::Any ).
Currently on doing shards update, I am getting a missing version warning;
rishav@rishav-sbook:~/digglu$ shards update
Resolving dependencies
Fetching https://github.com/will/crystal-pg.git
Fetching https://github.com/gdotdesign/cr-dotenv.git
Fetching https://github.com/crystal-community/jwt.git
Fetching https://github.com/evanhahn/crystal-helmet.git
Fetching https://github.com/crystal-lang/crystal-db.git
Fetching https://github.com/spider-gazelle/openssl_ext.git
Unable to satisfy the following requirements:
- `crystal (>= 0.35.0, < 2.0.0)` required by `pg 0.23.2`
- `crystal (>= 0.34.0, < 2.0.0)` required by `dotenv 1.0.0`
- `crystal (>= 0.36.1)` required by `jwt 1.5.1`
- `crystal (< 1.0.0)` required by `helmet 0.2.2`
- `crystal (>= 0.35.0, < 2.0.0)` required by `db 0.10.1`
- `crystal (>= 0.36.1)` required by `openssl_ext 2.1.4`
Failed to resolve dependencies, try updating incompatible shards or use --ignore-crystal-version as a workaround if no update is available.
There more info here https://forum.crystal-lang.org/t/weird-shards-outdated-output-crystal-1-0-0/3065
Essentially this is an explicit check to ensure that a library works with Crystal 1.0
jwt:
github: crystal-community/crystal-jwt
# shards install
...
Updating https://github.com/crystal-community/crystal-jwt.git
Username for 'https://github.com': cevarief
Password for 'https://[email protected]':
Failed to clone https://github.com/crystal-community/crystal-jwt.git
It works if i clone manually to lib folder.
Error in line 1: while requiring "./spec/integration/algorithms/none_spec.cr"
in spec/integration/algorithms/none_spec.cr:13: instantiating 'JWT:Module#decode(String, String, String)'
decoded_token = JWT.decode(token, secret_key, alg)
^~~~~~
in src/jwt.cr:40: instantiating 'validate_aud!(Hash(String, JSON::Any), Nil)'
validate_aud!(payload, opts[:aud]?) if opts[:aud]?
^~~~~~~~~~~~~
in src/jwt.cr:106: instantiating 'Array(T)#includes?(Nil)'
if !auds.includes?(aud)
^~~~~~~~~
in /usr/share/crystal/src/enumerable.cr:530: instantiating 'any?()'
any? { |e| e == obj }
^~~~
in /usr/share/crystal/src/enumerable.cr:69: instantiating 'each()'
each { |e| return true if yield e }
^~~~
in /usr/share/crystal/src/indexable.cr:148: instantiating 'each_index()'
each_index do |i|
^~~~~~~~~~
in /usr/share/crystal/src/indexable.cr:148: instantiating 'each_index()'
each_index do |i|
^~~~~~~~~~
in /usr/share/crystal/src/enumerable.cr:69: instantiating 'each()'
each { |e| return true if yield e }
^~~~
in /usr/share/crystal/src/enumerable.cr:530: instantiating 'any?()'
any? { |e| e == obj }
^~~~
in /usr/share/crystal/src/enumerable.cr:530: undefined method '==' for I
any? { |e| e == obj }
^
Rerun with --error-trace to show a complete error trace.
I recommend to set up daily builds with Travis, it helps to fix errors early.
/cc @veelenga
Hi there! Thanks for the great little library.
I wrote a small shard that adds a mixin to the JWT namespace that makes it easy to extend existing classes and structs with the optional JWT claims and serialize them with #encode
encoded = session.encode("secret", "none") do
issued_at Time.now
issuer "z64"
audience ["GitHub", "snapcase"]
end
See the full example and implementation here: https://github.com/y32/jwt_obj
This abstracts away the optional claim "codes" of "ext", "iss", etc. into a more expressive DSL, additionally letting users use Time
for applicable fields instead of writing their own epoch conversion.
It is currently built to fit our use case, but I'd be happy to PR it and make adjustments if it would complement this shard. If this shard is meant to strictly be a implementation of JWT, that's cool too ๐
Can you re-release/re-publish/re-create tag v0.2.2 because it doesn't include v0.2.2 on shard.yml, see:
and
https://github.com/crystal-community/jwt/blob/v0.2.2/shard.yml#L2
This causes problems with shards install
because dependencies will be always broken:
...
Installing jwt (0.1.0 at 0.2.2)
...
Hi, I'm trying to decode tokens generated by arangodb 3.1.23
Token is :
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ1aWQiOiI4MjY4OTEwOSIsImlhdCI6MTUwMzM5NDAwNjI1NSwicGF5bG9hZCI6eyJyb2xlIjoiRWxldmUiLCJlbWFpbCI6ImVsZXZlMUBlc3NhaS5jb20iLCJ1c2VybmFtZSI6IlAuQkFSUkVTIn0sImV4cCI6MTUwMzM5NzYwNjI1OH0.FcfRg1JYqIT9ZQQneEDRbt16_ltN6dyAfuFezsN0uBJ8jO-jAPzUYqlRJ77hKvjF2h51jvdtII5GVoEw72TIyw
Secret Key is :
fJShJ9ZH0c05eXZNzi0qcBV3WeLar2Vi9zIdo8Ggbk3LoLTpkzTef8L0AYlwzcO1YotNsaBydIYk50F2
Error is :
xception: Invalid Int32: 1503397606258 (ArgumentError)
0x4e4b87: *CallStack::unwind:Array(Pointer(Void)) at ??
0x502d48: to_i32 at /opt/crystal/src/string.cr 408:60
0x502b6c: to_i at /opt/crystal/src/string.cr 319:5
0x654e15: validate_exp! at /home/rails/servers/chatrc/lib/jwt/src/jwt.cr 85:24
0x6548e7: decode at /home/rails/servers/chatrc/lib/jwt/src/jwt.cr 38:5
0x669e84: run at /opt/crystal/src/http/web_socket.cr 255:3
0x66b8d1: call at /opt/crystal/src/http/server/handlers/websocket_handler.cr 35:9
0x66ad05: call at /home/rails/servers/chatrc/lib/kemal/src/kemal/websocket_handler.cr 12:7
0x678e47: call_next at /opt/crystal/src/http/server/handler.cr 24:7
0x678880: call at /home/rails/servers/chatrc/lib/kemal/src/kemal/common_exception_handler.cr 9:9
0x677e23: call_next at /opt/crystal/src/http/server/handler.cr 24:7
0x674a31: call at /home/rails/servers/chatrc/lib/kemal/src/kemal/common_log_handler.cr 13:35
0x5f8468: call_next at /opt/crystal/src/http/server/handler.cr 24:7
0x5f804f: call at /home/rails/servers/chatrc/lib/kemal/src/kemal/init_handler.cr 11:7
0x681c3b: process at /opt/crystal/src/http/server/request_processor.cr 39:11
0x681549: process at /opt/crystal/src/http/server/request_processor.cr 16:3
0x67ba10: handle_client at /opt/crystal/src/http/server.cr 191:5
0x4fcc6e: run at /opt/crystal/src/fiber.cr 255:3
0x4d7e36: ~proc2Proc(Fiber, (IO::FileDescriptor | Nil)) at /opt/crystal/src/concurrent.cr 61:3
0x0: ??? at ??
With latest arangodb version, token generated can be decoded
Any help will be welcome
How would you verify and read a JWT signed by a JWKS? Here are some reference libs from other languages:
https://github.com/auth0/node-jwks-rsa
https://github.com/nov/json-jwt/wiki#decode--verify
Attempting to run one of the examples (basic_usage.cr) results in the following:
aaron@t430:~/Documents/ogreets/OGV3/lib/jwt$ shards install
Fetching https://github.com/stakach/openssl_ext.git
Installing openssl_ext (1.0.0)
aaron@t430:~/Documents/ogreets/OGV3/lib/jwt$ crystal run examples/basic_usage.cr
In src/jwt.cr:116:29
116 | if exp.to_s.to_i < Time.now.to_unix
^--
Warning: Deprecated Time.now. Use `Time.local` or `Time.utc` instead.
In src/jwt.cr:122:29
122 | if nbf.to_s.to_i > Time.now.to_unix
^--
Warning: Deprecated Time.now. Use `Time.local` or `Time.utc` instead.
A total of 2 warnings were found.
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIifQ.Y3shN5Wh4FmOPM34biIm9QQmat373hJFKNxgSANQWJo"
{"foo" => "bar"}
{"typ" => "JWT", "alg" => "HS256"}
aaron@t430:~/Documents/ogreets/OGV3/lib/jwt$
I used this lib successfully for one year with crystal 0.25.1
Attempts at encode/decode using this lib in my app @0.31.1 produces the following:
17 | token = JWT.encode(uh, "secretpass", JWT::Algorithm::HS256)
^-----
Error: instantiating 'JWT:Module#encode(Hash(String, Bool | Int32 | String | Nil), String, JWT::Algorithm)'
In lib/jwt/src/jwt.cr:25:17
25 | segments << encoded_signature(algorithm, key, segments.join("."))
^----------------
Error: instantiating 'encoded_signature(JWT::Algorithm, String, String)'
In lib/jwt/src/jwt.cr:88:17
88 | signature = sign(algorithm, key, data)
^---
Error: instantiating 'sign(JWT::Algorithm, String, String)'
In lib/jwt/src/jwt.cr:102:20
102 | OpenSSL::RSA.new(key).sign(OpenSSL::Digest.new("sha256"), data)
^--
Error: instantiating 'OpenSSL::RSA.class#new(String)'
In lib/openssl_ext/src/openssl_ext/pkey.cr:16:5
16 | def self.new(encoded : String, passphrase = nil, is_private = true)
^--
Error: instantiating 'new(String, Nil, Bool)'
In lib/openssl_ext/src/openssl_ext/pkey.cr:18:12
18 | self.new(IO::Memory.new(encoded), passphrase, is_private)
^--
Error: instantiating 'OpenSSL::RSA.class#new(IO::Memory, Nil, Bool)'
In lib/openssl_ext/src/openssl_ext/pkey.cr:24:26
24 | bio = GETS_BIO.new(io)
^--
Error: instantiating 'OpenSSL::GETS_BIO.class#new(IO::Memory)'
In lib/openssl_ext/src/openssl_ext/bio.cr:16:10
16 | io.seek(position)
^---
Error: instantiating 'IO+#seek((Int32 | Int64))'
I confess to total ignorance of OpenSSL::RSA, as I can't even find it...
https://crystal-lang.org/api/0.31.1/OpenSSL.html
(the RSA part... OpenSSL is there...)
I could totally be conflating my own errors with lib errors, so any light you can give is most appreciated...
Valgrind points to a memory leak in a dependency library - spider-gazelle/openssl_ext
==29088== 316,624 (215,880 direct, 100,744 indirect) bytes in 1,799 blocks are definitely lost in loss record 110 of 110
==29088== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29088== by 0x5243F08: CRYPTO_zalloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==29088== by 0x517513C: BIO_new (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1)
==29088== by 0x2362D6: *OpenSSL::GETS_BIO#initialize<IO::Memory>:Nil (bio.cr:37)
==29088== by 0x236296: *OpenSSL::GETS_BIO::new<IO::Memory>:OpenSSL::GETS_BIO (bio.cr:36)
==29088== by 0x235D23: *OpenSSL::PKey::RSA::new<IO::Memory, Nil>:OpenSSL::PKey::RSA (rsa.cr:20)
==29088== by 0x235C5D: *OpenSSL::PKey::RSA::new<String, Nil>:OpenSSL::PKey::RSA (rsa.cr:10)
==29088== by 0x235C42: *OpenSSL::PKey::RSA::new<String>:OpenSSL::PKey::RSA (rsa.cr:9)
==29088== by 0x16B515: __crystal_main (my_test.cr:18)
where my code is
loop do
rsa = OpenSSL::PKey::RSA.new(MY_KEY_HERE)
end
Based on my experience, I believe to have narrowed it down to here. Unfortunately, I'm unqualified to deal with OpenSSL's BIO and spider-gazelle/openssl_ext repository has got Issues disabled.
I hope someone qualified enough will be here to help out.
Hello,
I used to use the jwt shard for some time and it always worked fine, until a few days ago.
Not sure if started doing something wrong or if something got broken?
require "jwt"
token = JWT.encode "token body", "hello, there", JWT::Algorithm::HS256
pp! JWT.decode token, "hello, there", JWT::Algorithm::HS256
$ crystal test.cr
JWT.decode(token, "hello, there", JWT::Algorithm::HS256) # => Unhandled exception: cast from String to Hash(K, V) failed, at /usr/lib/crystal/json/any.cr:239:5:239 (TypeCastError)
from /usr/lib/crystal/json/any.cr:239:5 in 'as_h'
from lib/jwt/src/jwt.cr:72:15 in 'decode'
from broken?.cr:6:5 in '__crystal_main'
from /usr/lib/crystal/crystal/main.cr:97:5 in 'main_user_code'
from /usr/lib/crystal/crystal/main.cr:86:7 in 'main'
from /usr/lib/crystal/crystal/main.cr:106:3 in 'main'
from __libc_start_main
from _start
from ???
$
$ Crystal 0.32.0 (2019-12-12)
LLVM: 9.0.0
Default target: x86_64-pc-linux-gnu
I did test with Crystal 0.31.1 first and had the same issue.
When trying to run the example from the README, I get the following error: undefined constant JWT::Algorithm::HS256
. My shard.yml is pulling from the master branch, but the code I have differs from the code here in the GitHub repo, and I have no idea why.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.