Type:
Module
Constants:
TOKEN_KEY
:
'token='
TOKEN_REGEX
:
/^Token /
AUTHN_PAIR_DELIMITERS
:
/(?:,|;|\t+)/
Makes it dead easy to do HTTP Token authentication.
Simple Token example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class PostsController < ApplicationController TOKEN = "secret" before_action :authenticate , except: [ :index ] def index render plain: "Everyone can see me!" end def edit render plain: "I'm only accessible if you know the password" end private def authenticate authenticate_or_request_with_http_token do |token, options| token == TOKEN end end end |
Here is a more advanced Token example where only Atom feeds and the XML API is protected by HTTP token authentication, the regular HTML interface is protected by a session approach:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class ApplicationController < ActionController::Base before_action :set_account , :authenticate protected def set_account @account = Account.find_by(url_name: request.subdomains.first) end def authenticate case request.format when Mime:: XML , Mime:: ATOM if user = authenticate_with_http_token { |t, o| @account .users.authenticate(t, o) } @current_user = user else request_http_token_authentication end else if session_authenticated? @current_user = @account .users.find(session[ :authenticated ][ :user_id ]) else redirect_to(login_url) and return false end end end end |
In your integration tests, you can do something like this:
1 2 3 4 5 6 7 8 | def test_access_granted_from_xml get( "/notes/1.xml" , nil , 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Token.encode_credentials(users( :dhh ).token) ) assert_equal 200 , status end |
On shared hosts, Apache sometimes doesn't pass authentication headers to FCGI instances. If your environment matches this description and you cannot authenticate, try this rule in your Apache setup:
1 | RewriteRule ^(.*)$ dispatch.fcgi [ E = X - HTTP_AUTHORIZATION :%{ HTTP :Authorization}, QSA , L ] |