api/methods/auth.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Peas
  class API < Grape::API
    # /auth
    resource :auth do
      # POST /auth/request
      desc "Request authentication with username and public key, returns document to sign"
      params do
        requires :username, type: String, desc: "Username", allow_blank: false
        requires :public_key, type: String, desc: "User's SSH public key", allow_blank: false
      end
      post :request do
        response = {}
        user = User.where username: params[:username]
        if user.length == 0
          if User.count == 0
            # Automatically add the user if they are the first in the DB
            user = User.create! username: params[:username], public_key: params[:public_key]
            response[:user_added] = [user.username, user.public_key]
          else
            status 400
            return respond 'User does not exist, ask admin user to add you', :error
          end
        else
          user = user.first
        end
        user.signme = SecureRandom.urlsafe_base64 64
        user.save!
        response[:sign] = user.signme
        respond response
      end

      # POST /auth/verify
      desc "Verify a signed document. Returns a new API key"
      params do
        requires :username, type: String, desc: "Username", allow_blank: false
        requires :signed, type: String, desc: "A Base64 encoded OpenSSL signed document", allow_blank: false
      end
      post :verify do
        user = User.find_by username: params[:username]
        # Convert the SSH key to an OpenSSL key
        public_key = OpenSSHKeyConverter.decode_pubkey user.public_key
        document = user.signme
        signature = base64_url_decode params[:signed]
        # Confirm that the user signed the doc with the private key that pairs with their public key
        if public_key.verify(OpenSSL::Digest::SHA256.new, signature, document)
          # Issue them an api_key which can be used to access methods on the API
          api_key = SecureRandom.urlsafe_base64 64
          user.api_key = api_key
          user.save!
          return respond api_key: api_key
        else
          status 406
          return respond 'Could not verify signed document', :error
        end
      end
    end
  end
end