Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #947: Allow blank redirect URI for URI-less grant flows #1237

Merged
merged 1 commit into from Apr 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Expand Up @@ -7,6 +7,7 @@ User-visible changes worth mentioning.

## master

- [#1237] Allow to set blank redirect URI if Doorkeeper configured to use redirect URI-less grant flows.
- [#1234] Fix `StaleRecordsCleaner` to properly work with big amount of records.
- [#1228] Allow to explicitly set non-expiring tokens in `custom_access_token_expires_in` configuration
option using `Float::INIFINITY` return value.
Expand Down
2 changes: 2 additions & 0 deletions app/validators/redirect_uri_validator.rb
Expand Up @@ -8,6 +8,8 @@ def self.native_redirect_uri
end

def validate_each(record, attribute, value)
return if Doorkeeper.configuration.allow_blank_redirect_uri?

if value.blank?
record.errors.add(attribute, :blank)
else
Expand Down
6 changes: 6 additions & 0 deletions app/views/doorkeeper/applications/_form.html.erb
Expand Up @@ -25,6 +25,12 @@
<%= raw t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code, class: 'bg-light') { Doorkeeper.configuration.native_redirect_uri }) %>
</span>
<% end %>

<% if Doorkeeper.configuration.allow_blank_redirect_uri? %>
<span class="form-text text-secondary">
<%= t('doorkeeper.applications.help.blank_redirect_uri') %>
</span>
<% end %>
</div>
</div>

Expand Down
1 change: 1 addition & 0 deletions config/locales/en.yml
Expand Up @@ -32,6 +32,7 @@ en:
help:
confidential: 'Application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.'
redirect_uri: 'Use one line per URI'
blank_redirect_uri: "Leave it blank if you configured your provider to use Client Credentials, Resource Owner Password Credentials or any other grant type that doesn't require redirect URI."
native_redirect_uri: 'Use %{native_redirect_uri} if you want to add localhost URIs for development purposes'
scopes: 'Separate scopes with spaces. Leave blank to use the default scopes.'
edit:
Expand Down
5 changes: 5 additions & 0 deletions lib/doorkeeper/config.rb
Expand Up @@ -405,6 +405,11 @@ def token_grant_types
@token_grant_types ||= calculate_token_grant_types.freeze
end

def allow_blank_redirect_uri?
grant_flows.exclude?("authorization_code") &&
grant_flows.exclude?("implicit")
end

def option_defined?(name)
!instance_variable_get("@#{name}").nil?
end
Expand Down
3 changes: 3 additions & 0 deletions lib/generators/doorkeeper/application_owner_generator.rb
Expand Up @@ -4,6 +4,9 @@
require "rails/generators/active_record"

module Doorkeeper
# Generates migration to add reference to owner of the
# Doorkeeper application.
#
class ApplicationOwnerGenerator < ::Rails::Generators::Base
include ::Rails::Generators::Migration
source_root File.expand_path("templates", __dir__)
Expand Down
Expand Up @@ -4,6 +4,9 @@
require "rails/generators/active_record"

module Doorkeeper
# Generates migration to add confidential column to Doorkeeper
# applications table.
#
class ConfidentialApplicationsGenerator < ::Rails::Generators::Base
include ::Rails::Generators::Migration
source_root File.expand_path("templates", __dir__)
Expand Down
2 changes: 2 additions & 0 deletions lib/generators/doorkeeper/install_generator.rb
Expand Up @@ -4,6 +4,8 @@
require "rails/generators/active_record"

module Doorkeeper
# Setup doorkeeper into Rails application: locales, routes, etc.
#
class InstallGenerator < ::Rails::Generators::Base
include ::Rails::Generators::Migration
source_root File.expand_path("templates", __dir__)
Expand Down
2 changes: 2 additions & 0 deletions lib/generators/doorkeeper/migration_generator.rb
Expand Up @@ -4,6 +4,8 @@
require "rails/generators/active_record"

module Doorkeeper
# Copies main Doorkeeper migration into parent Rails application.
#
class MigrationGenerator < ::Rails::Generators::Base
include ::Rails::Generators::Migration
source_root File.expand_path("templates", __dir__)
Expand Down
3 changes: 3 additions & 0 deletions lib/generators/doorkeeper/pkce_generator.rb
Expand Up @@ -4,6 +4,9 @@
require "rails/generators/active_record"

module Doorkeeper
# Generates migration with PKCE required database columns for
# Doorkeeper tables.
#
class PkceGenerator < ::Rails::Generators::Base
include ::Rails::Generators::Migration
source_root File.expand_path("templates", __dir__)
Expand Down
3 changes: 3 additions & 0 deletions lib/generators/doorkeeper/previous_refresh_token_generator.rb
Expand Up @@ -4,6 +4,9 @@
require "rails/generators/active_record"

module Doorkeeper
# Generates migration to add previous refresh token column to the
# database for Doorkeeper tables.
#
class PreviousRefreshTokenGenerator < ::Rails::Generators::Base
include ::Rails::Generators::Migration
source_root File.expand_path("templates", __dir__)
Expand Down
4 changes: 4 additions & 0 deletions lib/generators/doorkeeper/templates/migration.rb.erb
Expand Up @@ -4,6 +4,10 @@ class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
t.string :name, null: false
t.string :uid, null: false
t.string :secret, null: false

# Remove `null: false` if you are planning to use grant flows
# that doesn't require redirect URI to be used during authorization
# like Client Credentials flow or Resource Owner Password.
t.text :redirect_uri, null: false
t.string :scopes, null: false, default: ''
t.boolean :confidential, null: false, default: true
Expand Down
2 changes: 2 additions & 0 deletions lib/generators/doorkeeper/views_generator.rb
Expand Up @@ -2,6 +2,8 @@

module Doorkeeper
module Generators
# Generates doorkeeper views for Rails application
#
class ViewsGenerator < ::Rails::Generators::Base
source_root File.expand_path("../../../app/views", __dir__)

Expand Down
2 changes: 1 addition & 1 deletion spec/dummy/db/schema.rb
Expand Up @@ -47,7 +47,7 @@
t.string "name", null: false
t.string "uid", null: false
t.string "secret", null: false
t.text "redirect_uri", null: false
t.text "redirect_uri"
t.string "scopes", default: "", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
Expand Down
2 changes: 0 additions & 2 deletions spec/lib/oauth/password_access_token_request_spec.rb
Expand Up @@ -157,8 +157,6 @@ module Doorkeeper::OAuth
222
elsif context.scopes.exists?("magic")
Float::INFINITY
else
nil
end
}
)
Expand Down
32 changes: 28 additions & 4 deletions spec/models/doorkeeper/application_spec.rb
Expand Up @@ -82,10 +82,34 @@ module Doorkeeper
expect(new_application).not_to be_valid
end

