Drop support for OAuth 1

This commit is contained in:
Tom Hughes 2024-07-24 19:12:14 +01:00 committed by Anton Khorev
parent cee9818dfc
commit 17bc0853a0
48 changed files with 52 additions and 2395 deletions

View file

@ -59,7 +59,6 @@ gem "dry-validation"
gem "frozen_record" gem "frozen_record"
gem "http_accept_language", "~> 2.1.1" gem "http_accept_language", "~> 2.1.1"
gem "i18n-js", "~> 3.9.2" gem "i18n-js", "~> 3.9.2"
gem "oauth-plugin", ">= 0.5.1"
gem "openstreetmap-deadlock_retry", ">= 1.3.1", :require => "deadlock_retry" gem "openstreetmap-deadlock_retry", ">= 1.3.1", :require => "deadlock_retry"
gem "rack-cors" gem "rack-cors"
gem "rails-i18n", "~> 7.0.0" gem "rails-i18n", "~> 7.0.0"
@ -76,6 +75,7 @@ gem "addressable", "~> 2.8"
gem "rack-uri_sanitizer" gem "rack-uri_sanitizer"
# Omniauth for authentication # Omniauth for authentication
gem "multi_json"
gem "omniauth", "~> 2.0.2" gem "omniauth", "~> 2.0.2"
gem "omniauth-facebook" gem "omniauth-facebook"
gem "omniauth-github" gem "omniauth-github"

View file

@ -362,11 +362,6 @@ GEM
mini_portile2 (~> 2.8.2) mini_portile2 (~> 2.8.2)
racc (~> 1.4) racc (~> 1.4)
oauth (0.4.7) oauth (0.4.7)
oauth-plugin (0.5.1)
multi_json
oauth (~> 0.4.4)
oauth2 (>= 0.5.0)
rack
oauth2 (2.0.9) oauth2 (2.0.9)
faraday (>= 0.17.3, < 3.0) faraday (>= 0.17.3, < 3.0)
jwt (>= 1.0, < 3.0) jwt (>= 1.0, < 3.0)
@ -672,8 +667,8 @@ DEPENDENCIES
mini_racer (~> 0.9.0) mini_racer (~> 0.9.0)
minitest (~> 5.1) minitest (~> 5.1)
minitest-focus minitest-focus
multi_json
multi_xml (~> 0.6.0) multi_xml (~> 0.6.0)
oauth-plugin (>= 0.5.1)
omniauth (~> 2.0.2) omniauth (~> 2.0.2)
omniauth-facebook omniauth-facebook
omniauth-github omniauth-github

View file

@ -12,7 +12,6 @@ class Ability
can [:index, :permalink, :edit, :help, :fixthemap, :offline, :export, :about, :communities, :preview, :copyright, :key, :id], :site can [:index, :permalink, :edit, :help, :fixthemap, :offline, :export, :about, :communities, :preview, :copyright, :key, :id], :site
can [:finish, :embed], :export can [:finish, :embed], :export
can [:search, :search_latlon, :search_osm_nominatim, :search_osm_nominatim_reverse], :geocoder can [:search, :search_latlon, :search_osm_nominatim, :search_osm_nominatim_reverse], :geocoder
can [:token, :request_token, :access_token, :test_request], :oauth
if Settings.status != "database_offline" if Settings.status != "database_offline"
can [:index, :feed, :show], Changeset can [:index, :feed, :show], Changeset
@ -31,12 +30,10 @@ class Ability
if user&.active? if user&.active?
can :welcome, :site can :welcome, :site
can [:revoke, :authorize], :oauth
can [:show], :deletion can [:show], :deletion
if Settings.status != "database_offline" if Settings.status != "database_offline"
can [:subscribe, :unsubscribe], Changeset can [:subscribe, :unsubscribe], Changeset
can [:index, :new, :create, :show, :edit, :update, :destroy], ClientApplication
can [:index, :new, :create, :show, :edit, :update, :destroy], :oauth2_application can [:index, :new, :create, :show, :edit, :update, :destroy], :oauth2_application
can [:index, :destroy], :oauth2_authorized_application can [:index, :destroy], :oauth2_authorized_application
can [:new, :show, :create, :destroy], :oauth2_authorization can [:new, :show, :create, :destroy], :oauth2_authorization

View file

@ -16,8 +16,6 @@ class AccountsController < ApplicationController
allow_social_login :only => [:edit, :update] allow_social_login :only => [:edit, :update]
def edit def edit
@tokens = current_user.oauth_tokens.authorized
if errors = session.delete(:user_errors) if errors = session.delete(:user_errors)
errors.each do |attribute, error| errors.each do |attribute, error|
current_user.errors.add(attribute, error) current_user.errors.add(attribute, error)
@ -27,8 +25,6 @@ class AccountsController < ApplicationController
end end
def update def update
@tokens = current_user.oauth_tokens.authorized
user_params = params.require(:user).permit(:display_name, :new_email, :pass_crypt, :pass_crypt_confirmation, :auth_provider) user_params = params.require(:user).permit(:display_name, :new_email, :pass_crypt, :pass_crypt_confirmation, :auth_provider)
if params[:user][:auth_provider].blank? || if params[:user][:auth_provider].blank? ||

View file

@ -385,7 +385,7 @@ module Api
def add_comment(note, text, event, notify: true) def add_comment(note, text, event, notify: true)
attributes = { :visible => true, :event => event, :body => text } attributes = { :visible => true, :event => event, :body => text }
if doorkeeper_token || current_token if doorkeeper_token
author = current_user if scope_enabled?(:write_notes) author = current_user if scope_enabled?(:write_notes)
else else
author = current_user author = current_user

View file

@ -14,10 +14,8 @@ module Api
def show def show
@permissions = if doorkeeper_token.present? @permissions = if doorkeeper_token.present?
doorkeeper_token.scopes.map { |s| :"allow_#{s}" } doorkeeper_token.scopes.map { |s| :"allow_#{s}" }
elsif current_token.present?
ClientApplication.all_permissions.select { |p| current_token.read_attribute(p) }
elsif current_user elsif current_user
ClientApplication.all_permissions Oauth.scopes.map { |s| :"allow_#{s.name}" }
else else
[] []
end end

View file

@ -69,15 +69,13 @@ class ApiController < ApplicationController
# Use capabilities from the oauth token if it exists and is a valid access token # Use capabilities from the oauth token if it exists and is a valid access token
if doorkeeper_token&.accessible? if doorkeeper_token&.accessible?
ApiAbility.new(nil).merge(ApiCapability.new(doorkeeper_token)) ApiAbility.new(nil).merge(ApiCapability.new(doorkeeper_token))
elsif Authenticator.new(self, [:token]).allow?
ApiAbility.new(nil).merge(ApiCapability.new(current_token))
else else
ApiAbility.new(current_user) ApiAbility.new(current_user)
end end
end end
def deny_access(_exception) def deny_access(_exception)
if doorkeeper_token || current_token if doorkeeper_token
set_locale set_locale
report_error t("oauth.permissions.missing"), :forbidden report_error t("oauth.permissions.missing"), :forbidden
elsif current_user elsif current_user
@ -107,13 +105,6 @@ class ApiController < ApplicationController
# try and setup using OAuth # try and setup using OAuth
if doorkeeper_token&.accessible? if doorkeeper_token&.accessible?
self.current_user = User.find(doorkeeper_token.resource_owner_id) self.current_user = User.find(doorkeeper_token.resource_owner_id)
elsif Authenticator.new(self, [:token]).allow?
if Settings.oauth_10a_support
# self.current_user setup by OAuth
else
report_error t("application.oauth_10a_disabled", :link => t("application.auth_disabled_link")), :forbidden
self.current_user = nil
end
else else
username, passwd = auth_data # parse from headers username, passwd = auth_data # parse from headers
# authenticate per-scheme # authenticate per-scheme

View file

@ -86,10 +86,6 @@ class ApplicationController < ActionController::Base
@oauth_token = current_user.oauth_token(Settings.oauth_application) if current_user && Settings.key?(:oauth_application) @oauth_token = current_user.oauth_token(Settings.oauth_application) if current_user && Settings.key?(:oauth_application)
end end
def require_oauth_10a_support
report_error t("application.oauth_10a_disabled", :link => t("application.auth_disabled_link")), :forbidden unless Settings.oauth_10a_support
end
## ##
# require the user to have cookies enabled in their browser # require the user to have cookies enabled in their browser
def require_cookies def require_cookies
@ -297,7 +293,7 @@ class ApplicationController < ActionController::Base
end end
def deny_access(_exception) def deny_access(_exception)
if doorkeeper_token || current_token if doorkeeper_token
set_locale set_locale
report_error t("oauth.permissions.missing"), :forbidden report_error t("oauth.permissions.missing"), :forbidden
elsif current_user elsif current_user
@ -341,9 +337,6 @@ class ApplicationController < ActionController::Base
[user, pass] [user, pass]
end end
# override to stop oauth plugin sending errors
def invalid_oauth_response; end
# clean any referer parameter # clean any referer parameter
def safe_referer(referer) def safe_referer(referer)
begin begin
@ -366,7 +359,7 @@ class ApplicationController < ActionController::Base
end end
def scope_enabled?(scope) def scope_enabled?(scope)
doorkeeper_token&.includes_scope?(scope) || current_token&.includes_scope?(scope) doorkeeper_token&.includes_scope?(scope)
end end
helper_method :scope_enabled? helper_method :scope_enabled?

View file

@ -1,75 +0,0 @@
class OauthClientsController < ApplicationController
layout "site"
before_action :authorize_web
before_action :set_locale
authorize_resource :class => ClientApplication
def index
@client_applications = current_user.client_applications
@tokens = current_user.oauth_tokens.authorized
end
def show
@client_application = current_user.client_applications.find(params[:id])
rescue ActiveRecord::RecordNotFound
@type = "client application"
render :action => "not_found", :status => :not_found
end
def new
if Settings.oauth_10_registration
@client_application = ClientApplication.new
else
flash[:error] = t ".disabled"
redirect_to :action => "index"
end
end
def edit
@client_application = current_user.client_applications.find(params[:id])
rescue ActiveRecord::RecordNotFound
@type = "client application"
render :action => "not_found", :status => :not_found
end
def create
@client_application = current_user.client_applications.build(application_params)
if @client_application.save
flash[:notice] = t ".flash"
redirect_to :action => "show", :id => @client_application.id
else
render :action => "new"
end
end
def update
@client_application = current_user.client_applications.find(params[:id])
if @client_application.update(application_params)
flash[:notice] = t ".flash"
redirect_to :action => "show", :id => @client_application.id
else
render :action => "edit"
end
rescue ActiveRecord::RecordNotFound
@type = "client application"
render :action => "not_found", :status => :not_found
end
def destroy
@client_application = current_user.client_applications.find(params[:id])
@client_application.destroy
flash[:notice] = t ".flash"
redirect_to :action => "index"
rescue ActiveRecord::RecordNotFound
@type = "client application"
render :action => "not_found", :status => :not_found
end
private
def application_params
params.require(:client_application).permit(:name, :url, :callback_url, :support_url, ClientApplication.all_permissions)
end
end

View file

@ -1,80 +0,0 @@
class OauthController < ApplicationController
include OAuth::Controllers::ProviderController
# The ProviderController will call login_required for any action that needs
# a login, but we want to check authorization on every action.
authorize_resource :class => false
before_action :require_oauth_10a_support
layout "site"
allow_all_form_action :only => :oauth1_authorize
def revoke
@token = current_user.oauth_tokens.find_by :token => params[:token]
if @token
@token.invalidate!
flash[:notice] = t(".flash", :application => @token.client_application.name)
end
redirect_to oauth_clients_url(:display_name => @token.user.display_name)
end
protected
def login_required
authorize_web
set_locale
end
def user_authorizes_token?
any_auth = false
@token.client_application.permissions.each do |pref|
if params[pref].to_i.nonzero?
@token.write_attribute(pref, true)
any_auth ||= true
else
@token.write_attribute(pref, false)
end
end
any_auth
end
def oauth1_authorize
if @token.invalidated?
@message = t "oauth.authorize_failure.invalid"
render :action => "authorize_failure"
elsif request.post?
if user_authorizes_token?
@token.authorize!(current_user)
callback_url = if @token.oauth10?
params[:oauth_callback] || @token.client_application.callback_url
else
@token.oob? ? @token.client_application.callback_url : @token.callback_url
end
@redirect_url = URI.parse(callback_url) if callback_url.present?
if @redirect_url.to_s.blank?
render :action => "authorize_success"
else
@redirect_url.query = if @redirect_url.query.blank?
"oauth_token=#{@token.token}"
else
@redirect_url.query +
"&oauth_token=#{@token.token}"
end
@redirect_url.query += "&oauth_verifier=#{@token.verifier}" unless @token.oauth10?
redirect_to @redirect_url.to_s, :allow_other_host => true
end
else
@token.invalidate!
@message = t("oauth.authorize_failure.denied", :app_name => @token.client_application.name)
render :action => "authorize_failure"
end
end
end
end

View file

@ -1,57 +0,0 @@
# == Schema Information
#
# Table name: oauth_tokens
#
# id :integer not null, primary key
# user_id :integer
# type :string(20)
# client_application_id :integer
# token :string(50)
# secret :string(50)
# authorized_at :datetime
# invalidated_at :datetime
# created_at :datetime
# updated_at :datetime
# allow_read_prefs :boolean default(FALSE), not null
# allow_write_prefs :boolean default(FALSE), not null
# allow_write_diary :boolean default(FALSE), not null
# allow_write_api :boolean default(FALSE), not null
# allow_read_gpx :boolean default(FALSE), not null
# allow_write_gpx :boolean default(FALSE), not null
# callback_url :string
# verifier :string(20)
# scope :string
# valid_to :datetime
# allow_write_notes :boolean default(FALSE), not null
#
# Indexes
#
# index_oauth_tokens_on_token (token) UNIQUE
# index_oauth_tokens_on_user_id (user_id)
#
# Foreign Keys
#
# oauth_tokens_client_application_id_fkey (client_application_id => client_applications.id)
# oauth_tokens_user_id_fkey (user_id => users.id)
#
class AccessToken < OauthToken
belongs_to :user, :optional => true
belongs_to :client_application, :optional => true
scope :valid, -> { where(:invalidated_at => nil) }
validates :user, :secret, :presence => true
before_create :set_authorized_at
def includes_scope?(scope)
self[:"allow_#{scope}"]
end
protected
def set_authorized_at
self.authorized_at = Time.now.utc
end
end

View file

@ -1,109 +0,0 @@
# == Schema Information
#
# Table name: client_applications
#
# id :integer not null, primary key
# name :string
# url :string
# support_url :string
# callback_url :string
# key :string(50)
# secret :string(50)
# user_id :integer
# created_at :datetime
# updated_at :datetime
# allow_read_prefs :boolean default(FALSE), not null
# allow_write_prefs :boolean default(FALSE), not null
# allow_write_diary :boolean default(FALSE), not null
# allow_write_api :boolean default(FALSE), not null
# allow_read_gpx :boolean default(FALSE), not null
# allow_write_gpx :boolean default(FALSE), not null
# allow_write_notes :boolean default(FALSE), not null
#
# Indexes
#
# index_client_applications_on_key (key) UNIQUE
# index_client_applications_on_user_id (user_id)
#
# Foreign Keys
#
# client_applications_user_id_fkey (user_id => users.id)
#
class ClientApplication < ApplicationRecord
belongs_to :user, :optional => true
has_many :tokens, :class_name => "OauthToken", :dependent => :delete_all
has_many :access_tokens
has_many :oauth2_verifiers
has_many :oauth_tokens
validates :key, :presence => true, :uniqueness => true
validates :name, :url, :secret, :presence => true
validates :url, :format => /\A#{URI::DEFAULT_PARSER.make_regexp(%w[http https])}\z/
validates :support_url, :allow_blank => true, :format => /\A#{URI::DEFAULT_PARSER.make_regexp(%w[http https])}\z/
validates :callback_url, :allow_blank => true, :format => /\A#{URI::DEFAULT_PARSER.make_regexp}\z/
before_validation :generate_keys, :on => :create
attr_accessor :token_callback_url
def self.find_token(token_key)
token = OauthToken.includes(:client_application).find_by(:token => token_key)
token if token&.authorized?
end
def self.verify_request(request, options = {}, &block)
signature = OAuth::Signature.build(request, options, &block)
return false unless OauthNonce.remember(signature.request.nonce, signature.request.timestamp)
signature.verify
rescue OAuth::Signature::UnknownSignatureMethod
false
end
def self.all_permissions
Oauth.scopes.collect { |s| :"allow_#{s.name}" }
end
def oauth_server
@oauth_server ||= OAuth::Server.new("https://#{Settings.server_url}")
end
def credentials
@credentials ||= OAuth::Consumer.new(key, secret)
end
def create_request_token(_params = {})
params = { :client_application => self, :callback_url => token_callback_url }
permissions.each do |p|
params[p] = true
end
RequestToken.create(params)
end
def access_token_for_user(user)
unless token = access_tokens.valid.find_by(:user_id => user)
params = { :user => user }
permissions.each do |p|
params[p] = true
end
token = access_tokens.create(params)
end
token
end
# the permissions that this client would like from the user
def permissions
ClientApplication.all_permissions.select { |p| self[p] }
end
protected
def generate_keys
self.key = OAuth::Helper.generate_key(40)[0, 40]
self.secret = OAuth::Helper.generate_key(40)[0, 40]
end
end

View file

@ -1,58 +0,0 @@
# == Schema Information
#
# Table name: oauth_tokens
#
# id :integer not null, primary key
# user_id :integer
# type :string(20)
# client_application_id :integer
# token :string(50)
# secret :string(50)
# authorized_at :datetime
# invalidated_at :datetime
# created_at :datetime
# updated_at :datetime
# allow_read_prefs :boolean default(FALSE), not null
# allow_write_prefs :boolean default(FALSE), not null
# allow_write_diary :boolean default(FALSE), not null
# allow_write_api :boolean default(FALSE), not null
# allow_read_gpx :boolean default(FALSE), not null
# allow_write_gpx :boolean default(FALSE), not null
# callback_url :string
# verifier :string(20)
# scope :string
# valid_to :datetime
# allow_write_notes :boolean default(FALSE), not null
#
# Indexes
#
# index_oauth_tokens_on_token (token) UNIQUE
# index_oauth_tokens_on_user_id (user_id)
#
# Foreign Keys
#
# oauth_tokens_client_application_id_fkey (client_application_id => client_applications.id)
# oauth_tokens_user_id_fkey (user_id => users.id)
#
class Oauth2Token < AccessToken
attr_accessor :state
def as_json(_options = {})
d = { :access_token => token, :token_type => "bearer" }
d[:expires_in] = expires_in if expires_at
d
end
def to_query
q = "access_token=#{token}&token_type=bearer"
q << "&state=#{CGI.escape(state)}" if @state
q << "&expires_in=#{expires_in}" if expires_at
q << "&scope=#{CGI.escape(scope)}" if scope
q
end
def expires_in
expires_at.to_i - Time.now.to_i
end
end

View file

@ -1,72 +0,0 @@
# == Schema Information
#
# Table name: oauth_tokens
#
# id :integer not null, primary key
# user_id :integer
# type :string(20)
# client_application_id :integer
# token :string(50)
# secret :string(50)
# authorized_at :datetime
# invalidated_at :datetime
# created_at :datetime
# updated_at :datetime
# allow_read_prefs :boolean default(FALSE), not null
# allow_write_prefs :boolean default(FALSE), not null
# allow_write_diary :boolean default(FALSE), not null
# allow_write_api :boolean default(FALSE), not null
# allow_read_gpx :boolean default(FALSE), not null
# allow_write_gpx :boolean default(FALSE), not null
# callback_url :string
# verifier :string(20)
# scope :string
# valid_to :datetime
# allow_write_notes :boolean default(FALSE), not null
#
# Indexes
#
# index_oauth_tokens_on_token (token) UNIQUE
# index_oauth_tokens_on_user_id (user_id)
#
# Foreign Keys
#
# oauth_tokens_client_application_id_fkey (client_application_id => client_applications.id)
# oauth_tokens_user_id_fkey (user_id => users.id)
#
class Oauth2Verifier < OauthToken
validates :user, :presence => true, :associated => true
attr_accessor :state
def exchange!(_params = {})
OauthToken.transaction do
token = Oauth2Token.create! :user => user, :client_application => client_application, :scope => scope
invalidate!
token
end
end
def code
token
end
def redirect_url
callback_url
end
def to_query
q = "code=#{token}"
q << "&state=#{CGI.escape(state)}" if @state
q
end
protected
def generate_keys
self.token = OAuth::Helper.generate_key(20)[0, 20]
self.expires_at = 10.minutes.from_now
self.authorized_at = Time.now.utc
end
end

View file

@ -1,31 +0,0 @@
# == Schema Information
#
# Table name: oauth_nonces
#
# id :bigint(8) not null, primary key
# nonce :string
# timestamp :integer
# created_at :datetime
# updated_at :datetime
#
# Indexes
#
# index_oauth_nonces_on_nonce_and_timestamp (nonce,timestamp) UNIQUE
#
# Simple store of nonces. The OAuth Spec requires that any given pair of nonce and timestamps are unique.
# Thus you can use the same nonce with a different timestamp and viceversa.
class OauthNonce < ApplicationRecord
validates :timestamp, :presence => true
validates :nonce, :presence => true, :uniqueness => { :scope => :timestamp }
# Remembers a nonce and it's associated timestamp. It returns false if it has already been used
def self.remember(nonce, timestamp)
return false if Time.now.to_i - timestamp.to_i > 86400
oauth_nonce = OauthNonce.create(:nonce => nonce, :timestamp => timestamp.to_i)
return false if oauth_nonce.new_record?
oauth_nonce
end
end

View file

@ -1,72 +0,0 @@
# == Schema Information
#
# Table name: oauth_tokens
#
# id :integer not null, primary key
# user_id :integer
# type :string(20)
# client_application_id :integer
# token :string(50)
# secret :string(50)
# authorized_at :datetime
# invalidated_at :datetime
# created_at :datetime
# updated_at :datetime
# allow_read_prefs :boolean default(FALSE), not null
# allow_write_prefs :boolean default(FALSE), not null
# allow_write_diary :boolean default(FALSE), not null
# allow_write_api :boolean default(FALSE), not null
# allow_read_gpx :boolean default(FALSE), not null
# allow_write_gpx :boolean default(FALSE), not null
# callback_url :string
# verifier :string(20)
# scope :string
# valid_to :datetime
# allow_write_notes :boolean default(FALSE), not null
#
# Indexes
#
# index_oauth_tokens_on_token (token) UNIQUE
# index_oauth_tokens_on_user_id (user_id)
#
# Foreign Keys
#
# oauth_tokens_client_application_id_fkey (client_application_id => client_applications.id)
# oauth_tokens_user_id_fkey (user_id => users.id)
#
class OauthToken < ApplicationRecord
belongs_to :client_application, :optional => true
belongs_to :user, :optional => true
scope :authorized, -> { where("authorized_at IS NOT NULL and invalidated_at IS NULL") }
validates :token, :presence => true, :uniqueness => true
validates :user, :associated => true
validates :client_application, :presence => true
before_validation :generate_keys, :on => :create
def invalidated?
invalidated_at != nil
end
def invalidate!
update(:invalidated_at => Time.now.utc)
end
def authorized?
!authorized_at.nil? && !invalidated?
end
def to_query
"oauth_token=#{token}&oauth_token_secret=#{secret}"
end
protected
def generate_keys
self.token = OAuth::Helper.generate_key(40)[0, 40]
self.secret = OAuth::Helper.generate_key(40)[0, 40]
end
end

View file

@ -1,82 +0,0 @@
# == Schema Information
#
# Table name: oauth_tokens
#
# id :integer not null, primary key
# user_id :integer
# type :string(20)
# client_application_id :integer
# token :string(50)
# secret :string(50)
# authorized_at :datetime
# invalidated_at :datetime
# created_at :datetime
# updated_at :datetime
# allow_read_prefs :boolean default(FALSE), not null
# allow_write_prefs :boolean default(FALSE), not null
# allow_write_diary :boolean default(FALSE), not null
# allow_write_api :boolean default(FALSE), not null
# allow_read_gpx :boolean default(FALSE), not null
# allow_write_gpx :boolean default(FALSE), not null
# callback_url :string
# verifier :string(20)
# scope :string
# valid_to :datetime
# allow_write_notes :boolean default(FALSE), not null
#
# Indexes
#
# index_oauth_tokens_on_token (token) UNIQUE
# index_oauth_tokens_on_user_id (user_id)
#
# Foreign Keys
#
# oauth_tokens_client_application_id_fkey (client_application_id => client_applications.id)
# oauth_tokens_user_id_fkey (user_id => users.id)
#
class RequestToken < OauthToken
attr_accessor :provided_oauth_verifier
def authorize!(user)
return false if authorized?
self.user = user
self.authorized_at = Time.now.utc
self.verifier = OAuth::Helper.generate_key(20)[0, 20] unless oauth10?
save
end
def exchange!
return false unless authorized?
return false unless oauth10? || verifier == provided_oauth_verifier
RequestToken.transaction do
params = { :user => user, :client_application => client_application }
# copy the permissions from the authorised request token to the access token
client_application.permissions.each do |p|
params[p] = self[p]
end
access_token = AccessToken.create(params)
invalidate!
access_token
end
end
def to_query
if oauth10?
super
else
"#{super}&oauth_callback_confirmed=true"
end
end
def oob?
callback_url.nil? || callback_url.casecmp?("oob")
end
def oauth10?
Settings.key?(:oauth_10_support) && Settings.oauth_10_support && callback_url.blank?
end
end

View file

@ -66,9 +66,6 @@ class User < ApplicationRecord
has_many :note_comments, :foreign_key => :author_id, :inverse_of => :author has_many :note_comments, :foreign_key => :author_id, :inverse_of => :author
has_many :notes, :through => :note_comments has_many :notes, :through => :note_comments
has_many :client_applications
has_many :oauth_tokens, -> { order(:authorized_at => :desc).preload(:client_application) }, :class_name => "OauthToken", :inverse_of => :user
has_many :oauth2_applications, :class_name => Doorkeeper.config.application_model.name, :as => :owner has_many :oauth2_applications, :class_name => Doorkeeper.config.application_model.name, :as => :owner
has_many :access_grants, :class_name => Doorkeeper.config.access_grant_model.name, :foreign_key => :resource_owner_id has_many :access_grants, :class_name => Doorkeeper.config.access_grant_model.name, :foreign_key => :resource_owner_id
has_many :access_tokens, :class_name => Doorkeeper.config.access_token_model.name, :foreign_key => :resource_owner_id has_many :access_tokens, :class_name => Doorkeeper.config.access_token_model.name, :foreign_key => :resource_owner_id
@ -332,7 +329,6 @@ class User < ApplicationRecord
## ##
# revoke any authentication tokens # revoke any authentication tokens
def revoke_authentication_tokens def revoke_authentication_tokens
oauth_tokens.authorized.each(&:invalidate!)
access_tokens.not_expired.each(&:revoke) access_tokens.not_expired.each(&:revoke)
end end
@ -377,12 +373,6 @@ class User < ApplicationRecord
suspend! if may_suspend? && spam_score > Settings.spam_threshold suspend! if may_suspend? && spam_score > Settings.spam_threshold
end end
##
# return an oauth 1 access token for a specified application
def access_token(application_key)
ClientApplication.find_by(:key => application_key).access_token_for_user(self)
end
## ##
# return an oauth 2 access token for a specified application # return an oauth 2 access token for a specified application
def oauth_token(application_id) def oauth_token(application_id)

View file

@ -5,9 +5,6 @@
<li class="nav-item"> <li class="nav-item">
<%= link_to t(".account_settings"), edit_account_path, :class => "nav-link #{'active' if %w[accounts deletions].include?(controller_name)}" %> <%= link_to t(".account_settings"), edit_account_path, :class => "nav-link #{'active' if %w[accounts deletions].include?(controller_name)}" %>
</li> </li>
<li class="nav-item">
<%= link_to t(".oauth1_settings"), oauth_clients_path(current_user), :class => "nav-link #{'active' if controller_name == 'oauth_clients'}" %>
</li>
<li class="nav-item"> <li class="nav-item">
<%= link_to t(".oauth2_applications"), oauth_applications_path, :class => "nav-link #{'active' if controller_name == 'oauth2_applications'}" %> <%= link_to t(".oauth2_applications"), oauth_applications_path, :class => "nav-link #{'active' if controller_name == 'oauth2_applications'}" %>
</li> </li>

View file

@ -1,18 +0,0 @@
<% content_for :heading do %>
<h1><%= t ".title" %></h1>
<% end %>
<p><%= t(".request_access_html", :app_name => link_to(@token.client_application.name, @token.client_application.url), :user => link_to(current_user.display_name, current_user)) %></p>
<%= bootstrap_form_tag do |f| %>
<%= f.hidden_field :oauth_token, :value => @token.token %>
<% if params[:oauth_callback] -%>
<%= f.hidden_field :oauth_callback, :value => params[:oauth_callback] %>
<% end -%>
<%= f.form_group :permissions, :label => { :text => t(".allow_to") } do %>
<% @token.client_application.permissions.each do |perm| -%>
<%= f.check_box perm, :value => "yes", :checked => @token.read_attribute(perm), :label => t(".#{perm}") %>
<% end -%>
<% end -%>
<%= f.primary t(".grant_access") %>
<% end %>

View file

@ -1,5 +0,0 @@
<% content_for :heading do %>
<h1><%= t ".title" %></h1>
<% end %>
<p><%= @message %></p>

View file

@ -1,9 +0,0 @@
<% content_for :heading do %>
<h1><%= t ".title" %></h1>
<% end %>
<p><%= t(".allowed_html", :app_name => link_to(@token.client_application.name, @token.client_application.url)) %></p>
<% if @token.oob? and not @token.oauth10? %>
<p><%= t ".verification", :code => @token.verifier %></p>
<% end %>

View file

@ -1,11 +0,0 @@
<%= f.text_field :name %>
<%= f.text_field :url %>
<%= f.text_field :callback_url %>
<%= f.text_field :support_url %>
<div class='mb-3'>
<p><%= t ".requests" %></p>
<% ClientApplication.all_permissions.each do |perm| %>
<%= f.check_box perm %>
<% end %>
</div>
<%= f.primary %>

View file

@ -1,9 +0,0 @@
<% content_for :heading do %>
<h1><%= t ".title" %></h1>
<% end %>
<%= render :partial => "settings_menu" %>
<%= bootstrap_form_for @client_application, :url => oauth_client_path(@client_application.user.display_name, @client_application), :html => { :method => :put } do |f| %>
<%= render :partial => "form", :locals => { :f => f } %>
<% end %>

View file

@ -1,47 +0,0 @@
<% content_for :heading do %>
<h1><%= t ".title" %></h1>
<% end %>
<%= render :partial => "settings_menu" %>
<% unless @tokens.empty? %>
<h3><%= t ".my_tokens" %></h3>
<p><%= t ".list_tokens" %></p>
<table class="table table-sm">
<thead>
<tr>
<th><%= t ".application" %></th>
<th><%= t ".issued_at" %></th>
<th>&nbsp;</th>
</tr>
</thead>
<% @tokens.each do |token| %>
<tr>
<td><%= link_to token.client_application.name, token.client_application.url %></td>
<td><%= token.authorized_at %></td>
<td>
<%= form_tag({ :controller => "oauth", :action => "revoke" }) do %>
<%= hidden_field_tag "token", token.token, :autocomplete => "off" %>
<%= submit_tag t(".revoke"), :class => "btn btn-sm btn-primary" %>
<% end %>
</td>
</tr>
<% end %>
</table>
<% end %>
<h3><%= t ".my_apps" %></h3>
<% if @client_applications.empty? %>
<p><%= t(".no_apps_html", :oauth => link_to(t(".oauth"), "https://oauth.net")) %></p>
<% else %>
<p><%= t ".registered_apps" %></p>
<ul>
<% @client_applications.each do |client| %>
<li class="client_application">
<%= link_to client.name, :action => :show, :id => client.id %>
</li>
<% end %>
</ul>
<% end %>
<% if Settings.oauth_10_registration -%>
<%= link_to t(".register_new"), { :action => :new }, :class => "btn btn-outline-primary" %>
<% end -%>

View file

@ -1,9 +0,0 @@
<% content_for :heading do %>
<h1><%= t ".title" %></h1>
<% end %>
<%= render :partial => "settings_menu" %>
<%= bootstrap_form_for @client_application, :url => { :action => :create } do |f| %>
<%= render :partial => "form", :locals => { :f => f } %>
<% end %>

View file

@ -1 +0,0 @@
<p><%= t('.sorry', :type => @type) %></p>

View file

@ -1,33 +0,0 @@
<% content_for :heading do %>
<h1><%= t(".title", :app_name => @client_application.name) %></h1>
<% end %>
<%= render :partial => "settings_menu" %>
<dl class="row">
<dt class="col-sm-3"><%= t ".key" %></dt>
<dd class="col-sm-9"><%= @client_application.key %></dt>
<dt class="col-sm-3"><%= t ".secret" %></dt>
<dd class="col-sm-9"><%= @client_application.secret %></dd>
<dt class="col-sm-3"><%= t ".url" %></dt>
<dd class="col-sm-9">http<%= "s" if request.ssl? %>://<%= request.host_with_port %><%= @client_application.oauth_server.request_token_path %></dd>
<dt class="col-sm-3"><%= t ".access_url" %></dt>
<dd class="col-sm-9">http<%= "s" if request.ssl? %>://<%= request.host_with_port %><%= @client_application.oauth_server.access_token_path %></dd>
<dt class="col-sm-3"><%= t ".authorize_url" %></dt>
<dd class="col-sm-9">http<%= "s" if request.ssl? %>://<%= request.host_with_port %><%= @client_application.oauth_server.authorize_path %></dd>
</dl>
<div>
<p><%= t ".requests" %></p>
<ul>
<% @client_application.permissions.each do |perm| %>
<li><%= t("activerecord.attributes.client_application.#{perm}") %></li>
<% end %>
</ul>
<p><%= t ".support_notice" %></p>
</div>
<div>
<%= link_to t(".edit"), edit_oauth_client_path(@client_application.user.display_name, @client_application), :method => :get, :class => "btn btn-outline-primary" %>
<%= link_to t(".delete"), oauth_client_path(@client_application.user.display_name, @client_application), :method => :delete, :data => { :confirm => t(".confirm") }, :class => "btn btn-outline-danger" %>
</div>

View file

