Only allow primary domain for RS

Replace user addresses with usernames in the respective URLs
This commit is contained in:
Râu Cao 2023-11-01 21:46:38 +01:00
parent 5075fef616
commit 56c127ca0c
Signed by: raucao
GPG Key ID: 15E65F399D084BA9
7 changed files with 65 additions and 43 deletions

View File

@ -3,8 +3,7 @@ class Rs::OauthController < ApplicationController
before_action :authenticate_user!, only: :create before_action :authenticate_user!, only: :create
def new def new
username, org = params[:useraddress].split("@") @user = User.where(cn: params[:username].downcase, ou: Setting.primary_domain).first
@user = User.where(cn: username.downcase, ou: org).first
@scopes = parse_scopes params[:scope] @scopes = parse_scopes params[:scope]
@redirect_uri = params[:redirect_uri] @redirect_uri = params[:redirect_uri]
@client_id = params[:client_id] @client_id = params[:client_id]
@ -22,7 +21,7 @@ class Rs::OauthController < ApplicationController
unless current_user == @user unless current_user == @user
sign_out :user sign_out :user
redirect_to new_rs_oauth_url(@user.address, redirect_to new_rs_oauth_url(@user.cn,
scope: params[:scope], scope: params[:scope],
redirect_uri: params[:redirect_uri], redirect_uri: params[:redirect_uri],
client_id: params[:client_id], client_id: params[:client_id],
@ -107,9 +106,8 @@ class Rs::OauthController < ApplicationController
def require_signed_in_with_username def require_signed_in_with_username
unless user_signed_in? unless user_signed_in?
username, org = params[:useraddress].split("@")
session[:user_return_to] = request.url session[:user_return_to] = request.url
redirect_to new_user_session_path(cn: username, ou: org) redirect_to new_user_session_path(cn: params[:username], ou: Setting.primary_domain)
end end
end end

View File

@ -6,15 +6,19 @@ class WebfingerController < ApplicationController
def show def show
resource = params[:resource] resource = params[:resource]
if resource && resource.match(/acct:\w+/) if resource && @useraddress = resource.match(/acct:(.+)/)&.[](1)
useraddress = resource.split(":").last @username, @org = @useraddress.split("@")
username, org = useraddress.split("@")
username.downcase! unless Rails.env.development?
unless User.where(cn: username, ou: org).any? # Allow different domains (e.g. localhost:3000) in development only
head 404 and return unless @org == Setting.primary_domain
end
unless User.where(cn: @username.downcase, ou: Setting.primary_domain).any?
head 404 and return head 404 and return
end end
render json: webfinger(useraddress).to_json, render json: webfinger.to_json,
content_type: "application/jrd+json" content_type: "application/jrd+json"
else else
head 422 and return head 422 and return
@ -23,19 +27,18 @@ class WebfingerController < ApplicationController
private private
def webfinger(useraddress) def webfinger
links = []; links = [];
links << remotestorage_link(useraddress) if Setting.remotestorage_enabled # TODO check if storage service is enabled for user, not just globally
links << remotestorage_link if Setting.remotestorage_enabled
{ "links" => links } { "links" => links }
end end
def remotestorage_link(useraddress) def remotestorage_link
# TODO use when OAuth routes are available auth_url = new_rs_oauth_url("#{@username}@#{Setting.primary_domain}")
# auth_url = new_rs_oauth_url(useraddress) storage_url = "#{Setting.rs_storage_url}/#{@username}"
auth_url = "https://example.com/rs/oauth"
storage_url = "#{Setting.rs_storage_url}/#{useraddress}"
{ {
"rel" => "http://tools.ietf.org/id/draft-dejong-remotestorage", "rel" => "http://tools.ietf.org/id/draft-dejong-remotestorage",

View File

@ -78,8 +78,8 @@ Rails.application.routes.draw do
namespace :rs do namespace :rs do
resource :oauth, only: [:new, :create], path_names: { resource :oauth, only: [:new, :create], path_names: {
new: ':useraddress', create: ':useraddress' new: ':username', create: ':username'
}, controller: 'oauth', constraints: { useraddress: /[^\/]+/} }, controller: 'oauth'
get 'oauth/token/:id/launch_app' => 'oauth#launch_app', as: :launch_app get 'oauth/token/:id/launch_app' => 'oauth#launch_app', as: :launch_app
end end

View File

@ -69,6 +69,23 @@ services:
- ldap - ldap
- redis - redis
liquor-cabinet:
image: gitea.kosmos.org/5apps/liquor-cabinet:latest
networks:
- external_network
- internal_network
ports:
- "4567:4567"
environment:
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_DB: 2
S3_ENDPOINT: https://garage
S3_REGION: garage
S3_ACCESS_KEY:
S3_SECRET_KEY:
S3_BUCKET:
# phpldapadmin: # phpldapadmin:
# image: osixia/phpldapadmin:0.9.0 # image: osixia/phpldapadmin:0.9.0
# ports: # ports:

View File

@ -3,7 +3,11 @@ require 'rails_helper'
RSpec.describe Rs::OauthController, type: :controller do RSpec.describe Rs::OauthController, type: :controller do
let(:user) { create :user } let(:user) { create :user }
describe "GET /rs/oauth/:useraddress" do before do
allow_any_instance_of(AppCatalog::WebApp).to receive(:update_metadata).and_return(true)
end
describe "GET /rs/oauth/:username" do
context "when user is signed in" do context "when user is signed in" do
before do before do
sign_in user sign_in user
@ -14,7 +18,7 @@ RSpec.describe Rs::OauthController, type: :controller do
before do before do
get :new, params: { get :new, params: {
useraddress: other_user.address, username: other_user.cn,
redirect_uri: "https://example.com", redirect_uri: "https://example.com",
client_id: "example.com", client_id: "example.com",
scope: "examples" scope: "examples"
@ -22,7 +26,7 @@ RSpec.describe Rs::OauthController, type: :controller do
end end
it "logs out the users and repeats the request" do it "logs out the users and repeats the request" do
url = new_rs_oauth_url other_user.address, url = new_rs_oauth_url other_user.cn,
redirect_uri: "https://example.com", redirect_uri: "https://example.com",
client_id: "example.com", client_id: "example.com",
scope: "examples" scope: "examples"
@ -34,7 +38,7 @@ RSpec.describe Rs::OauthController, type: :controller do
context "when no valid token exists" do context "when no valid token exists" do
before do before do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
redirect_uri: "https://example.com", redirect_uri: "https://example.com",
client_id: "example.com", client_id: "example.com",
scope: "documents,[photos], contacts:rw videos:r tasks/work/:r", scope: "documents,[photos], contacts:rw videos:r tasks/work/:r",
@ -61,7 +65,7 @@ RSpec.describe Rs::OauthController, type: :controller do
context "no redirect_uri" do context "no redirect_uri" do
before do before do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
scope: "documents,[photos], contacts:rw videos:r tasks/work/:r", scope: "documents,[photos], contacts:rw videos:r tasks/work/:r",
client_id: "https://example.com" client_id: "https://example.com"
} }
@ -75,7 +79,7 @@ RSpec.describe Rs::OauthController, type: :controller do
context "no client_id" do context "no client_id" do
before do before do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
scope: "documents,[photos], contacts:rw videos:r tasks/work/:r", scope: "documents,[photos], contacts:rw videos:r tasks/work/:r",
redirect_uri: "https://example.com" redirect_uri: "https://example.com"
} }
@ -89,7 +93,7 @@ RSpec.describe Rs::OauthController, type: :controller do
context "different host for client_id and redirect_uri" do context "different host for client_id and redirect_uri" do
before do before do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
scope: "documents,[photos], contacts:rw videos:r tasks/work/:r", scope: "documents,[photos], contacts:rw videos:r tasks/work/:r",
redirect_uri: "https://example.com/foobar", redirect_uri: "https://example.com/foobar",
client_id: "https://google.com" client_id: "https://google.com"
@ -116,7 +120,7 @@ RSpec.describe Rs::OauthController, type: :controller do
context "with same host for client_id and redirect_uri" do context "with same host for client_id and redirect_uri" do
before do before do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
scope: "documents,[photos], contacts:rw videos:r tasks/work/:r", scope: "documents,[photos], contacts:rw videos:r tasks/work/:r",
redirect_uri: "https://example.com", redirect_uri: "https://example.com",
client_id: "https://example.com" client_id: "https://example.com"
@ -131,7 +135,7 @@ RSpec.describe Rs::OauthController, type: :controller do
context "with different host for client_id and redirect_uri" do context "with different host for client_id and redirect_uri" do
before do before do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
scope: "documents,[photos], contacts:rw videos:r tasks/work/:r", scope: "documents,[photos], contacts:rw videos:r tasks/work/:r",
redirect_uri: "https://app.example.com", redirect_uri: "https://app.example.com",
client_id: "https://example.com" client_id: "https://example.com"
@ -146,7 +150,7 @@ RSpec.describe Rs::OauthController, type: :controller do
context "with different redirect_uri" do context "with different redirect_uri" do
before do before do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
scope: "documents,[photos], contacts:rw videos:r tasks/work/:r", scope: "documents,[photos], contacts:rw videos:r tasks/work/:r",
redirect_uri: "https://example.com/a_new_route", redirect_uri: "https://example.com/a_new_route",
client_id: "https://example.com" client_id: "https://example.com"
@ -161,7 +165,7 @@ RSpec.describe Rs::OauthController, type: :controller do
context "with state param given" do context "with state param given" do
before do before do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
scope: "documents,[photos], contacts:rw videos:r tasks/work/:r", scope: "documents,[photos], contacts:rw videos:r tasks/work/:r",
redirect_uri: "https://example.com", redirect_uri: "https://example.com",
client_id: "https://example.com", client_id: "https://example.com",
@ -178,7 +182,7 @@ RSpec.describe Rs::OauthController, type: :controller do
context "no scope" do context "no scope" do
before do before do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
redirect_uri: "https://example.com", redirect_uri: "https://example.com",
client_id: "https://example.com", client_id: "https://example.com",
state: "foobar123" state: "foobar123"
@ -193,7 +197,7 @@ RSpec.describe Rs::OauthController, type: :controller do
context "empty scope" do context "empty scope" do
before do before do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
scope: "", scope: "",
redirect_uri: "https://example.com", redirect_uri: "https://example.com",
client_id: "https://example.com", client_id: "https://example.com",
@ -210,7 +214,7 @@ RSpec.describe Rs::OauthController, type: :controller do
context "when user is not signed in" do context "when user is not signed in" do
it "redirects to the signin page with username pre-filled" do it "redirects to the signin page with username pre-filled" do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
scope: "documents,photos", scope: "documents,photos",
redirect_uri: "https://example.com" redirect_uri: "https://example.com"
} }
@ -227,7 +231,7 @@ RSpec.describe Rs::OauthController, type: :controller do
describe "full" do describe "full" do
before do before do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
scope: "*:rw", scope: "*:rw",
redirect_uri: "https://example.com", redirect_uri: "https://example.com",
client_id: "example.com" client_id: "example.com"
@ -243,7 +247,7 @@ RSpec.describe Rs::OauthController, type: :controller do
describe "read-only" do describe "read-only" do
before do before do
get :new, params: { get :new, params: {
useraddress: user.address, username: user.cn,
scope: "*:r", scope: "*:r",
redirect_uri: "https://example.com", redirect_uri: "https://example.com",
client_id: "example.com" client_id: "example.com"
@ -258,7 +262,7 @@ RSpec.describe Rs::OauthController, type: :controller do
end end
end end
describe "POST /rs/oauth/:useraddress" do describe "POST /rs/oauth/:username" do
context "when user is signed in" do context "when user is signed in" do
before do before do
sign_in user sign_in user

View File

@ -10,7 +10,7 @@ RSpec.describe 'remoteStorage OAuth Dialog', type: :feature do
context "with normal permissions" do context "with normal permissions" do
before do before do
visit new_rs_oauth_path(useraddress: user.address, visit new_rs_oauth_path(username: user.cn,
redirect_uri: "http://example.com", redirect_uri: "http://example.com",
client_id: "http://example.com", client_id: "http://example.com",
scope: "documents,[photos], contacts:r") scope: "documents,[photos], contacts:r")
@ -36,7 +36,7 @@ RSpec.describe 'remoteStorage OAuth Dialog', type: :feature do
context "root access" do context "root access" do
context "full" do context "full" do
before do before do
visit new_rs_oauth_path(useraddress: user.address, visit new_rs_oauth_path(username: user.cn,
redirect_uri: "http://example.com", redirect_uri: "http://example.com",
client_id: "http://example.com", client_id: "http://example.com",
scope: ":rw") scope: ":rw")
@ -60,7 +60,7 @@ RSpec.describe 'remoteStorage OAuth Dialog', type: :feature do
end end
it "prefills the username field in the signin form" do it "prefills the username field in the signin form" do
visit new_rs_oauth_path(useraddress: user.address, visit new_rs_oauth_path(username: user.cn,
redirect_uri: "http://example.com", redirect_uri: "http://example.com",
client_id: "http://example.com", client_id: "http://example.com",
scope: "documents,[photos], contacts:r") scope: "documents,[photos], contacts:r")
@ -69,7 +69,7 @@ RSpec.describe 'remoteStorage OAuth Dialog', type: :feature do
end end
it "redirects to the OAuth dialog after sign-in" do it "redirects to the OAuth dialog after sign-in" do
auth_url = new_rs_oauth_url(useraddress: user.address, auth_url = new_rs_oauth_url(username: user.cn,
redirect_uri: "http://example.com", redirect_uri: "http://example.com",
client_id: "http://example.com", client_id: "http://example.com",
scope: "documents,[photos], contacts:r") scope: "documents,[photos], contacts:r")

View File

@ -15,10 +15,10 @@ RSpec.describe "WebFinger", type: :request do
res = JSON.parse(response.body) res = JSON.parse(response.body)
rs_link = res["links"].find {|l| l["rel"] == "http://tools.ietf.org/id/draft-dejong-remotestorage"} rs_link = res["links"].find {|l| l["rel"] == "http://tools.ietf.org/id/draft-dejong-remotestorage"}
expect(rs_link["href"]).to eql("https://storage.kosmos.org/tony@kosmos.org") expect(rs_link["href"]).to eql("https://storage.kosmos.org/tony")
oauth_url = rs_link["properties"]["http://tools.ietf.org/html/rfc6749#section-4.2"] oauth_url = rs_link["properties"]["http://tools.ietf.org/html/rfc6749#section-4.2"]
expect(oauth_url).to eql("https://example.com/rs/oauth") expect(oauth_url).to eql("http://www.example.com/rs/oauth/tony@kosmos.org")
end end
end end