add jwt with claims functionality.
This commit is contained in:
parent
e925905a4a
commit
894b2af373
|
@ -11,5 +11,6 @@ gem 'jwt'
|
||||||
gem 'sqlite3'
|
gem 'sqlite3'
|
||||||
gem 'bcrypt'
|
gem 'bcrypt'
|
||||||
gem 'securerandom'
|
gem 'securerandom'
|
||||||
|
gem 'json'
|
||||||
|
|
||||||
# bundle install
|
# bundle install
|
|
@ -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
|
||||||
|
|
59
auth/auth.rb
59
auth/auth.rb
|
@ -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
|
||||||
|
|
|
@ -20,28 +20,23 @@ 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)
|
||||||
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'])
|
admin_user_id = db.get_first_value('SELECT id FROM users WHERE username = ?', ['admin'])
|
||||||
claim_ids = db.execute('SELECT id FROM claims')
|
claim_ids = db.execute('SELECT id FROM claims')
|
||||||
|
@ -49,5 +44,12 @@ def initialize_database
|
||||||
claim_ids.each do |claim_id|
|
claim_ids.each do |claim_id|
|
||||||
db.execute('INSERT INTO user_claims (user_id, claim_id) VALUES (?, ?)', [admin_user_id, claim_id])
|
db.execute('INSERT INTO user_claims (user_id, claim_id) VALUES (?, ?)', [admin_user_id, claim_id])
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
puts 'Table already contains data. Skipping default user creation.'
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
32
auth/post.rb
32
auth/post.rb
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue