require 'oauth/provider/authorizer' module OAuth module Controllers module ProviderController def self.included(controller) controller.class_eval do before_filter :login_required, :only => [:authorize,:revoke] oauthenticate :only => [:test_request] oauthenticate :strategies => :token, :interactive => false, :only => [:invalidate,:capabilities] oauthenticate :strategies => :two_legged, :interactive => false, :only => [:request_token] oauthenticate :strategies => :oauth10_request_token, :interactive => false, :only => [:access_token] skip_before_filter :verify_authenticity_token, :only=>[:request_token, :access_token, :invalidate, :test_request, :token] end end def request_token @token = current_client_application.create_request_token params if @token render :text => @token.to_query else render :nothing => true, :status => 401 end end def access_token @token = current_token && current_token.exchange! if @token render :text => @token.to_query else render :nothing => true, :status => 401 end end def token @client_application = ClientApplication.find_by_key! params[:client_id] if @client_application.secret != params[:client_secret] oauth2_error "invalid_client" return end # older drafts used none for client_credentials params[:grant_type] = 'client_credentials' if params[:grant_type] == 'none' logger.info "grant_type=#{params[:grant_type]}" if ["authorization_code", "password", "client_credentials"].include?(params[:grant_type]) send "oauth2_token_#{params[:grant_type].underscore}" else oauth2_error "unsupported_grant_type" end end def test_request render :text => params.collect{|k,v|"#{k}=#{v}"}.join("&") end def authorize if params[:oauth_token] @token = ::RequestToken.find_by_token! params[:oauth_token] oauth1_authorize else if request.post? @authorizer = OAuth::Provider::Authorizer.new current_user, user_authorizes_token?, params redirect_to @authorizer.redirect_uri else @client_application = ClientApplication.find_by_key! params[:client_id] render :action => "oauth2_authorize" end end end def revoke @token = current_user.tokens.find_by_token! params[:token] if @token @token.invalidate! flash[:notice] = "You've revoked the token for #{@token.client_application.name}" end redirect_to oauth_clients_url end # Invalidate current token def invalidate current_token.invalidate! head :status=>410 end # Capabilities of current_token def capabilities if current_token.respond_to?(:capabilities) @capabilities=current_token.capabilities else @capabilities={:invalidate=>url_for(:action=>:invalidate)} end respond_to do |format| format.json {render :json=>@capabilities} format.xml {render :xml=>@capabilities} end end protected def oauth1_authorize unless @token render :action=>"authorize_failure" return end unless @token.invalidated? if request.post? if user_authorizes_token? @token.authorize!(current_user) callback_url = @token.oob? ? @token.client_application.callback_url : @token.callback_url @redirect_url = URI.parse(callback_url) unless callback_url.blank? unless @redirect_url.to_s.blank? @redirect_url.query = @redirect_url.query.blank? ? "oauth_token=#{@token.token}&oauth_verifier=#{@token.verifier}" : @redirect_url.query + "&oauth_token=#{@token.token}&oauth_verifier=#{@token.verifier}" redirect_to @redirect_url.to_s else render :action => "authorize_success" end else @token.invalidate! render :action => "authorize_failure" end end else render :action => "authorize_failure" end end # http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.1.1 def oauth2_token_authorization_code @verification_code = @client_application.oauth2_verifiers.find_by_token params[:code] unless @verification_code oauth2_error return end if @verification_code.redirect_url != params[:redirect_uri] oauth2_error return end @token = @verification_code.exchange! render :json=>@token end # http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.1.2 def oauth2_token_password @user = authenticate_user( params[:username], params[:password]) unless @user oauth2_error return end @token = Oauth2Token.create :client_application=>@client_application, :user=>@user, :scope=>params[:scope] render :json=>@token end # should authenticate and return a user if valid password. Override in your own controller def authenticate_user(username,password) User.authenticate(username,password) end # autonomous authorization which creates a token for client_applications user def oauth2_token_client_credentials @token = Oauth2Token.create :client_application=>@client_application, :user=>@client_application.user, :scope=>params[:scope] render :json=>@token end # Override this to match your authorization page form def user_authorizes_token? params[:authorize] == '1' end def oauth2_error(error="invalid_grant") render :json=>{:error=>error}.to_json, :status => 400 end end end end