web-dev-qa-db-ja.com

シナトラ-API-認証

シナトラで小さなAPIアプリケーションを開発します。 API呼び出しを保護するために使用できる認証オプションは何ですか?

58
Saim

Sinatraには組み込みの認証サポートはありません。利用可能な宝石はいくつかありますが、ほとんどはユーザー認証用に設計されています(つまり、ウェブサイト用)。 APIについては、やり過ぎのようです。自分で作るのは簡単です。各ルートのリクエストパラメータをチェックして、有効なAPIキーが含まれているかどうかを確認し、含まれていない場合は401エラーを返します。

helpers do
  def valid_key? (key)
    false
  end
end

get "/" do
  error 401 unless valid_key?(params[:key])

  "Hello, world."
end

#  $ irb -r open-uri
#  >> open("http://yourapp.com/api/?key=123")
#  OpenURI::HTTPError: 401 Unauthorized

errorの呼び出し後、valid_key?メソッドはfalseを返します— errorは内部でhaltを呼び出し、リクエストの続行を停止します。

もちろん、各ルートの最初にチェックを繰り返すことは理想的ではありません。代わりに、ルートに条件を追加する小さな拡張を作成できます。

class App < Sinatra::Base
  register do
    def check (name)
      condition do
        error 401 unless send(name) == true
      end
    end
  end

  helpers do
    def valid_key?
      params[:key].to_i % 2 > 0
    end
  end

  get "/", :check => :valid_key? do
    [1, 2, 3].to_json
  end
end

すべてのルートで認証だけが必要な場合は、beforeハンドラーを使用します。

before do
  error 401 unless params[:key] =~ /^xyz/
end

get "/" do
  {"e" => mc**2}.to_json
end
89
Todd Yandell

http://www.secondforge.com/blog/2014/11/05/simple-api-authentication-in-sinatra/ には、ユーザートークンを使用する少し詳細な回答があります。

これは、APIキーよりも1ステップ複雑ですが、名前/メール/パスワードの編集やユーザーごとの情報へのアクセスなどを行うためにAPIがユーザーにログインするための認証が必要な場合に必要です。 (つまり、「プライベート」APIアクション)。また、ユーザートークンを取り消したり、期限切れにしたりして、ユーザーをログアウトさせることもできます。

class App < Sinatra::Base

  before do
    begin
      if request.body.read(1)
        request.body.rewind
        @request_payload = JSON.parse request.body.read, { symbolize_names: true }
      end
    rescue JSON::ParserError => e
      request.body.rewind
      puts "The body #{request.body.read} was not JSON"
    end
  end

  post '/login' do
    params = @request_payload[:user]

    user = User.find(email: params[:email])
    if user.password == params[:password] #compare the hash to the string; magic
      #log the user in
    else
      #tell the user they aren't logged in
    end
  end
end

(JSON本体ではなくHTTPヘッダーから資格情報を読み取る方が一般的であることに注意する価値がありますが、作成者はそれについて言及しています。)

2
chug2k

更新

最近では、トークンベースの認証が普及しています。単純な認証と承認のために、Ruby JWT標準の実装Ruby-jwtによる実装)を使用することをお勧めします。

gem 'jwt'
1
Marcelo Fonseca