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 'bcrypt'
gem 'securerandom'
gem 'json'
# bundle install

View File

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

View File

@ -53,7 +53,40 @@ post '/auth/login' do
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
def get_reauth_jwt (user_id)
@ -73,6 +106,23 @@ def get_reauth_jwt (user_id)
#data: {time: 'now', help: 'no'}.to_json
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)
puts "Getting claims for #{user_id}"
db = SQLite3::Database.new('./database/auth.db')
@ -85,15 +135,18 @@ def get_claims (user_id)
', user_id)
claims_list = []
if results.empty?
puts 'No claims found.'
else
results.each do |column|
puts "#{column[0]}"
claim = column[0]
claims_list << claim
end
end
return results
return claims_list
end
# 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 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')
if result == 0
puts 'Default admin user added.'
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
puts 'Table already contains data. Skipping default user creation.'
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

View File

@ -1,5 +1,6 @@
require 'net/http'
require 'uri'
require 'json'
# The URL you want to send the POST request to
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
response = http.request(request)
# Output the response
puts "Response Code: #{response.code}"
puts "Response Body: #{response.body}"
unless response.code == '200'
puts "Response Code: #{response.code}. Aborting."
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