Skip to content

Instantly share code, notes, and snippets.

@marcelobbfonseca
Last active September 27, 2023 02:36
Show Gist options
  • Save marcelobbfonseca/0b70c87f613bb5525957c8f27e322190 to your computer and use it in GitHub Desktop.
Save marcelobbfonseca/0b70c87f613bb5525957c8f27e322190 to your computer and use it in GitHub Desktop.
Sinatra ruby JWT authentication middleware
# To connect this middleware.rb file to your sinatra app
# add 'use JWTAuthorization' as one of your first lines in
# your Application class.
# e.g.
# require 'middlewares.rb'
# class Application < Sinatra::Base
# use JWTAuthorization
# ...
# end
require 'sinatra/json'
require 'jwt'
class JWTAuthorization
def initialize app
@app = app
end
def call env
begin
# env.fetch gets http header
# bearer = env.fetch('HTTP_AUTHORIZATION', '').split(' ')[1] # also work
bearer = env.fetch('HTTP_AUTHORIZATION').slice(7..-1) # gets JWT token
key = OpenSSL::PKey::RSA.new ENV['PUBLIC_KEY'] # read public key pem file
payload = JWT.decode bearer, key, true, { algorithm: 'RS256'} # decode and verify token with pub key
claims = payload.first
# current_user is defined by env[:user].
# useful to define current_user if you are using pundit gem
if claims['iss'] == 'user'
env[:user] = User.find_by_email(claims['email'])
end
# access your claims here...
@app.call env
rescue JWT::ExpiredSignature
[403, { 'Content-Type' => 'text/plain' }, ['The token has expired.']]
rescue JWT::DecodeError
[401, { 'Content-Type' => 'text/plain' }, ['A token must be passed.']]
rescue JWT::InvalidIssuerError
[403, { 'Content-Type' => 'text/plain' }, ['The token does not have a valid issuer.']]
rescue JWT::InvalidIatError
[403, { 'Content-Type' => 'text/plain' }, ['The token does not have a valid "issued at" time.']]
# useful only if using pundit gem
rescue Pundit::NotAuthorizedError
[401, { 'Content-Type' => 'text/plain' }, ['Unauthorized access.']]
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment