class Rs::OauthController < ApplicationController before_action :require_signed_in_with_username, only: :new before_action :authenticate_user!, only: :create def new @user = User.where(cn: params[:username].downcase, ou: Setting.primary_domain).first @scopes = parse_scopes params[:scope] @redirect_uri = params[:redirect_uri] @client_id = params[:client_id] @state = params[:state] @root_access_requested = (@scopes & [":r",":rw"]).any? @denial_url = url_with_state("#{@redirect_uri}#error=access_denied", @state) @expire_at_dates = [["Never", nil], ["In 1 month", 1.month.from_now], ["In 1 day", 1.day.from_now]] http_status :bad_request and return unless @redirect_uri.present? unless current_user == @user sign_out :user redirect_to new_rs_oauth_url(@user.cn, scope: params[:scope], redirect_uri: params[:redirect_uri], client_id: params[:client_id], state: params[:state]) return end unless @client_id.present? redirect_to(url_with_state("#{@redirect_uri}#error=invalid_request", @state), allow_other_host: true) and return end if @scopes.empty? redirect_to(url_with_state("#{@redirect_uri}#error=invalid_scope", @state), allow_other_host: true) and return end unless hostname_of(@client_id) == hostname_of(@redirect_uri) redirect_to(url_with_state("#{@redirect_uri}#error=invalid_client", @state), allow_other_host: true) and return end @client_id.gsub!(/http(s)?:\/\//, "") if auth = current_user.remote_storage_authorizations.valid.where(permissions: @scopes, client_id: @client_id).first redirect_to(url_with_state("#{@redirect_uri}#access_token=#{auth.token}", @state), allow_other_host: true) and return end end def create unless current_user.id.to_s == params[:user_id] Rails.logger.info("NO MATCH: #{params[:user_id]}, #{current_user.id}") http_status :forbidden and return end permissions = parse_scopes params[:scope] redirect_uri = params[:redirect_uri].presence client_id = params[:client_id].presence state = params[:state].presence expire_at = params[:expire_at].presence http_status :bad_request and return unless redirect_uri.present? if permissions.empty? redirect_to(url_with_state("#{redirect_uri}#error=invalid_scope", state), allow_other_host: true) and return end unless client_id.present? redirect_to(url_with_state("#{redirect_uri}#error=invalid_request", state), allow_other_host: true) and return end unless hostname_of(client_id) == hostname_of(redirect_uri) redirect_to(url_with_state("#{redirect_uri}#error=invalid_client", state), allow_other_host: true) and return end client_id.gsub!(/http(s)?:\/\//, "") auth = current_user.remote_storage_authorizations.create!( permissions: permissions, client_id: client_id, redirect_uri: redirect_uri, app_name: client_id, expire_at: expire_at ) redirect_to url_with_state("#{redirect_uri}#access_token=#{auth.token}", state), allow_other_host: true end private def require_signed_in_with_username unless user_signed_in? session[:user_return_to] = request.url redirect_to new_user_session_path(cn: params[:username], ou: Setting.primary_domain) end end def hostname_of(uri) uri.gsub(/http(s)?:\/\//, "").split(":")[0].split("/")[0] end def parse_scopes(scope_string) return [] if scope_string.blank? scopes = scope_string. gsub(/\[|\]/, ""). gsub(/\,/, " "). gsub(/\/:/, ":"). split(/\s/).map(&:strip). reject(&:empty?) scopes = [":r"] if scopes.include?("*:r") scopes = [":rw"] if scopes.include?("*:rw") scopes end def url_with_state(url, state) state ? "#{url}&state=#{CGI.escape(state)}" : url end end