Skip to content

Commit

Permalink
Merge pull request #1264 from fotos/tokens-controller-authorization-h…
Browse files Browse the repository at this point in the history
…ooks

Add #{before,after}_successful_authorization hooks in Doorkeeper::TokensController
  • Loading branch information
nbulaj committed Jun 6, 2019
2 parents adea1d2 + aa2e7ce commit b21370d
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 31 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,7 @@ User-visible changes worth mentioning.
## master

- [#PR ID] Add your description here.
- [#1264] Add :before_successful_authorization and :after_successful_authorization hooks in TokensController
- [#1263]: Response properly when introspection fails and fix configurations's user guide.

## 5.2.0.rc1
Expand Down
15 changes: 14 additions & 1 deletion app/controllers/doorkeeper/tokens_controller.rb
Expand Up @@ -88,7 +88,20 @@ def strategy
end

def authorize_response
@authorize_response ||= strategy.authorize
@authorize_response ||= begin
before_successful_authorization
auth = strategy.authorize
after_successful_authorization unless auth.is_a?(Doorkeeper::OAuth::ErrorResponse)
auth
end
end

def after_successful_authorization
Doorkeeper.configuration.after_successful_authorization.call(self)
end

def before_successful_authorization
Doorkeeper.configuration.before_successful_authorization.call(self)
end

def revocation_error_response
Expand Down
154 changes: 124 additions & 30 deletions spec/controllers/tokens_controller_spec.rb
Expand Up @@ -3,31 +3,139 @@
require "spec_helper"

describe Doorkeeper::TokensController do
describe "when authorization has succeeded" do
let(:token) { double(:token, authorize: true) }
let(:client) { FactoryBot.create :application }
let!(:user) { User.create!(name: "Joe", password: "sekret") }

it "returns the authorization" do
skip "verify need of these specs"
before do
Doorkeeper.configure do
resource_owner_from_credentials do
User.first
end
end

expect(token).to receive(:authorization)
allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(["password"])
end

post :create
subject { JSON.parse(response.body) }

describe "POST #create" do
before do
post :create, params: {
client_id: client.uid,
client_secret: client.secret,
grant_type: "password",
}
end

it "responds after authorization" do
expect(response).to be_successful
end

it "includes access token in response" do
expect(subject["access_token"]).to eq(Doorkeeper::AccessToken.first.token)
end

it "includes token type in response" do
expect(subject["token_type"]).to eq("Bearer")
end

it "includes token expiration in response" do
expect(subject["expires_in"].to_i).to eq(Doorkeeper.configuration.access_token_expires_in)
end

it "issues the token for the current client" do
expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
end

it "issues the token for the current resource owner" do
expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
end
end

describe "when authorization has failed" do
it "returns the error response" do
token = double(:token, authorize: false)
allow(controller).to receive(:token) { token }
describe "POST #create with errors" do
before do
post :create, params: {
client_id: client.uid,
client_secret: "invalid",
grant_type: "password",
}
end

post :create
it "responds after authorization" do
expect(response).to be_unauthorized
end

expect(response.status).to eq 400
expect(response.headers["WWW-Authenticate"]).to match(/Bearer/)
it "include error in response" do
expect(subject["error"]).to eq("invalid_client")
end

it "include error_description in response" do
expect(subject["error_description"]).to be
end

it "does not include access token in response" do
expect(subject["access_token"]).to be_nil
end

it "does not include token type in response" do
expect(subject["token_type"]).to be_nil
end

it "does not include token expiration in response" do
expect(subject["expires_in"]).to be_nil
end

it "does not issue any access token" do
expect(Doorkeeper::AccessToken.all).to be_empty
end
end

describe "POST #create with callbacks" do
after do
client.update_attribute :redirect_uri, "urn:ietf:wg:oauth:2.0:oob"
end

describe "when successful" do
after do
post :create, params: {
client_id: client.uid,
client_secret: client.secret,
grant_type: "password",
}
end

it "should call :before_successful_authorization callback" do
expect(Doorkeeper.configuration)
.to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
end

it "should call :after_successful_authorization callback" do
expect(Doorkeeper.configuration)
.to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
end
end

describe "with errors" do
after do
post :create, params: {
client_id: client.uid,
client_secret: "invalid",
grant_type: "password",
}
end

it "should call :before_successful_authorization callback" do
expect(Doorkeeper.configuration)
.to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
end

it "should not call :after_successful_authorization callback" do
expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
end
end
end

describe "when there is a failure due to a custom error" do
describe "POST #create with custom error" do
it "returns the error response with a custom message" do
# I18n looks for `doorkeeper.errors.messages.custom_message` in locale files
custom_message = "my_message"
Expand Down Expand Up @@ -58,7 +166,7 @@
end

# http://tools.ietf.org/html/rfc7009#section-2.2
describe "revoking tokens" do
describe "POST #revoke" do
let(:client) { FactoryBot.create(:application) }
let(:access_token) { FactoryBot.create(:access_token, application: client) }

Expand Down Expand Up @@ -117,21 +225,7 @@
end
end

describe "authorize response memoization" do
it "memoizes the result of the authorization" do
strategy = double(:strategy, authorize: true)
expect(strategy).to receive(:authorize).once
allow(controller).to receive(:strategy) { strategy }
allow(controller).to receive(:create) do
2.times { controller.send :authorize_response }
controller.render json: {}, status: :ok
end

post :create
end
end

describe "when requested token introspection" do
describe "POST #introspect" do
let(:client) { FactoryBot.create(:application) }
let(:access_token) { FactoryBot.create(:access_token, application: client) }
let(:token_for_introspection) { FactoryBot.create(:access_token, application: client) }
Expand Down

0 comments on commit b21370d

Please sign in to comment.