it "is invalid without redirect_uri" do
new_application.save
new_application.redirect_uri = nil
expect(new_application).not_to be_valid
context "redirect URI" do
context "when grant flows allow blank redirect URI" do
before do
Doorkeeper.configure do
grant_flows %w[password client_credentials]
end
end

it "is valid without redirect_uri" do
new_application.save
new_application.redirect_uri = nil
expect(new_application).to be_valid
end
end

context "when grant flows require redirect URI" do
before do
Doorkeeper.configure do
grant_flows %w[password client_credentials authorization_code]
end
end

it "is invalid without redirect_uri" do
new_application.save
new_application.redirect_uri = nil
expect(new_application).not_to be_valid
end
end
end

it "checks uniqueness of uid" do
Expand Down
30 changes: 30 additions & 0 deletions spec/requests/applications/applications_request_spec.rb
Expand Up @@ -94,6 +94,36 @@
true
)
end

context "redirect URI" do
scenario "adding app with blank redirect URI when configured flows requires redirect uri" do
config_is_set("grant_flows", %w[authorization_code implicit client_credentials])

fill_in "doorkeeper_application[name]", with: "My Application"
fill_in "doorkeeper_application[redirect_uri]",
with: ""

click_button "Submit"
i_should_see "Whoops! Check your form for possible errors"
end

scenario "adding app with blank redirect URI when configured flows without redirect uri" do
config_is_set("grant_flows", %w[client_credentials password])

# Visit it once again to consider grant flows
visit "/oauth/applications/new"

i_should_see I18n.t("doorkeeper.applications.help.blank_redirect_uri")

fill_in "doorkeeper_application[name]", with: "My Application"
fill_in "doorkeeper_application[redirect_uri]",
with: ""

click_button "Submit"
i_should_see "Application created"
i_should_see "My Application"
end
end
end
end

Expand Down
2 changes: 1 addition & 1 deletion spec/requests/flows/password_spec.rb
Expand Up @@ -18,7 +18,7 @@
end

describe "Resource Owner Password Credentials Flow" do
let(:client_attributes) { {} }
let(:client_attributes) { { redirect_uri: nil } }

before do
config_is_set(:grant_flows, ["password"])
Expand Down