add jwt with claims functionality.

This commit is contained in:
josephroy99 2023-12-14 00:18:12 +00:00
parent e925905a4a
commit 894b2af373
5 changed files with 106 additions and 22 deletions

View File

@ -11,5 +11,6 @@ gem 'jwt'
gem 'sqlite3' gem 'sqlite3'
gem 'bcrypt' gem 'bcrypt'
gem 'securerandom' gem 'securerandom'
gem 'json'
# bundle install # bundle install

View File

@ -2,6 +2,7 @@ GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
bcrypt (3.1.20) bcrypt (3.1.20)
json (2.7.1)
jwt (2.7.1) jwt (2.7.1)
mustermann (3.0.0) mustermann (3.0.0)
ruby2_keywords (~> 0.0.1) ruby2_keywords (~> 0.0.1)
@ -24,6 +25,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
bcrypt bcrypt
json
jwt jwt
securerandom securerandom
sinatra sinatra

View File

@ -53,7 +53,40 @@ post '/auth/login' do
reauthJWT = get_reauth_jwt user_id reauthJWT = get_reauth_jwt user_id
return reauthJWT.to_json return {token: reauthJWT}.to_json
end
post '/auth/reauthenticate' do
content_type :json
authorization_header = request.env['HTTP_AUTHORIZATION']
unless authorization_header && authorization_header.match(/^Bearer (.+)/)
status 401
return { reply: 'Unauthorized Access. Token missing or invalid.' }.to_json
end
reauth_token = Regexp.last_match(1)
hmac_secret = 'WChX-tQWbGbj_pGJQREoFAZGC9JWh58KSk8O7KPj-P8Nd-J88g3eSFDVuNe6zddj0ZB3yxjm_IuPNPyLhiSnxlWHImqXR6ajh3OzrzYm0bNb3f5C4IAScphyEdAfYGMcM-HvYOXxxxp5u5mryfiV3JH1CTqL1CzGyO8df7zUpRKXEXZ5SKmUvhfLU0XKCR_28FAZUgPCAi3GywkDDsH0by68j33BU5cnMT8KiEkHOX4wVUVDQc85_AuE7fN3ji_WkhnDCSLXU9dBCcXM3ziFFeX0RbvIRDG0vKdzwt4TOr4Jws7NP9w11GrUGDFKARZqvT7FTxwxO3MM-mmjb2xyGg'
begin
# Verify the token using the secret key
decoded_token = JWT.decode(reauth_token, hmac_secret, true, algorithm: 'HS256')
# At this point, the token is valid
# You can access the claims inside the 'decoded_token' variable
uid = decoded_token.first['uid']
# Your reauthentication logic here...
# Return a response (replace with your own logic)
{ reply: get_jwt(uid) }.to_json
rescue JWT::DecodeError
status 401
return { reply: 'Unauthorized Access. Invalid token.' }.to_json
end
end end
def get_reauth_jwt (user_id) def get_reauth_jwt (user_id)
@ -73,6 +106,23 @@ def get_reauth_jwt (user_id)
#data: {time: 'now', help: 'no'}.to_json #data: {time: 'now', help: 'no'}.to_json
end end
def get_jwt (user_id)
claims = get_claims user_id
payload = {
sub: 'authentication' ,
admin: check_if_user_is_admin(user_id),
iss: 'roysathome.net',
uid: user_id, #Example id
iat: Time.now.to_i,
exp: Time.now.to_i + 60,
claims: claims
}
hmac_secret = 'WChX-tQWbGbj_pGJQREoFAZGC9JWh58KSk8O7KPj-P8Nd-J88g3eSFDVuNe6zddj0ZB3yxjm_IuPNPyLhiSnxlWHImqXR6ajh3OzrzYm0bNb3f5C4IAScphyEdAfYGMcM-HvYOXxxxp5u5mryfiV3JH1CTqL1CzGyO8df7zUpRKXEXZ5SKmUvhfLU0XKCR_28FAZUgPCAi3GywkDDsH0by68j33BU5cnMT8KiEkHOX4wVUVDQc85_AuE7fN3ji_WkhnDCSLXU9dBCcXM3ziFFeX0RbvIRDG0vKdzwt4TOr4Jws7NP9w11GrUGDFKARZqvT7FTxwxO3MM-mmjb2xyGg'
return JWT.encode payload, hmac_secret, 'HS256'
end
def get_claims (user_id) def get_claims (user_id)
puts "Getting claims for #{user_id}" puts "Getting claims for #{user_id}"
db = SQLite3::Database.new('./database/auth.db') db = SQLite3::Database.new('./database/auth.db')
@ -85,15 +135,18 @@ def get_claims (user_id)
', user_id) ', user_id)
claims_list = []
if results.empty? if results.empty?
puts 'No claims found.' puts 'No claims found.'
else else
results.each do |column| results.each do |column|
puts "#{column[0]}" claim = column[0]
claims_list << claim
end end
end end
return results return claims_list
end end
# Run the application # Run the application

View File

@ -20,34 +20,36 @@ def initialize_database
db.execute('CREATE TABLE IF NOT EXISTS claims (id INTEGER PRIMARY KEY, claim TEXT)') db.execute('CREATE TABLE IF NOT EXISTS claims (id INTEGER PRIMARY KEY, claim TEXT)')
db.execute('CREATE TABLE IF NOT EXISTS user_claims (id INTEGER PRIMARY KEY, user_id INTEGER, claim_id INTEGER)') db.execute('CREATE TABLE IF NOT EXISTS user_claims (id INTEGER PRIMARY KEY, user_id INTEGER, claim_id INTEGER)')
result = db.get_first_value('SELECT COUNT(*) FROM claims')
if result == 0
db.execute('INSERT INTO claims (claim) VALUES (?)', ['add_user'])
db.execute('INSERT INTO claims (claim) VALUES (?)', ['remove_user'])
db.execute('INSERT INTO claims (claim) VALUES (?)', ['is_machine'])
db.execute('INSERT INTO claims (claim) VALUES (?)', ['is_user'])
db.execute('INSERT INTO claims (claim) VALUES (?)', ['add_claim_to_user'])
db.execute('INSERT INTO claims (claim) VALUES (?)', ['remove_claim_from_user'])
end
result = db.get_first_value('SELECT COUNT(*) FROM users') result = db.get_first_value('SELECT COUNT(*) FROM users')
if result == 0 if result == 0
puts 'Default admin user added.' puts 'Default admin user added.'
create_new_user('admin', 'pass123', 1) create_new_user('admin', 'pass123', 1)
admin_user_id = db.get_first_value('SELECT id FROM users WHERE username = ?', ['admin'])
claim_ids = db.execute('SELECT id FROM claims')
claim_ids.each do |claim_id|
db.execute('INSERT INTO user_claims (user_id, claim_id) VALUES (?, ?)', [admin_user_id, claim_id])
end
else else
puts 'Table already contains data. Skipping default user creation.' puts 'Table already contains data. Skipping default user creation.'
end end
result = db.get_first_value('SELECT COUNT(*) FROM claims')
if result == 0
db.execute('INSERT INTO claims (claim) VALUES (?)', ['add_user'])
db.execute('INSERT INTO claims (claim) VALUES (?)', ['remove_user'])
db.execute('INSERT INTO claims (claim) VALUES (?)', ['add_claim_to_user'])
db.execute('INSERT INTO claims (claim) VALUES (?)', ['is_machine'])
db.execute('INSERT INTO claims (claim) VALUES (?)', ['is_user'])
db.execute('INSERT INTO claims (claim) VALUES (?)', ['remove_claim_from_user'])
db.execute('INSERT INTO claims (claim) VALUES (?)', ['remove_claim_from_user'])
db.execute('INSERT INTO claims (claim) VALUES (?)', ['remove_claim_from_user'])
end
admin_user_id = db.get_first_value('SELECT id FROM users WHERE username = ?', ['admin'])
claim_ids = db.execute('SELECT id FROM claims')
claim_ids.each do |claim_id|
db.execute('INSERT INTO user_claims (user_id, claim_id) VALUES (?, ?)', [admin_user_id, claim_id])
end
end end

View File

@ -1,5 +1,6 @@
require 'net/http' require 'net/http'
require 'uri' require 'uri'
require 'json'
# The URL you want to send the POST request to # The URL you want to send the POST request to
url = URI.parse('http://localhost:4567/auth/login') url = URI.parse('http://localhost:4567/auth/login')
@ -28,6 +29,31 @@ request['Content-Type'] = 'application/x-www-form-urlencoded'
# Send the request and get the response # Send the request and get the response
response = http.request(request) response = http.request(request)
# Output the response unless response.code == '200'
puts "Response Code: #{response.code}" puts "Response Code: #{response.code}. Aborting."
puts "Response Body: #{response.body}" puts "Response Body: #{response.body}"
puts "Aborting."
exit
end
puts 'Reauthentication token stored.'
response_data = JSON.parse(response.body)
reauthentication_token = response_data['token']
url = URI.parse('http://localhost:4567/auth/reauthenticate')
request = Net::HTTP::Post.new(url.path)
request['Authorization'] = "Bearer #{reauthentication_token}"
response = http.request(request)
unless response.code == '200'
puts "Response Code: #{response.code}. Aborting."
puts "Response Body: #{response.body}"
puts "Aborting."
exit
end
puts response.body