Verified Commit 7060621c authored by David Rybolovlev's avatar David Rybolovlev :eyeglasses:
Browse files

Change README.md. Add: raising error when signature is invalid.

No related merge requests found
Showing with 115 additions and 30 deletions
+115 -30
# Konsierge::Signature
TODO: Delete this and the text below, and describe your gem
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/konsierge/signature`. To experiment with that code, run `bin/console` for an interactive prompt.
A Ruby gem for generating and verifying digital signatures in HTTP requests for Rails API applications. This gem provides a secure way to sign and verify HTTP requests, ensuring the authenticity and integrity of API communications.
## Installation
TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
Add this line to your application's Gemfile:
Install the gem and add to the application's Gemfile by executing:
```ruby
git_source(:gitlab) {|repo| "https://gitlab.konsierge.com/digitalbox-public/gem/#{repo}.git" }
```bash
bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
gem 'konsierge-signature'
```
If bundler is not being used to manage dependencies, install the gem by executing:
And then execute:
```bash
gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
bundle install
```
## Requirements
- Ruby >= 2.7.0
## Usage
TODO: Write usage instructions here
### Configuration
First, configure the gem with your secret key:
```bash
rails g konsierge:signature:install
```
This command will create file `config/initializers/konsierge/signature.rb` with following content:
```ruby
require "konsierge/signature"
Konsierge::Signature.configure do |config|
config.secret_key = ENV["HTTP_SIGNATURE_SECRET_KEY"]
config.logger = Rails.logger
config.log_level = Rails.env.development? ? Logger::DEBUG : Logger::INFO
config.logging_enabled = ENV['HTTP_SIGNATURE_LOGGING_ENABLED']
end
```
### Generating Signatures
To generate a signature for an HTTP request:
```ruby
signer = Konsierge::Signature::Http.new(secret_key, client_token)
signature = signer.sign(
method: 'POST', # or :post
path: '/api/v1/resource', # with beginning '/'
body: {},
query: {}
)
```
### Verifying Signatures
To verify an incoming request signature:
```ruby
signer = Konsierge::Signature::Http.new(secret_key, client_token)
signature_valid = signer.verify(
method: request.method,
path: request.path,
body: request.raw_post,
query: request.query,
signature: received_signature
)
if signature_valid
# Process the request
else
# Handle invalid signature
end
```
### Rails Integration
In your Rails controller, you can add signature verification as a before_action:
```ruby
require "konsierge/signature"
class ApiController < ApplicationController
include Konsierge::Signature::Verifiable
rescue_from Konsierge::Signature::InvalidSignatureError do |e|
render_json {error: e.message}, status: 403
end
end
```
## Development
......@@ -32,12 +104,12 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/konsierge-signature. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/konsierge-signature/blob/main/CODE_OF_CONDUCT.md).
Bug reports and pull requests are welcome on GitLab at https://gitlab.konsierge.com/digitalbox-public/gem/konsierge-signature. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](CODE_OF_CONDUCT.md).
## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
## Code of Conduct
Everyone interacting in the Konsierge::Signature project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/konsierge-signature/blob/main/CODE_OF_CONDUCT.md).
Everyone interacting in the Konsierge::Signature project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](CODE_OF_CONDUCT.md).
......@@ -7,6 +7,7 @@ require_relative "signature/http"
module Konsierge
module Signature
class Error < StandardError; end
class InvalidSignatureError < StandardError; end
def self.configuration
@configuration ||= Configuration.new
......
......@@ -5,7 +5,8 @@ require "logger"
module Konsierge
module Signature
class Configuration
attr_accessor :encoding_substitutions, :logger, :log_level, :logging_enabled
attr_accessor :encoding_substitutions, :logger, :log_level
attr_writer :logging_enabled
def initialize
@secret_key = nil
......@@ -30,6 +31,10 @@ module Konsierge
def secret_key
@secret_key || raise(Error, "Secret key not set")
end
def logging_enabled
@logging_enabled.respond_to?(:call) ? @logging_enabled.call : @logging_enabled
end
end
end
end
......@@ -35,12 +35,9 @@ module Konsierge
query = request.query_parameters
body = request_body
unless signer.verify(method: method, path: path, query: query, body: body, signature: request_sign)
render json: { error: "Invalid Signature" }, status: 403
return
end
return if signer.verify(method: method, path: path, query: query, body: body, signature: request_sign)
true
raise Signature::InvalidSignatureError, "Invalid signature"
end
def request_body
......
......@@ -2,6 +2,6 @@
module Konsierge
module Signature
VERSION = "0.1.4"
VERSION = "0.1.5"
end
end
......@@ -27,13 +27,11 @@ RSpec.describe Konsierge::Signature::Verifiable, type: :request do
it "returns 200 OK" do
subject
expect(response).to have_http_status(200)
end
it "returns valid body" do
subject
expect(response.parsed_body).to eq("ok" => true)
end
......@@ -44,13 +42,11 @@ RSpec.describe Konsierge::Signature::Verifiable, type: :request do
it "returns 200 OK" do
subject
expect(response).to have_http_status(200)
end
it "returns valid body" do
subject
expect(response.parsed_body).to eq("ok" => true)
end
end
......@@ -61,16 +57,14 @@ RSpec.describe Konsierge::Signature::Verifiable, type: :request do
{ "X-Request-Sign" => "invalid_signature", "X-Client-Token" => token, "Content-Type" => "application/json" }
end
it "returns 403 Forbidden" do
it "returns 500 status" do
subject
expect(response).to have_http_status(403)
expect(response).to have_http_status(500)
end
it "returns error message" do
it "returns invalid signature error message" do
subject
expect(response.parsed_body).to eq("error" => "Invalid Signature")
expect(response.parsed_body["error"]).to match("Invalid signature")
end
end
end
......@@ -25,5 +25,21 @@ RSpec.describe Konsierge::Signature do
end
end.to raise_error(Konsierge::Signature::Error, "Secret key not set")
end
it "allows setting and getting the logging enabled" do
described_class.configure do |config|
config.logging_enabled = true
end
expect(described_class.configuration.logging_enabled).to be(true)
end
it "allows setting and getting the logging enabled as proc" do
described_class.configure do |config|
config.logging_enabled = -> { true }
end
expect(described_class.configuration.logging_enabled).to be(true)
end
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment