Skip to content

Commit

Permalink
playing around with jwt lib
Browse files Browse the repository at this point in the history
  • Loading branch information
kickster97 committed Jan 17, 2025
1 parent 53cd6de commit 7621056
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 10 deletions.
12 changes: 12 additions & 0 deletions shard.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,22 @@ shards:
git: https://github.com/cloudamqp/amqp-client.cr.git
version: 1.2.8

bindata:
git: https://github.com/spider-gazelle/bindata.git
version: 2.1.0

jwt:
git: https://github.com/crystal-community/jwt.git
version: 1.6.1

lz4:
git: https://github.com/84codes/lz4.cr.git
version: 1.0.0+git.commit.96d714f7593c66ca7425872fd26c7b1286806d3d

openssl_ext:
git: https://github.com/spider-gazelle/openssl_ext.git
version: 2.4.4

systemd:
git: https://github.com/84codes/systemd.cr.git
version: 2.0.0
Expand Down
2 changes: 2 additions & 0 deletions shard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ dependencies:
github: 84codes/systemd.cr
lz4:
github: 84codes/lz4.cr
jwt:
github: crystal-community/jwt

development_dependencies:
ameba:
Expand Down
2 changes: 2 additions & 0 deletions src/lavinmq/auth/auth_handler.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module LavinMQ
abstract class AuthHandler
Log = LavinMQ::Log.for "auth.handler"
property successor : AuthHandler?
@log = Logger.new(Log)

abstract def authenticate(username : String, password : String)

Expand Down
3 changes: 1 addition & 2 deletions src/lavinmq/auth/handlers/basic_auth.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ module LavinMQ

def authenticate(username : String, password : String)
user = @users[username]
# TODO: do not do authentication check if the user is not in the userstore, instead pass directly to the next handler
return user if user && user.password && user.password.not_nil!.verify(password)
puts "Basic authentication failed"
@log.warn { "Basic authentication failed" }
try_next(username, password)
end
end
Expand Down
4 changes: 2 additions & 2 deletions src/lavinmq/auth/handlers/http.cr
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ module LavinMQ
def authenticate(username : String, password : String)
# TODO: implement the HTTP authentication logic and permissions parser here
if password.starts_with?("http")
puts "HTTP authentication successful"
@log.warn { "HTTP authentication successful" }
return @users[username]
else
puts "HTTP authentication failed"
@log.warn { "HTTP authentication failed" }
return try_next(username, password)
end
end
Expand Down
29 changes: 23 additions & 6 deletions src/lavinmq/auth/handlers/oauth2.cr
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
require "../auth_handler"
require "jwt"
require "../../config"

module LavinMQ
class OAuth2Handler < LavinMQ::AuthHandler
def initialize(@users : UserStore)
end

# Temporary for tests
@token : String = LavinMQ::Config.instance.token
@public_key : String = LavinMQ::Config.instance.public_key

def authenticate(username : String, password : String)
# TODO: implement the OAuth2 authentication logic and permissions parser here
if password.starts_with?("oauth")
puts "OAuth2 authentication successful"
@users[username]
else
puts "OAuth2 authentication failed"
begin
payload, header = JWT.decode(@token, key: @public_key, algorithm: JWT::Algorithm::RS256, verify: true, validate: true)
oauth_user
rescue ex : JWT::DecodeError
@log.warn { "OAuth2 authentication failed, could not decode token: #{ex}" }
try_next(username, password)
rescue ex : JWT::UnsupportedAlgorithmError
@log.warn { "OAuth2 authentication failed, unsupported algortihm: #{ex}" }
try_next(username, password)
rescue ex
@log.warn { "OAuth2 authentication failed: #{ex}" }
try_next(username, password)
end
end

def oauth_user
# TODO: Create a uset that will be deleted when it disconnects, but also cannot be authorised with basic auth.
# introduce the needed configs for validation, and parse the payload to get the user details
user = @users.create("oauth_user", "password")
end
end
end
5 changes: 5 additions & 0 deletions src/lavinmq/config.cr
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ module LavinMQ
property http_auth_url : String? = ""
property oauth_url : String? = ""
property auth_backends = ["basic", "oauth", "http"]
#this will be fetched from an jwks endpoint
property public_key = ""
# this will come from the connect packet
property token = ""

@@instance : Config = self.new

def self.instance : LavinMQ::Config
Expand Down

0 comments on commit 7621056

Please sign in to comment.