@ -1,90 +0,0 @@
require "oauth/controllers/provider_controller"
require "oauth/helper"
require "oauth/rack/oauth_filter"
Rails.configuration.middleware.use OAuth::Rack::OAuthFilter
module OAuth
module Helper
def escape(value)
value.to_s.gsub(OAuth::RESERVED_CHARACTERS) do |c|
c.bytes.map do |b|
format("%%%02X", b)
end.join
end.force_encoding(Encoding::US_ASCII)
end
def unescape(value)
value.to_s.gsub(/%\h{2}/) do |c|
c[1..].to_i(16).chr
end.force_encoding(Encoding::UTF_8)
end
end
module RequestProxy
class RackRequest
def method
request.request_method
end
end
end
end
module OpenStreetMap
module ProviderController
def self.prepended(mod)
super
mod.singleton_class.prepend(OpenStreetMap::ProviderController::ClassMethods)
end
def render(options = {})
text = options.delete(:text)
if text
super(options.merge(:plain => text))
elsif options.delete(:nothing)
status = options.delete(:status) || :ok
head status, options
else
super
end
end
module ClassMethods
def included(controller)
controller.class_eval do
def self.before_filter(...)
before_action(...)
end
def self.skip_before_filter(...)
skip_before_action(...)
end
end
super
end
end
end
module OAuthFilter
def oauth1_verify(request, options = {}, &block)
signature = OAuth::Signature.build(request, options, &block)
return false unless OauthNonce.remember(signature.request.nonce, signature.request.timestamp)
value = signature.verify
if request.ssl? && !value
http_request = request.dup
http_request.define_singleton_method(:scheme) { "http" }
http_request.define_singleton_method(:port) { 80 }
signature = OAuth::Signature.build(http_request, options, &block)
value = signature.verify
end
value
rescue OAuth::Signature::UnknownSignatureMethod
false
end
end
end
OAuth::Controllers::ProviderController.prepend(OpenStreetMap::ProviderController)
OAuth::Rack::OAuthFilter.prepend(OpenStreetMap::OAuthFilter)

View file

@ -2598,7 +2598,6 @@ en:
need_to_see_terms: "Your access to the API is temporarily suspended. Please log-in to the web interface to view the Contributor Terms. You do not need to agree, but you must view them." need_to_see_terms: "Your access to the API is temporarily suspended. Please log-in to the web interface to view the Contributor Terms. You do not need to agree, but you must view them."
settings_menu: settings_menu:
account_settings: Account Settings account_settings: Account Settings
oauth1_settings: OAuth 1 settings
oauth2_applications: OAuth 2 applications oauth2_applications: OAuth 2 applications
oauth2_authorizations: OAuth 2 authorizations oauth2_authorizations: OAuth 2 authorizations
muted_users: Muted Users muted_users: Muted Users
@ -2624,28 +2623,6 @@ en:
title: Log in with Wikipedia title: Log in with Wikipedia
alt: Wikipedia logo alt: Wikipedia logo
oauth: oauth:
authorize:
title: "Authorize access to your account"
request_access_html: "The application %{app_name} is requesting access to your account, %{user}. Please check whether you would like the application to have the following capabilities. You may choose as many or as few as you like."
allow_to: "Allow the client application to:"
allow_read_prefs: "read your user preferences."
allow_write_prefs: "modify your user preferences."
allow_write_diary: "create diary entries, comments and make friends."
allow_write_api: "modify the map."
allow_read_gpx: "read your private GPS traces."
allow_write_gpx: "upload GPS traces."
allow_write_notes: "modify notes."
grant_access: "Grant Access"
authorize_success:
title: "Authorization request allowed"
allowed_html: "You have granted application %{app_name} access to your account."
verification: "The verification code is %{code}."
authorize_failure:
title: "Authorization request failed"
denied: "You have denied application %{app_name} access to your account."
invalid: "The authorization token is not valid."
revoke:
flash: "You've revoked the token for %{application}"
permissions: permissions:
missing: "You have not permitted the application access to this facility" missing: "You have not permitted the application access to this facility"
scopes: scopes:
@ -2664,46 +2641,6 @@ en:
skip_authorization: Auto approve application skip_authorization: Auto approve application
for_roles: for_roles:
moderator: This permission is for actions available only to moderators moderator: This permission is for actions available only to moderators
oauth_clients:
new:
title: "Register a new application"
disabled: "Registration of OAuth 1 applications has been disabled"
edit:
title: "Edit your application"
show:
title: "OAuth details for %{app_name}"
key: "Consumer Key:"
secret: "Consumer Secret:"
url: "Request Token URL:"
access_url: "Access Token URL:"
authorize_url: "Authorise URL:"
support_notice: "We support HMAC-SHA1 (recommended) and RSA-SHA1 signatures."
edit: "Edit Details"
delete: "Delete Client"
confirm: "Are you sure?"
requests: "Requesting the following permissions from the user:"
index:
title: "My OAuth Details"
my_tokens: "My Authorised Applications"
list_tokens: "The following tokens have been issued to applications in your name:"
application: "Application Name"
issued_at: "Issued At"
revoke: "Revoke!"
my_apps: "My Client Applications"
no_apps_html: "Do you have an application you would like to register for use with us using the %{oauth} standard? You must register your web application before it can make OAuth requests to this service."
oauth: OAuth
registered_apps: "You have the following client applications registered:"
register_new: "Register your application"
form:
requests: "Request the following permissions from the user:"
not_found:
sorry: "Sorry, that %{type} could not be found."
create:
flash: "Registered the information successfully"
update:
flash: "Updated the client information successfully"
destroy:
flash: "Destroyed the client application registration"
oauth2_applications: oauth2_applications:
index: index:
title: "My Client Applications" title: "My Client Applications"

View file

@ -323,17 +323,6 @@ OpenStreetMap::Application.routes.draw do
end end
resources :user_mutes, :only => [:index] resources :user_mutes, :only => [:index]
# oauth admin pages (i.e: for setting up new clients, etc...)
scope "/user/:display_name" do
resources :oauth_clients
end
match "/oauth/revoke" => "oauth#revoke", :via => [:get, :post]
match "/oauth/authorize" => "oauth#authorize", :via => [:get, :post], :as => :authorize
get "/oauth/token" => "oauth#token", :as => :token
match "/oauth/request_token" => "oauth#request_token", :via => [:get, :post], :as => :request_token
match "/oauth/access_token" => "oauth#access_token", :via => [:get, :post], :as => :access_token
get "/oauth/test_request" => "oauth#test_request", :as => :test_request
# roles and banning pages # roles and banning pages
post "/user/:display_name/role/:role/grant" => "user_roles#grant", :as => "grant_role" post "/user/:display_name/role/:role/grant" => "user_roles#grant", :as => "grant_role"
post "/user/:display_name/role/:role/revoke" => "user_roles#revoke", :as => "revoke_role" post "/user/:display_name/role/:role/revoke" => "user_roles#revoke", :as => "revoke_role"

View file

@ -108,12 +108,6 @@ attachments_dir: ":rails_root/public/attachments"
#memcache_servers: [] #memcache_servers: []
# Enable HTTP basic authentication support # Enable HTTP basic authentication support
basic_auth_support: true basic_auth_support: true
# Enable OAuth 1.0/1.0a registration
oauth_10_registration: true
# Enable legacy OAuth 1.0 support
oauth_10_support: true
# Enable OAuth 1.0a support
oauth_10a_support: true
# URL of Nominatim instance to use for geocoding # URL of Nominatim instance to use for geocoding
nominatim_url: "https://nominatim.openstreetmap.org/" nominatim_url: "https://nominatim.openstreetmap.org/"
# Default editor # Default editor

View file

@ -0,0 +1,38 @@
class DropOauth1Tables < ActiveRecord::Migration[7.1]
def change
remove_index :oauth_nonces, [:nonce, :timestamp], :unique => true
drop_table :oauth_nonces do |t|
t.string :nonce
t.integer :timestamp
t.timestamps :null => true
end
remove_index :oauth_tokens, :token, :unique => true
drop_table :oauth_tokens do |t|
t.integer :user_id
t.string :type, :limit => 20
t.integer :client_application_id
t.string :token, :limit => 50
t.string :secret, :limit => 50
t.timestamp :authorized_at, :invalidated_at
t.timestamps :null => true
end
remove_index :client_applications, :key, :unique => true
drop_table :client_applications do |t|
t.string :name
t.string :url
t.string :support_url
t.string :callback_url
t.string :key, :limit => 50
t.string :secret, :limit => 50
t.integer :user_id
t.timestamps :null => true
end
end
end

View file

@ -472,51 +472,6 @@ CREATE TABLE public.changesets_subscribers (
); );
--
-- Name: client_applications; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.client_applications (
id integer NOT NULL,
name character varying,
url character varying,
support_url character varying,
callback_url character varying,
key character varying(50),
secret character varying(50),
user_id integer,
created_at timestamp without time zone,
updated_at timestamp without time zone,
allow_read_prefs boolean DEFAULT false NOT NULL,
allow_write_prefs boolean DEFAULT false NOT NULL,
allow_write_diary boolean DEFAULT false NOT NULL,
allow_write_api boolean DEFAULT false NOT NULL,
allow_read_gpx boolean DEFAULT false NOT NULL,
allow_write_gpx boolean DEFAULT false NOT NULL,
allow_write_notes boolean DEFAULT false NOT NULL
);
--
-- Name: client_applications_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.client_applications_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: client_applications_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE public.client_applications_id_seq OWNED BY public.client_applications.id;
-- --
-- Name: current_node_tags; Type: TABLE; Schema: public; Owner: - -- Name: current_node_tags; Type: TABLE; Schema: public; Owner: -
-- --
@ -1244,38 +1199,6 @@ CREATE SEQUENCE public.oauth_applications_id_seq
ALTER SEQUENCE public.oauth_applications_id_seq OWNED BY public.oauth_applications.id; ALTER SEQUENCE public.oauth_applications_id_seq OWNED BY public.oauth_applications.id;
--
-- Name: oauth_nonces; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.oauth_nonces (
id bigint NOT NULL,
nonce character varying,
"timestamp" integer,
created_at timestamp without time zone,
updated_at timestamp without time zone
);
--
-- Name: oauth_nonces_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.oauth_nonces_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: oauth_nonces_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE public.oauth_nonces_id_seq OWNED BY public.oauth_nonces.id;
-- --
-- Name: oauth_openid_requests; Type: TABLE; Schema: public; Owner: - -- Name: oauth_openid_requests; Type: TABLE; Schema: public; Owner: -
-- --
@ -1306,55 +1229,6 @@ CREATE SEQUENCE public.oauth_openid_requests_id_seq
ALTER SEQUENCE public.oauth_openid_requests_id_seq OWNED BY public.oauth_openid_requests.id; ALTER SEQUENCE public.oauth_openid_requests_id_seq OWNED BY public.oauth_openid_requests.id;
--
-- Name: oauth_tokens; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.oauth_tokens (
id integer NOT NULL,
user_id integer,
type character varying(20),
client_application_id integer,
token character varying(50),
secret character varying(50),
authorized_at timestamp without time zone,
invalidated_at timestamp without time zone,
created_at timestamp without time zone,
updated_at timestamp without time zone,
allow_read_prefs boolean DEFAULT false NOT NULL,
allow_write_prefs boolean DEFAULT false NOT NULL,
allow_write_diary boolean DEFAULT false NOT NULL,
allow_write_api boolean DEFAULT false NOT NULL,
allow_read_gpx boolean DEFAULT false NOT NULL,
allow_write_gpx boolean DEFAULT false NOT NULL,
callback_url character varying,
verifier character varying(20),
scope character varying,
valid_to timestamp without time zone,
allow_write_notes boolean DEFAULT false NOT NULL
);
--
-- Name: oauth_tokens_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.oauth_tokens_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: oauth_tokens_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE public.oauth_tokens_id_seq OWNED BY public.oauth_tokens.id;
-- --
-- Name: redactions; Type: TABLE; Schema: public; Owner: - -- Name: redactions; Type: TABLE; Schema: public; Owner: -
-- --
@ -1728,13 +1602,6 @@ ALTER TABLE ONLY public.changeset_comments ALTER COLUMN id SET DEFAULT nextval('
ALTER TABLE ONLY public.changesets ALTER COLUMN id SET DEFAULT nextval('public.changesets_id_seq'::regclass); ALTER TABLE ONLY public.changesets ALTER COLUMN id SET DEFAULT nextval('public.changesets_id_seq'::regclass);
--
-- Name: client_applications id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.client_applications ALTER COLUMN id SET DEFAULT nextval('public.client_applications_id_seq'::regclass);
-- --
-- Name: current_nodes id; Type: DEFAULT; Schema: public; Owner: - -- Name: current_nodes id; Type: DEFAULT; Schema: public; Owner: -
-- --
@ -1854,13 +1721,6 @@ ALTER TABLE ONLY public.oauth_access_tokens ALTER COLUMN id SET DEFAULT nextval(
ALTER TABLE ONLY public.oauth_applications ALTER COLUMN id SET DEFAULT nextval('public.oauth_applications_id_seq'::regclass); ALTER TABLE ONLY public.oauth_applications ALTER COLUMN id SET DEFAULT nextval('public.oauth_applications_id_seq'::regclass);
--
-- Name: oauth_nonces id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.oauth_nonces ALTER COLUMN id SET DEFAULT nextval('public.oauth_nonces_id_seq'::regclass);
-- --
-- Name: oauth_openid_requests id; Type: DEFAULT; Schema: public; Owner: - -- Name: oauth_openid_requests id; Type: DEFAULT; Schema: public; Owner: -
-- --
@ -1868,13 +1728,6 @@ ALTER TABLE ONLY public.oauth_nonces ALTER COLUMN id SET DEFAULT nextval('public
ALTER TABLE ONLY public.oauth_openid_requests ALTER COLUMN id SET DEFAULT nextval('public.oauth_openid_requests_id_seq'::regclass); ALTER TABLE ONLY public.oauth_openid_requests ALTER COLUMN id SET DEFAULT nextval('public.oauth_openid_requests_id_seq'::regclass);
--
-- Name: oauth_tokens id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.oauth_tokens ALTER COLUMN id SET DEFAULT nextval('public.oauth_tokens_id_seq'::regclass);
-- --
-- Name: redactions id; Type: DEFAULT; Schema: public; Owner: - -- Name: redactions id; Type: DEFAULT; Schema: public; Owner: -
-- --
@ -1981,14 +1834,6 @@ ALTER TABLE ONLY public.changesets
ADD CONSTRAINT changesets_pkey PRIMARY KEY (id); ADD CONSTRAINT changesets_pkey PRIMARY KEY (id);
--
-- Name: client_applications client_applications_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.client_applications
ADD CONSTRAINT client_applications_pkey PRIMARY KEY (id);
-- --
-- Name: current_node_tags current_node_tags_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- Name: current_node_tags current_node_tags_pkey; Type: CONSTRAINT; Schema: public; Owner: -
-- --
@ -2197,14 +2042,6 @@ ALTER TABLE ONLY public.oauth_applications
ADD CONSTRAINT oauth_applications_pkey PRIMARY KEY (id); ADD CONSTRAINT oauth_applications_pkey PRIMARY KEY (id);
--
-- Name: oauth_nonces oauth_nonces_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.oauth_nonces
ADD CONSTRAINT oauth_nonces_pkey PRIMARY KEY (id);
-- --
-- Name: oauth_openid_requests oauth_openid_requests_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- Name: oauth_openid_requests oauth_openid_requests_pkey; Type: CONSTRAINT; Schema: public; Owner: -
-- --
@ -2213,14 +2050,6 @@ ALTER TABLE ONLY public.oauth_openid_requests
ADD CONSTRAINT oauth_openid_requests_pkey PRIMARY KEY (id); ADD CONSTRAINT oauth_openid_requests_pkey PRIMARY KEY (id);
--
-- Name: oauth_tokens oauth_tokens_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.oauth_tokens
ADD CONSTRAINT oauth_tokens_pkey PRIMARY KEY (id);
-- --
-- Name: redactions redactions_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- Name: redactions redactions_pkey; Type: CONSTRAINT; Schema: public; Owner: -
-- --
@ -2585,20 +2414,6 @@ CREATE INDEX index_changesets_subscribers_on_changeset_id ON public.changesets_s
CREATE UNIQUE INDEX index_changesets_subscribers_on_subscriber_id_and_changeset_id ON public.changesets_subscribers USING btree (subscriber_id, changeset_id); CREATE UNIQUE INDEX index_changesets_subscribers_on_subscriber_id_and_changeset_id ON public.changesets_subscribers USING btree (subscriber_id, changeset_id);
--
-- Name: index_client_applications_on_key; Type: INDEX; Schema: public; Owner: -
--
CREATE UNIQUE INDEX index_client_applications_on_key ON public.client_applications USING btree (key);
--
-- Name: index_client_applications_on_user_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_client_applications_on_user_id ON public.client_applications USING btree (user_id);
-- --
-- Name: index_diary_entry_subscriptions_on_diary_entry_id; Type: INDEX; Schema: public; Owner: - -- Name: index_diary_entry_subscriptions_on_diary_entry_id; Type: INDEX; Schema: public; Owner: -
-- --
@ -2746,13 +2561,6 @@ CREATE INDEX index_oauth_applications_on_owner_type_and_owner_id ON public.oauth
CREATE UNIQUE INDEX index_oauth_applications_on_uid ON public.oauth_applications USING btree (uid); CREATE UNIQUE INDEX index_oauth_applications_on_uid ON public.oauth_applications USING btree (uid);
--
-- Name: index_oauth_nonces_on_nonce_and_timestamp; Type: INDEX; Schema: public; Owner: -
--
CREATE UNIQUE INDEX index_oauth_nonces_on_nonce_and_timestamp ON public.oauth_nonces USING btree (nonce, "timestamp");
-- --
-- Name: index_oauth_openid_requests_on_access_grant_id; Type: INDEX; Schema: public; Owner: - -- Name: index_oauth_openid_requests_on_access_grant_id; Type: INDEX; Schema: public; Owner: -
-- --
@ -2760,20 +2568,6 @@ CREATE UNIQUE INDEX index_oauth_nonces_on_nonce_and_timestamp ON public.oauth_no
CREATE INDEX index_oauth_openid_requests_on_access_grant_id ON public.oauth_openid_requests USING btree (access_grant_id); CREATE INDEX index_oauth_openid_requests_on_access_grant_id ON public.oauth_openid_requests USING btree (access_grant_id);
--
-- Name: index_oauth_tokens_on_token; Type: INDEX; Schema: public; Owner: -
--
CREATE UNIQUE INDEX index_oauth_tokens_on_token ON public.oauth_tokens USING btree (token);
--
-- Name: index_oauth_tokens_on_user_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_oauth_tokens_on_user_id ON public.oauth_tokens USING btree (user_id);
-- --
-- Name: index_reports_on_issue_id; Type: INDEX; Schema: public; Owner: - -- Name: index_reports_on_issue_id; Type: INDEX; Schema: public; Owner: -
-- --
@ -3032,14 +2826,6 @@ ALTER TABLE ONLY public.changesets
ADD CONSTRAINT changesets_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id); ADD CONSTRAINT changesets_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id);
--
-- Name: client_applications client_applications_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.client_applications
ADD CONSTRAINT client_applications_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id);
-- --
-- Name: current_node_tags current_node_tags_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- Name: current_node_tags current_node_tags_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
-- --
@ -3376,22 +3162,6 @@ ALTER TABLE ONLY public.note_comments
ADD CONSTRAINT note_comments_note_id_fkey FOREIGN KEY (note_id) REFERENCES public.notes(id); ADD CONSTRAINT note_comments_note_id_fkey FOREIGN KEY (note_id) REFERENCES public.notes(id);
--
-- Name: oauth_tokens oauth_tokens_client_application_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.oauth_tokens
ADD CONSTRAINT oauth_tokens_client_application_id_fkey FOREIGN KEY (client_application_id) REFERENCES public.client_applications(id);
--
-- Name: oauth_tokens oauth_tokens_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.oauth_tokens
ADD CONSTRAINT oauth_tokens_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id);
-- --
-- Name: redactions redactions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- Name: redactions redactions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
-- --
@ -3581,6 +3351,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('21'), ('21'),
('20240822121603'), ('20240822121603'),
('20240813070506'), ('20240813070506'),
('20240724194738'),
('20240618193051'), ('20240618193051'),
('20240605134916'), ('20240605134916'),
('20240405083825'), ('20240405083825'),

View file

@ -1,9 +1,6 @@
namespace :db do namespace :db do
desc "Expire old tokens" desc "Expire old tokens"
task :expire_tokens => :environment do task :expire_tokens => :environment do
OauthNonce.where("timestamp < EXTRACT(EPOCH FROM NOW() - INTERVAL '1 day')").delete_all
OauthToken.where("invalidated_at < NOW() - INTERVAL '28 days'").delete_all
RequestToken.where("authorized_at IS NULL AND created_at < NOW() - INTERVAL '28 days'").delete_all
Doorkeeper::AccessGrant.where("revoked_at < NOW() - INTERVAL '28 days' OR (created_at + expires_in * INTERVAL '1 second') < NOW() - INTERVAL '28 days'").delete_all Doorkeeper::AccessGrant.where("revoked_at < NOW() - INTERVAL '28 days' OR (created_at + expires_in * INTERVAL '1 second') < NOW() - INTERVAL '28 days'").delete_all
Doorkeeper::AccessToken.where("revoked_at < NOW() - INTERVAL '28 days' OR (created_at + expires_in * INTERVAL '1 second') < NOW() - INTERVAL '28 days'").delete_all Doorkeeper::AccessToken.where("revoked_at < NOW() - INTERVAL '28 days' OR (created_at + expires_in * INTERVAL '1 second') < NOW() - INTERVAL '28 days'").delete_all
end end

View file

@ -37,9 +37,9 @@ module Api
get permissions_path, :headers => auth_header get permissions_path, :headers => auth_header
assert_response :success assert_response :success
assert_select "osm > permissions", :count => 1 do assert_select "osm > permissions", :count => 1 do
assert_select "permission", :count => ClientApplication.all_permissions.size assert_select "permission", :count => Oauth.scopes.size
ClientApplication.all_permissions.each do |p| Oauth.scopes.each do |p|
assert_select "permission[name='#{p}']", :count => 1 assert_select "permission[name='allow_#{p.name}']", :count => 1
end end
end end
@ -50,24 +50,9 @@ module Api
js = ActiveSupport::JSON.decode(@response.body) js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js assert_not_nil js
assert_equal ClientApplication.all_permissions.size, js["permissions"].count assert_equal Oauth.scopes.size, js["permissions"].count
ClientApplication.all_permissions.each do |p| Oauth.scopes.each do |p|
assert_includes js["permissions"], p.to_s assert_includes js["permissions"], "allow_#{p.name}"
end
end
def test_permissions_oauth1
token = create(:access_token,
:allow_read_prefs => true,
:allow_write_api => true,
:allow_read_gpx => false)
signed_get permissions_path, :oauth => { :token => token }
assert_response :success
assert_select "osm > permissions", :count => 1 do
assert_select "permission", :count => 2
assert_select "permission[name='allow_read_prefs']", :count => 1
assert_select "permission[name='allow_write_api']", :count => 1
assert_select "permission[name='allow_read_gpx']", :count => 0
end end
end end

View file

@ -75,80 +75,6 @@ module Api
check_json_details(js, user, false, false) check_json_details(js, user, false, false)
end end
def test_show_oauth1
user = create(:user,
:home_lat => 12.1, :home_lon => 23.4,
:languages => ["en"])
good_token = create(:access_token,
:user => user,
:allow_read_prefs => true)
bad_token = create(:access_token,
:user => user)
other_user = create(:user,
:home_lat => 12.1, :home_lon => 23.4,
:languages => ["en"])
# check that we can fetch our own details as XML with read_prefs
signed_get api_user_path(:id => user.id), :oauth => { :token => good_token }
assert_response :success
assert_equal "application/xml", response.media_type
# check the data that is returned
check_xml_details(user, true, false)
# check that we can fetch a different user's details as XML with read_prefs
signed_get api_user_path(:id => other_user.id), :oauth => { :token => good_token }
assert_response :success
assert_equal "application/xml", response.media_type
# check the data that is returned
check_xml_details(other_user, false, false)
# check that we can fetch our own details as XML without read_prefs
signed_get api_user_path(:id => user.id), :oauth => { :token => bad_token }
assert_response :success
assert_equal "application/xml", response.media_type
# check the data that is returned
check_xml_details(user, false, false)
# check that we can fetch our own details as JSON with read_prefs
signed_get api_user_path(:id => user.id, :format => "json"), :oauth => { :token => good_token }
assert_response :success
assert_equal "application/json", response.media_type
# parse the response
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
# check the data that is returned
check_json_details(js, user, true, false)
# check that we can fetch a different user's details as JSON with read_prefs
signed_get api_user_path(:id => other_user.id, :format => "json"), :oauth => { :token => good_token }
assert_response :success
assert_equal "application/json", response.media_type
# parse the response
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
# check the data that is returned
check_json_details(js, other_user, false, false)
# check that we can fetch our own details as JSON without read_prefs
signed_get api_user_path(:id => other_user.id, :format => "json"), :oauth => { :token => bad_token }
assert_response :success
assert_equal "application/json", response.media_type
# parse the response
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
# check the data that is returned
check_json_details(js, other_user, false, false)
end
def test_show_oauth2 def test_show_oauth2
user = create(:user, user = create(:user,
:home_lat => 12.1, :home_lon => 23.4, :home_lat => 12.1, :home_lon => 23.4,
@ -260,45 +186,6 @@ module Api
check_json_details(js, user, true, false) check_json_details(js, user, true, false)
end end
def test_details_oauth1
user = create(:user,
:home_lat => 12.1, :home_lon => 23.4,
:languages => ["en"])
good_token = create(:access_token,
:user => user,
:allow_read_prefs => true)
bad_token = create(:access_token,
:user => user)
# check that we can't fetch details as XML without read_prefs
signed_get user_details_path, :oauth => { :token => bad_token }
assert_response :forbidden
# check that we can fetch details as XML
signed_get user_details_path, :oauth => { :token => good_token }
assert_response :success
assert_equal "application/xml", response.media_type
# check the data that is returned
check_xml_details(user, true, false)
# check that we can't fetch details as JSON without read_prefs
signed_get user_details_path(:format => "json"), :oauth => { :token => bad_token }
assert_response :forbidden
# check that we can fetch details as JSON
signed_get user_details_path(:format => "json"), :oauth => { :token => good_token }
assert_response :success
assert_equal "application/json", response.media_type
# parse the response
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
# check the data that is returned
check_json_details(js, user, true, false)
end
def test_details_oauth2 def test_details_oauth2
user = create(:user, user = create(:user,
:home_lat => 12.1, :home_lon => 23.4, :home_lat => 12.1, :home_lon => 23.4,
@ -434,99 +321,6 @@ module Api
assert_select "user", :count => 0 assert_select "user", :count => 0
end end
def test_index_oauth1
user1 = create(:user, :description => "test1", :terms_agreed => Date.yesterday)
user2 = create(:user, :description => "test2", :terms_agreed => Date.yesterday)
user3 = create(:user, :description => "test3", :terms_agreed => Date.yesterday)
good_token = create(:access_token, :user => user1, :allow_read_prefs => true)
bad_token = create(:access_token, :user => user1)
signed_get api_users_path, :params => { :users => user1.id }, :oauth => { :token => good_token }
assert_response :success
assert_equal "application/xml", response.media_type
assert_select "user", :count => 1 do
check_xml_details(user1, true, false)
assert_select "user[id='#{user2.id}']", :count => 0
assert_select "user[id='#{user3.id}']", :count => 0
end
signed_get api_users_path, :params => { :users => user2.id }, :oauth => { :token => good_token }
assert_response :success
assert_equal "application/xml", response.media_type
assert_select "user", :count => 1 do
assert_select "user[id='#{user1.id}']", :count => 0
check_xml_details(user2, false, false)
assert_select "user[id='#{user3.id}']", :count => 0
end
signed_get api_users_path, :params => { :users => "#{user1.id},#{user3.id}" }, :oauth => { :token => good_token }
assert_response :success
assert_equal "application/xml", response.media_type
assert_select "user", :count => 2 do
check_xml_details(user1, true, false)
assert_select "user[id='#{user2.id}']", :count => 0
check_xml_details(user3, false, false)
end
signed_get api_users_path, :params => { :users => "#{user1.id},#{user3.id}" }, :oauth => { :token => bad_token }
assert_response :success
assert_equal "application/xml", response.media_type
assert_select "user", :count => 2 do
check_xml_details(user1, false, false)
assert_select "user[id='#{user2.id}']", :count => 0
check_xml_details(user3, false, false)
end
signed_get api_users_path, :params => { :users => user1.id, :format => "json" }, :oauth => { :token => good_token }
assert_response :success
assert_equal "application/json", response.media_type
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal 1, js["users"].count
check_json_details(js["users"][0], user1, true, false)
signed_get api_users_path, :params => { :users => user2.id, :format => "json" }, :oauth => { :token => good_token }
assert_response :success
assert_equal "application/json", response.media_type
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal 1, js["users"].count
check_json_details(js["users"][0], user2, false, false)
signed_get api_users_path, :params => { :users => "#{user1.id},#{user3.id}", :format => "json" }, :oauth => { :token => good_token }
assert_response :success
assert_equal "application/json", response.media_type
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal 2, js["users"].count
check_json_details(js["users"][0], user1, true, false)
check_json_details(js["users"][1], user3, false, false)
signed_get api_users_path, :params => { :users => "#{user1.id},#{user3.id}", :format => "json" }, :oauth => { :token => bad_token }
assert_response :success
assert_equal "application/json", response.media_type
js = ActiveSupport::JSON.decode(@response.body)
assert_not_nil js
assert_equal 2, js["users"].count
check_json_details(js["users"][0], user1, false, false)
check_json_details(js["users"][1], user3, false, false)
signed_get api_users_path, :params => { :users => create(:user, :suspended).id }, :oauth => { :token => good_token }
assert_response :success
assert_equal "application/xml", response.media_type
assert_select "user", :count => 0
signed_get api_users_path, :params => { :users => create(:user, :deleted).id }, :oauth => { :token => good_token }
assert_response :success
assert_equal "application/xml", response.media_type
assert_select "user", :count => 0
signed_get api_users_path, :params => { :users => 0 }, :oauth => { :token => good_token }
assert_response :success
assert_equal "application/xml", response.media_type
assert_select "user", :count => 0
end
def test_index_oauth2 def test_index_oauth2
user1 = create(:user, :description => "test1", :terms_agreed => Date.yesterday) user1 = create(:user, :description => "test1", :terms_agreed => Date.yesterday)
user2 = create(:user, :description => "test2", :terms_agreed => Date.yesterday) user2 = create(:user, :description => "test2", :terms_agreed => Date.yesterday)

View file

@ -1,204 +0,0 @@
require "test_helper"
class OauthClientsControllerTest < ActionDispatch::IntegrationTest
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/user/username/oauth_clients", :method => :get },
{ :controller => "oauth_clients", :action => "index", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/oauth_clients/new", :method => :get },
{ :controller => "oauth_clients", :action => "new", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/oauth_clients", :method => :post },
{ :controller => "oauth_clients", :action => "create", :display_name => "username" }
)
assert_routing(
{ :path => "/user/username/oauth_clients/1", :method => :get },
{ :controller => "oauth_clients", :action => "show", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/oauth_clients/1/edit", :method => :get },
{ :controller => "oauth_clients", :action => "edit", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/oauth_clients/1", :method => :put },
{ :controller => "oauth_clients", :action => "update", :display_name => "username", :id => "1" }
)
assert_routing(
{ :path => "/user/username/oauth_clients/1", :method => :delete },
{ :controller => "oauth_clients", :action => "destroy", :display_name => "username", :id => "1" }
)
end
def test_index
user = create(:user)
create_list(:client_application, 2, :user => user)
create_list(:access_token, 2, :user => user)
get oauth_clients_path(user)
assert_redirected_to login_path(:referer => oauth_clients_path(user))
session_for(user)
get oauth_clients_path(user)
assert_response :success
assert_template "index"
assert_select "li.client_application", 2
end
def test_new
user = create(:user)
get new_oauth_client_path(user)
assert_redirected_to login_path(:referer => new_oauth_client_path(user))
session_for(user)
get new_oauth_client_path(user)
assert_response :success
assert_template "new"
assert_select "form", 1 do
assert_select "input#client_application_name", 1
assert_select "input#client_application_url", 1
assert_select "input#client_application_callback_url", 1
assert_select "input#client_application_support_url", 1
ClientApplication.all_permissions.each do |perm|
assert_select "input#client_application_#{perm}", 1
end
end
end
def test_new_disabled
user = create(:user)
with_settings(:oauth_10_registration => false) do
get new_oauth_client_path(user)
assert_redirected_to login_path(:referer => new_oauth_client_path(user))
session_for(user)
get new_oauth_client_path(user)
assert_redirected_to oauth_clients_path(user)
end
end
def test_create
user = create(:user)
assert_difference "ClientApplication.count", 0 do
post oauth_clients_path(user)
end
assert_response :forbidden
session_for(user)
assert_difference "ClientApplication.count", 0 do
post oauth_clients_path(user, :client_application => { :name => "Test Application" })
end
assert_response :success
assert_template "new"
assert_difference "ClientApplication.count", 1 do
post oauth_clients_path(user, :client_application => { :name => "Test Application",
:url => "http://test.example.com/" })
end
assert_redirected_to oauth_client_path(:id => ClientApplication.find_by(:name => "Test Application").id)
end
def test_show
user = create(:user)
client = create(:client_application, :user => user)
other_client = create(:client_application)
get oauth_client_path(user, client)
assert_redirected_to login_path(:referer => oauth_client_path(user, client.id))
session_for(user)
get oauth_client_path(user, other_client)
assert_response :not_found
assert_template "not_found"
get oauth_client_path(user, client)
assert_response :success
assert_template "show"
end
def test_edit
user = create(:user)
client = create(:client_application, :user => user)
other_client = create(:client_application)
get edit_oauth_client_path(user, client)
assert_redirected_to login_path(:referer => edit_oauth_client_path(user, client.id))
session_for(user)
get edit_oauth_client_path(user, other_client)
assert_response :not_found
assert_template "not_found"
get edit_oauth_client_path(user, client)
assert_response :success
assert_template "edit"
assert_select "form", 1 do
assert_select "input#client_application_name", 1
assert_select "input#client_application_url", 1
assert_select "input#client_application_callback_url", 1
assert_select "input#client_application_support_url", 1
ClientApplication.all_permissions.each do |perm|
assert_select "input#client_application_#{perm}", 1
end
end
end
def test_update
user = create(:user)
client = create(:client_application, :user => user)
other_client = create(:client_application)
put oauth_client_path(user, client)
assert_response :forbidden
session_for(user)
put oauth_client_path(user, other_client)
assert_response :not_found
assert_template "not_found"
put oauth_client_path(user, client, :client_application => { :name => "New Name", :url => nil })
assert_response :success
assert_template "edit"
put oauth_client_path(user, client, :client_application => { :name => "New Name", :url => "http://new.example.com/url" })
assert_redirected_to oauth_client_path(:id => client.id)
end
def test_destroy
user = create(:user)
client = create(:client_application, :user => user)
other_client = create(:client_application)
assert_difference "ClientApplication.count", 0 do
delete oauth_client_path(user, client)
end
assert_response :forbidden
session_for(user)
assert_difference "ClientApplication.count", 0 do
delete oauth_client_path(user, other_client)
end
assert_response :not_found
assert_template "not_found"
assert_difference "ClientApplication.count", -1 do
delete oauth_client_path(user, client)
end
assert_redirected_to oauth_clients_path(user)
end
end

View file

@ -1,48 +0,0 @@
require "test_helper"
class OauthControllerTest < ActionDispatch::IntegrationTest
##
# test all routes which lead to this controller
def test_routes
assert_routing(
{ :path => "/oauth/revoke", :method => :get },
{ :controller => "oauth", :action => "revoke" }
)
assert_routing(
{ :path => "/oauth/revoke", :method => :post },
{ :controller => "oauth", :action => "revoke" }
)
assert_routing(
{ :path => "/oauth/authorize", :method => :get },
{ :controller => "oauth", :action => "authorize" }
)
assert_routing(
{ :path => "/oauth/authorize", :method => :post },
{ :controller => "oauth", :action => "authorize" }
)
assert_routing(
{ :path => "/oauth/token", :method => :get },
{ :controller => "oauth", :action => "token" }
)
assert_routing(
{ :path => "/oauth/request_token", :method => :get },
{ :controller => "oauth", :action => "request_token" }
)
assert_routing(
{ :path => "/oauth/request_token", :method => :post },
{ :controller => "oauth", :action => "request_token" }
)
assert_routing(
{ :path => "/oauth/access_token", :method => :get },
{ :controller => "oauth", :action => "access_token" }
)
assert_routing(
{ :path => "/oauth/access_token", :method => :post },
{ :controller => "oauth", :action => "access_token" }
)
assert_routing(
{ :path => "/oauth/test_request", :method => :get },
{ :controller => "oauth", :action => "test_request" }
)
end
end

View file

@ -1,8 +0,0 @@
FactoryBot.define do
factory :client_application do
sequence(:name) { |n| "Client application #{n}" }
sequence(:url) { |n| "http://example.com/app/#{n}" }
user
end
end

View file

@ -1,91 +0,0 @@
require "test_helper"
class ClientApplicationsTest < ActionDispatch::IntegrationTest
##
# run through the procedure of creating a client application and checking
# that it shows up on the user's account page.
def test_create_application
user = create(:user)
get "/login"
assert_redirected_to login_path(:cookie_test => "true")
follow_redirect!
assert_response :success
post "/login", :params => { "username" => user.email, "password" => "test", :referer => "/user/#{ERB::Util.u(user.display_name)}" }
assert_response :redirect
follow_redirect!
assert_response :success
assert_template "users/show"
get "/account/edit"
assert_response :success
assert_template "accounts/edit"
# check that the form to allow new client application creations exists
assert_in_heading do
assert_select "ul.nav.nav-tabs li.nav-item a[href='/user/#{ERB::Util.u(user.display_name)}/oauth_clients']"
end
# now we follow the link to the oauth client list
get "/user/#{ERB::Util.u(user.display_name)}/oauth_clients"
assert_response :success
assert_in_body do
assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/oauth_clients/new']"
end
# now we follow the link to the new oauth client page
get "/user/#{ERB::Util.u(user.display_name)}/oauth_clients/new"
assert_response :success
assert_in_heading do
assert_select "h1", "Register a new application"
end
assert_in_body do
assert_select "form[action='/user/#{ERB::Util.u(user.display_name)}/oauth_clients']" do
[:name, :url, :callback_url, :support_url].each do |inp|
assert_select "input[name=?]", "client_application[#{inp}]"
end
ClientApplication.all_permissions.each do |perm|
assert_select "input[name=?]", "client_application[#{perm}]"
end
end
end
post "/user/#{ERB::Util.u(user.display_name)}/oauth_clients",
:params => { "client_application[name]" => "My New App",
"client_application[url]" => "http://my.new.app.org/",
"client_application[callback_url]" => "http://my.new.app.org/callback",
"client_application[support_url]" => "http://my.new.app.org/support" }
assert_response :redirect
follow_redirect!
assert_response :success
assert_template "oauth_clients/show"
assert_equal "Registered the information successfully", flash[:notice]
# now go back to the account page and check its listed under this user
get "/user/#{ERB::Util.u(user.display_name)}/oauth_clients"
assert_response :success
assert_template "oauth_clients/index"
assert_in_body { assert_select "li>a", "My New App" }
end
##
# fake client workflow.
# this acts like a 3rd party client trying to access the site.
def test_3rd_party_token
# apparently the oauth gem doesn't really support being used inside integration
# tests, as its too tied into the HTTP headers and stuff that it signs.
end
private
##
# utility method to make the HTML screening easier to read.
def assert_in_heading(&block)
assert_select("div.content-heading", &block)
end
##
# utility method to make the HTML screening easier to read.
def assert_in_body(&block)
assert_select("div#content", &block)
end
end

View file

@ -1,421 +0,0 @@
require "test_helper"
class OAuthTest < ActionDispatch::IntegrationTest
include OAuth::Helper
def test_oauth10_web_app
client = create(:client_application, :callback_url => "http://some.web.app.example.org/callback", :allow_read_prefs => true, :allow_write_api => true, :allow_read_gpx => true)
user = create(:user)
session_for(user)
oauth10_without_callback(client)
oauth10_with_callback(client, "http://another.web.app.example.org/callback")
oauth10_refused(client)
end
def test_oauth10_desktop_app
client = create(:client_application, :allow_read_prefs => true, :allow_write_api => true, :allow_read_gpx => true)
user = create(:user)
session_for(user)
oauth10_without_callback(client)
oauth10_refused(client)
end
def test_oauth10a_web_app
client = create(:client_application, :callback_url => "http://some.web.app.example.org/callback", :allow_read_prefs => true, :allow_write_api => true, :allow_read_gpx => true)
user = create(:user)
session_for(user)
oauth10a_without_callback(client)
oauth10a_with_callback(client, "http://another.web.app.example.org/callback")
oauth10a_refused(client)
end
def test_oauth10a_desktop_app
client = create(:client_application, :allow_read_prefs => true, :allow_write_api => true, :allow_read_gpx => true)
user = create(:user)
session_for(user)
oauth10a_without_callback(client)
oauth10a_refused(client)
end
private
def oauth10_without_callback(client)
token = get_request_token(client)
get "/oauth/authorize", :params => { :oauth_token => token.token }
assert_response :success
assert_template :authorize
post "/oauth/authorize",
:params => { :oauth_token => token.token,
:allow_read_prefs => "1", :allow_write_prefs => "1" }
if client.callback_url
assert_redirected_to "#{client.callback_url}?oauth_token=#{token.token}"
else
assert_response :success
assert_template :authorize_success
end
token.reload
assert_not_nil token.created_at
assert_not_nil token.authorized_at
assert_nil token.invalidated_at
assert_allowed token, [:allow_read_prefs]
signed_get "/oauth/access_token", :oauth => { :token => token }
assert_response :success
token.reload
assert_not_nil token.created_at
assert_not_nil token.authorized_at
assert_not_nil token.invalidated_at
token = parse_token(response)
assert_instance_of AccessToken, token
assert_not_nil token.created_at
assert_not_nil token.authorized_at
assert_nil token.invalidated_at
assert_allowed token, [:allow_read_prefs]
post logout_path
signed_get "/api/0.6/user/preferences", :oauth => { :token => token }
assert_response :success
signed_get "/api/0.6/gpx/2", :oauth => { :token => token }
assert_response :forbidden
token.user.suspend!
signed_get "/api/0.6/user/preferences", :oauth => { :token => token }
assert_response :forbidden
token.user.hide!
signed_get "/api/0.6/user/preferences", :oauth => { :token => token }
assert_response :forbidden
token.user.unhide!
signed_get "/api/0.6/user/preferences", :oauth => { :token => token }
assert_response :success
session_for(token.user)
post "/oauth/revoke", :params => { :token => token.token }
assert_redirected_to oauth_clients_url(token.user.display_name)
token = OauthToken.find_by(:token => token.token)
assert_not_nil token.invalidated_at
signed_get "/api/0.6/user/preferences", :oauth => { :token => token }
assert_response :unauthorized
end
def oauth10_refused(client)
token = get_request_token(client)
get "/oauth/authorize", :params => { :oauth_token => token.token }
assert_response :success
assert_template :authorize
post "/oauth/authorize", :params => { :oauth_token => token.token }
assert_response :success
assert_template :authorize_failure
assert_select "p", "You have denied application #{client.name} access to your account."
token.reload
assert_nil token.authorized_at
assert_not_nil token.invalidated_at
get "/oauth/authorize", :params => { :oauth_token => token.token }
assert_response :success
assert_template :authorize_failure
assert_select "p", "The authorization token is not valid."
token.reload
assert_nil token.authorized_at
assert_not_nil token.invalidated_at
post "/oauth/authorize", :params => { :oauth_token => token.token }
assert_response :success
assert_template :authorize_failure
assert_select "p", "The authorization token is not valid."
token.reload
assert_nil token.authorized_at
assert_not_nil token.invalidated_at
end
def oauth10_with_callback(client, callback_url)
token = get_request_token(client)
get "/oauth/authorize", :params => { :oauth_token => token.token }
assert_response :success
assert_template :authorize
post "/oauth/authorize",
:params => { :oauth_token => token.token, :oauth_callback => callback_url,
:allow_write_api => "1", :allow_read_gpx => "1" }
assert_redirected_to "#{callback_url}?oauth_token=#{token.token}"
token.reload
assert_not_nil token.created_at
assert_not_nil token.authorized_at
assert_nil token.invalidated_at
assert_allowed token, [:allow_write_api, :allow_read_gpx]
signed_get "/oauth/access_token", :oauth => { :token => token }
assert_response :success
token.reload
assert_not_nil token.created_at
assert_not_nil token.authorized_at
assert_not_nil token.invalidated_at
token = parse_token(response)
assert_instance_of AccessToken, token
assert_not_nil token.created_at
assert_not_nil token.authorized_at
assert_nil token.invalidated_at
assert_allowed token, [:allow_write_api, :allow_read_gpx]
post logout_path
trace = create(:trace, :user => token.user)
signed_get "/api/0.6/gpx/#{trace.id}", :oauth => { :token => token }
assert_response :success
signed_get "/api/0.6/user/details", :oauth => { :token => token }
assert_response :forbidden
token.user.suspend!
signed_get "/api/0.6/gpx/#{trace.id}", :oauth => { :token => token }
assert_response :forbidden
token.user.hide!
signed_get "/api/0.6/gpx/#{trace.id}", :oauth => { :token => token }
assert_response :forbidden
token.user.unhide!
signed_get "/api/0.6/gpx/#{trace.id}", :oauth => { :token => token }
assert_response :success
session_for(token.user)
post "/oauth/revoke", :params => { :token => token.token }
assert_redirected_to oauth_clients_url(token.user.display_name)
token = OauthToken.find_by(:token => token.token)
assert_not_nil token.invalidated_at
signed_get "/api/0.6/gpx/2", :oauth => { :token => token }
assert_response :unauthorized
end
def oauth10a_without_callback(client)
token = get_request_token(client, :oauth_callback => "oob")
get "/oauth/authorize", :params => { :oauth_token => token.token }
assert_response :success
assert_template :authorize
post "/oauth/authorize",
:params => { :oauth_token => token.token,
:allow_read_prefs => "1", :allow_write_prefs => "1" }
if client.callback_url
assert_response :redirect
verifier = parse_verifier(response)
assert_redirected_to "http://some.web.app.example.org/callback?oauth_token=#{token.token}&oauth_verifier=#{verifier}"
else
assert_response :success
assert_template :authorize_success
m = response.body.match("<p>The verification code is ([A-Za-z0-9]+).</p>")
assert_not_nil m
verifier = m[1]
end
token.reload
assert_not_nil token.created_at
assert_not_nil token.authorized_at
assert_nil token.invalidated_at
assert_allowed token, [:allow_read_prefs]
signed_get "/oauth/access_token", :oauth => { :token => token }
assert_response :unauthorized
signed_get "/oauth/access_token", :oauth => { :token => token, :oauth_verifier => verifier }
assert_response :success
token.reload
assert_not_nil token.created_at
assert_not_nil token.authorized_at
assert_not_nil token.invalidated_at
token = parse_token(response)
assert_instance_of AccessToken, token
assert_not_nil token.created_at
assert_not_nil token.authorized_at
assert_nil token.invalidated_at
assert_allowed token, [:allow_read_prefs]
post logout_path
signed_get "/api/0.6/user/preferences", :oauth => { :token => token }
assert_response :success
trace = create(:trace, :user => token.user)
signed_get "/api/0.6/gpx/#{trace.id}", :oauth => { :token => token }
assert_response :forbidden
token.user.suspend!
signed_get "/api/0.6/user/preferences", :oauth => { :token => token }
assert_response :forbidden
token.user.hide!
signed_get "/api/0.6/user/preferences", :oauth => { :token => token }
assert_response :forbidden
token.user.unhide!
signed_get "/api/0.6/user/preferences", :oauth => { :token => token }
assert_response :success
session_for(token.user)
post "/oauth/revoke", :params => { :token => token.token }
assert_redirected_to oauth_clients_url(token.user.display_name)
token = OauthToken.find_by(:token => token.token)
assert_not_nil token.invalidated_at
signed_get "/api/0.6/user/preferences", :oauth => { :token => token }
assert_response :unauthorized
end
def oauth10a_with_callback(client, callback_url)
token = get_request_token(client, :oauth_callback => callback_url)
get "/oauth/authorize", :params => { :oauth_token => token.token }
assert_response :success
assert_template :authorize
post "/oauth/authorize",
:params => { :oauth_token => token.token,
:allow_write_api => "1", :allow_read_gpx => "1" }
assert_response :redirect
verifier = parse_verifier(response)
assert_redirected_to "#{callback_url}?oauth_token=#{token.token}&oauth_verifier=#{verifier}"
token.reload
assert_not_nil token.created_at
assert_not_nil token.authorized_at
assert_nil token.invalidated_at
assert_allowed token, [:allow_write_api, :allow_read_gpx]
signed_get "/oauth/access_token", :oauth => { :token => token }
assert_response :unauthorized
signed_get "/oauth/access_token", :oauth => { :token => token, :oauth_verifier => verifier }
assert_response :success
token.reload
assert_not_nil token.created_at
assert_not_nil token.authorized_at
assert_not_nil token.invalidated_at
token = parse_token(response)
assert_instance_of AccessToken, token
assert_not_nil token.created_at
assert_not_nil token.authorized_at
assert_nil token.invalidated_at
assert_allowed token, [:allow_write_api, :allow_read_gpx]
post logout_path
trace = create(:trace, :user => token.user)
signed_get "/api/0.6/gpx/#{trace.id}", :oauth => { :token => token }
assert_response :success
signed_get "/api/0.6/user/details", :oauth => { :token => token }
assert_response :forbidden
token.user.suspend!
signed_get "/api/0.6/gpx/#{trace.id}", :oauth => { :token => token }
assert_response :forbidden
token.user.hide!
signed_get "/api/0.6/gpx/#{trace.id}", :oauth => { :token => token }
assert_response :forbidden
token.user.unhide!
signed_get "/api/0.6/gpx/#{trace.id}", :oauth => { :token => token }
assert_response :success
session_for(token.user)
post "/oauth/revoke", :params => { :token => token.token }
assert_redirected_to oauth_clients_url(token.user.display_name)
token = OauthToken.find_by(:token => token.token)
assert_not_nil token.invalidated_at
signed_get "/api/0.6/gpx/2", :oauth => { :token => token }
assert_response :unauthorized
end
def oauth10a_refused(client)
token = get_request_token(client, :oauth_callback => "oob")
get "/oauth/authorize", :params => { :oauth_token => token.token }
assert_response :success
assert_template :authorize
post "/oauth/authorize", :params => { :oauth_token => token.token }
assert_response :success
assert_template :authorize_failure
assert_select "p", "You have denied application #{client.name} access to your account."
token.reload
assert_nil token.authorized_at
assert_not_nil token.invalidated_at
get "/oauth/authorize", :params => { :oauth_token => token.token }
assert_response :success
assert_template :authorize_failure
assert_select "p", "The authorization token is not valid."
token.reload
assert_nil token.authorized_at
assert_not_nil token.invalidated_at
post "/oauth/authorize", :params => { :oauth_token => token.token }
assert_response :success
assert_template :authorize_failure
assert_select "p", "The authorization token is not valid."
token.reload
assert_nil token.authorized_at
assert_not_nil token.invalidated_at
end
def get_request_token(client, options = {})
signed_get "/oauth/request_token", :oauth => options.merge(:consumer => client)
assert_response :success
token = parse_token(response)
assert_instance_of RequestToken, token
assert_not_nil token.created_at
assert_nil token.authorized_at
assert_nil token.invalidated_at
assert_equal_allowing_nil options[:oauth_callback], token.callback_url
assert_allowed token, client.permissions
token
end
def parse_token(response)
params = CGI.parse(response.body)
token = OauthToken.find_by(:token => params["oauth_token"].first)
assert_equal token.secret, params["oauth_token_secret"].first
token
end
def parse_verifier(response)
params = CGI.parse(URI.parse(response.location).query)
assert_not_nil params["oauth_verifier"]
assert_predicate params["oauth_verifier"].first, :present?
params["oauth_verifier"].first
end
def assert_allowed(token, allowed)
ClientApplication.all_permissions.each do |p|
assert_equal allowed.include?(p), token.attributes[p.to_s]
end
end
end

View file

@ -1,54 +0,0 @@
require "test_helper"
class ClientApplicationTest < ActiveSupport::TestCase
def test_url_valid
ok = ["http://example.com/test", "https://example.com/test"]
bad = ["", "ftp://example.com/test", "myapp://somewhere", "http://example.com\nhttp://example.net"]
ok.each do |url|
app = build(:client_application)
app.url = url
assert_predicate app, :valid?, "#{url} is invalid, when it should be"
end
bad.each do |url|
app = build(:client_application)
app.url = url
assert_not_predicate app, :valid?, "#{url} is valid when it shouldn't be"
end
end
def test_support_url_valid
ok = ["", "http://example.com/test", "https://example.com/test"]
bad = ["ftp://example.com/test", "myapp://somewhere", "gibberish", "http://example.com\nhttp://example.net"]
ok.each do |url|
app = build(:client_application)
app.support_url = url
assert_predicate app, :valid?, "#{url} is invalid, when it should be"
end
bad.each do |url|
app = build(:client_application)
app.support_url = url
assert_not_predicate app, :valid?, "#{url} is valid when it shouldn't be"
end
end
def test_callback_url_valid
ok = ["", "http://example.com/test", "https://example.com/test", "ftp://example.com/test", "myapp://somewhere"]
bad = ["gibberish", "http://example.com\nhttp://example.net"]
ok.each do |url|
app = build(:client_application)
app.callback_url = url
assert_predicate app, :valid?, "#{url} is invalid, when it should be"
end
bad.each do |url|
app = build(:client_application)
app.callback_url = url
assert_not_predicate app, :valid?, "#{url} is valid when it shouldn't be"
end
end
end

View file

@ -1,29 +0,0 @@
require "test_helper"
class OauthNonceTest < ActiveSupport::TestCase
##
# the nonce has only one property, that it is a unique pair of
# string and timestamp.
def test_nonce_uniqueness
string = "0123456789ABCDEF"
timestamp = Time.now.to_i
nonce1 = OauthNonce.remember(string, timestamp)
assert_not_equal false, nonce1, "First nonce should be unique. Check your test database is empty."
nonce2 = OauthNonce.remember(string, timestamp)
assert_not nonce2, "Shouldn't be able to remember the same nonce twice."
end
##
# nonces that are not current should be rejected
def test_nonce_not_current
string = "0123456789ABCDEF"
nonce1 = OauthNonce.remember(string, Time.now.to_i - 86430)
assert_not nonce1, "Nonces over a day in the past should be rejected"
nonce2 = OauthNonce.remember(string, Time.now.to_i - 86370)
assert_not_equal false, nonce2, "Nonces under a day in the past should be rejected"
end
end

View file

@ -1,23 +0,0 @@
require "test_helper"
class OauthTokenTest < ActiveSupport::TestCase
##
# check that after calling invalidate! on a token, it is invalid.
def test_token_invalidation
tok = OauthToken.new
assert_not_predicate tok, :invalidated?, "Token should be created valid."
tok.invalidate!
assert_predicate tok, :invalidated?, "Token should now be invalid."
end
##
# check that an authorized token is authorised and can be invalidated
def test_token_authorisation
tok = RequestToken.create(:client_application => create(:client_application))
assert_not_predicate tok, :authorized?, "Token should be created unauthorised."
tok.authorize!(create(:user))
assert_predicate tok, :authorized?, "Token should now be authorised."
tok.invalidate!
assert_not_predicate tok, :authorized?, "Token should now be invalid."
end
end

View file

@ -1,10 +0,0 @@
require "test_helper"
class RequestTokenTest < ActiveSupport::TestCase
def test_oob
assert_predicate RequestToken.new, :oob?
assert_predicate RequestToken.new(:callback_url => "oob"), :oob?
assert_predicate RequestToken.new(:callback_url => "OOB"), :oob?
assert_not_predicate RequestToken.new(:callback_url => "http://test.host/"), :oob?
end
end

View file

@ -304,18 +304,6 @@ class UserTest < ActiveSupport::TestCase
assert_not_predicate user, :active? assert_not_predicate user, :active?
end end
def test_soft_destroy_revokes_oauth1_tokens
user = create(:user)
access_token = create(:access_token, :user => user)
assert_equal 1, user.oauth_tokens.authorized.count
user.soft_destroy
assert_equal 0, user.oauth_tokens.authorized.count
access_token.reload
assert_predicate access_token, :invalidated?
end
def test_soft_destroy_revokes_oauth2_tokens def test_soft_destroy_revokes_oauth2_tokens
user = create(:user) user = create(:user)
oauth_access_token = create(:oauth_access_token, :resource_owner_id => user.id) oauth_access_token = create(:oauth_access_token, :resource_owner_id => user.id)

View file

@ -145,43 +145,6 @@ module ActiveSupport
{ "Authorization" => "Bearer #{token}" } { "Authorization" => "Bearer #{token}" }
end end
##
# make an OAuth signed request
def signed_request(method, uri, options = {})
uri = URI.parse(uri)
uri.scheme ||= "http"
uri.host ||= "www.example.com"
oauth = options.delete(:oauth)
params = options.fetch(:params, {}).transform_keys(&:to_s)
oauth[:consumer] ||= oauth[:token].client_application
helper = OAuth::Client::Helper.new(nil, oauth)
request = OAuth::RequestProxy.proxy(
"method" => method.to_s.upcase,
"uri" => uri,
"parameters" => params.merge(helper.oauth_parameters)
)
request.sign!(oauth)
method(method).call(request.signed_uri, **options)
end
##
# make an OAuth signed GET request
def signed_get(uri, options = {})
signed_request(:get, uri, options)
end
##
# make an OAuth signed POST request
def signed_post(uri, options = {})
signed_request(:post, uri, options)
end
## ##
# return request header for HTTP Accept # return request header for HTTP Accept
def accept_format_header(format) def accept_format_header(format)