Created
December 11, 2011 15:16
-
-
Save dblock/1461070 to your computer and use it in GitHub Desktop.
An updated OAuth2 controller for a Rails app (implies you have ClientApplication and AccessGrant)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class OauthController < ApplicationController | |
class ApiOAuthError < StandardError | |
attr_accessor :code, :description, :uri, :state | |
def initialize(code, description, uri = nil, state = nil) | |
@code = code | |
@description = description | |
@uri = uri | |
@state = state | |
end | |
end | |
before_filter :authenticate_user!, :except => [:access_token] | |
before_filter :expires_now | |
skip_before_filter :app_initialization, :retrieve_api, :verify_authenticity_token, :only => [:access_token] | |
rescue_from ApiOAuthError, :with => :oauth2_error | |
def oauth2_error(e) | |
# see http://tools.ietf.org/html/draft-ietf-oauth-v2-10 | |
error = { :error => e.code } | |
error[:error_description] = e.description unless e.description.blank? | |
error[:error_uri] = e.uri unless e.uri.blank? | |
error[:state] = e.state unless e.state.blank? | |
render :json => error, :status => 401 | |
end | |
def authorize | |
# client id | |
client_id = params[:client_id] | |
raise ApiOAuthError.new(:invalid_client, "missing client_id", nil, params[:state]) if client_id.blank? | |
# response type | |
response_type = params[:response_type] | |
raise ApiOAuthError.new(:unsupported_response_type, "missing response_type", nil, params[:state]) if response_type.blank? | |
raise ApiOAuthError.new(:unsupported_response_type, "unsupported response_type: #{params[:response_type]}", nil, params[:state]) unless response_type == 'code' | |
# client application | |
application = ClientApplication.where({:app_id => client_id}).first | |
raise ApiOAuthError.new(:invalid_client, "invalid client_id: #{client_id}", nil, params[:state]) unless application | |
raise ApiOAuthError.new(:access_denied, "invalid client_id: #{client_id}", nil, params[:state]) unless application.access_granted | |
# TODO: raise unauthorized_client if client is disabled | |
AccessGrant.prune! | |
access_grant = current_user.access_grants.create({:application => application}) | |
redirect_uri = access_grant.redirect_uri_for(params[:redirect_uri], params[:state]) | |
redirect_to redirect_uri | |
end | |
def access_token | |
# client id | |
client_id = params[:client_id] | |
raise ApiOAuthError.new(:invalid_client, "missing client_id", nil, params[:state]) if client_id.blank? | |
# client application | |
application = ClientApplication.where({:app_id => client_id}).first | |
raise ApiOAuthError.new(:invalid_client, "invalid client_id: #{client_id}", nil, params[:state]) unless application | |
# TODO: raise unauthorized_client if client is disabled | |
application = ClientApplication.authenticate(params[:client_id], params[:client_secret]) | |
raise ApiOAuthError.new(:access_denied, "invalid client_secret: #{params[:client_secret]}", nil, params[:state]) unless application | |
# grant type | |
grant_type = params[:grant_type] | |
case grant_type | |
when "authorization_code" then | |
code = params[:code] | |
raise ApiOAuthError.new(:invalid_grant, "missing code", nil, params[:state]) if code.blank? | |
access_grant = AccessGrant.authenticate(code, application.id) | |
raise ApiOAuthError.new(:invalid_grant, "invalid code: #{params[:code]}", nil, params[:state]) unless access_grant | |
when "credentials" then | |
AccessGrant.prune! | |
email = params[:email] | |
raise ApiOAuthError.new(:invalid_grant, "missing e-mail", nil, params[:state]) if email.blank? | |
password = params[:password] | |
raise ApiOAuthError.new(:invalid_grant, "missing password", nil, params[:state]) if password.blank? | |
user = User.where({email: email}).first | |
raise ApiOAuthError.new(:invalid_grant, "invalid e-mail or password", nil, params[:state]) if user.nil? or ! user.valid_password?(password) | |
access_grant = user.access_grants.create({:application => application}) | |
else | |
raise ApiOAuthError.new(:unsupported_grant_type, "unsupported grant type: #{params[:grant_type]}", nil, params[:state]) | |
end | |
access_grant.start_expiry_period! | |
token = | |
{ | |
:access_token => access_grant.access_token, | |
# :refresh_token => access_grant.refresh_token, | |
:expires_in => access_grant.access_token_expires_at | |
} | |
token[:state] = params[:state] unless params[:state].blank? | |
render :json => token | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment