diff --git a/config/locales/en.yml b/config/locales/en.yml index 10ecc09..e7cfbcb 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2,6 +2,9 @@ en: doorkeeper: scopes: openid: 'Authenticate your account' + errors: + messages: + login_required: 'The authorization server requires end-user authentication' openid_connect: errors: messages: diff --git a/lib/doorkeeper/openid_connect.rb b/lib/doorkeeper/openid_connect.rb index b36dc54..2d90ede 100644 --- a/lib/doorkeeper/openid_connect.rb +++ b/lib/doorkeeper/openid_connect.rb @@ -1,6 +1,8 @@ require 'doorkeeper/openid_connect/version' require 'doorkeeper/openid_connect/engine' +require 'doorkeeper/openid_connect/helpers/controller' + require 'doorkeeper/openid_connect/models/id_token' require 'doorkeeper/openid_connect/models/user_info' require 'doorkeeper/openid_connect/models/claims/claim' @@ -15,10 +17,6 @@ require 'json/jwt' module Doorkeeper - class << self - prepend OpenidConnect::DoorkeeperConfiguration - end - module OpenidConnect # TODO: make this configurable SIGNING_ALGORITHM = 'RS256' @@ -37,6 +35,16 @@ def self.signing_key end end +module Doorkeeper + class << self + prepend ::Doorkeeper::OpenidConnect::DoorkeeperConfiguration + end + + module Helpers::Controller + prepend ::Doorkeeper::OpenidConnect::Helpers::Controller + end +end + module Doorkeeper module OAuth class PasswordAccessTokenRequest diff --git a/lib/doorkeeper/openid_connect/helpers/controller.rb b/lib/doorkeeper/openid_connect/helpers/controller.rb new file mode 100644 index 0000000..f6b3938 --- /dev/null +++ b/lib/doorkeeper/openid_connect/helpers/controller.rb @@ -0,0 +1,30 @@ +module Doorkeeper + module OpenidConnect + module Helpers + module Controller + private + + def authenticate_resource_owner! + owner = super + + if prompt_values.include?('none') && (!owner || owner.is_a?(String)) + # clear the previous response body to avoid a DoubleRenderError + # TODO: this is currently broken on Rails 5, see + # https://github.com/rails/rails/issues/25106 + self.response_body = nil + + error = ::Doorkeeper::OAuth::ErrorResponse.new(name: :login_required) + response.headers.merge!(error.headers) + render json: error.body, status: error.status + else + owner + end + end + + def prompt_values + @prompt_values ||= params[:prompt].to_s.split(/ +/) + end + end + end + end +end diff --git a/spec/controllers/doorkeeper/authorizations_controller.rb b/spec/controllers/doorkeeper/authorizations_controller.rb new file mode 100644 index 0000000..8c2a6ef --- /dev/null +++ b/spec/controllers/doorkeeper/authorizations_controller.rb @@ -0,0 +1,37 @@ +require 'rails_helper' + +describe Doorkeeper::AuthorizationsController, type: :controller do + describe '#new' do + context 'without a prompt parameter' do + it 'renders the authorization form if logged in' do + get :new, current_user: 'Joe' + + expect(response).to be_successful + end + + it 'redirects to login form when not logged in' do + get :new + + expect(response).to redirect_to '/login' + end + end + + context 'with a prompt=none parameter' do + it 'renders the authorization form if logged in' do + get :new, current_user: 'Joe', prompt: 'none' + + expect(response).to be_successful + end + + it 'returns an error when not logged in' do + get :new, prompt: 'none' + + expect(response.status).to eq 401 + expect(JSON.parse(response.body)).to eq({ + 'error' => 'login_required', + 'error_description' => 'The authorization server requires end-user authentication' + }) + end + end + end +end diff --git a/spec/dummy/config/initializers/doorkeeper.rb b/spec/dummy/config/initializers/doorkeeper.rb index 2ef5dca..2286587 100644 --- a/spec/dummy/config/initializers/doorkeeper.rb +++ b/spec/dummy/config/initializers/doorkeeper.rb @@ -1,2 +1,9 @@ Doorkeeper.configure do + resource_owner_authenticator do + if params[:current_user] + User.new name: params[:current_user] + else + redirect_to('/login') + end + end end