Files
akkounts/spec/features/rs/oauth_spec.rb
T
raucao 295261b332
CI / Test (pull_request) Failing after 46s
Address review findings in the PKCE flow
- Make authorization-code redemption atomic: claim the code with a guarded
  delete inside the transaction that creates the authorization, so concurrent
  exchanges can't both issue a token (RFC 6749 4.1.3)
- Compare the token request's client_id host to the code's stored client_id
  (defense-in-depth alongside the exact redirect_uri match)
- Reject unknown response_type values with unsupported_response_type
- Validate the PKCE code_challenge (43-128 unreserved chars, S256) so a client
  can't persist an over-long or malformed challenge
- Return invalid_request for missing token-endpoint parameters, and set
  Cache-Control: no-store on error responses too
- Use the right separator when the redirect_uri already has a query string
- Look codes up through the active scope; drop the unused consume!; serialize
  permissions as JSON
- Purge abandoned authorization codes via a recurring Solid Queue task

Part of #254
2026-11-03 11:40:18 +04:00

104 lines
3.5 KiB
Ruby

require 'rails_helper'
RSpec.describe 'remoteStorage OAuth Dialog', type: :feature do
context "when signed in" do
let(:user) { create :user }
before do
login_as user, :scope => :user
end
context "with normal permissions" do
before do
visit new_rs_oauth_path(username: user.cn,
redirect_uri: "http://example.com",
client_id: "http://example.com",
scope: "documents,[photos], contacts:r")
end
it "shows the permissions in a list" do
within ".permissions" do
expect(page).to have_content("documents")
expect(page).to have_content("photos")
expect(page).to have_content("contacts")
end
within ".scope:first-of-type" do
expect(page).not_to have_content("read only")
end
within ".scope:last-of-type" do
expect(page).to have_content("read only")
end
end
end
context "root access" do
context "full" do
before do
visit new_rs_oauth_path(username: user.cn,
redirect_uri: "http://example.com",
client_id: "http://example.com",
scope: ":rw")
end
it "shows a special permission for all files and dirs" do
within ".scope" do
expect(page).to have_content("All files and directories")
end
end
end
end
context "with PKCE parameters" do
before do
visit new_rs_oauth_path(username: user.cn,
redirect_uri: "http://example.com",
client_id: "http://example.com",
scope: "documents:rw",
response_type: "code",
code_challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
code_challenge_method: "S256")
end
it "includes the PKCE parameters in the consent form" do
expect(page).to have_selector("input[name='response_type'][value='code']", visible: false)
expect(page).to have_selector("input[name='code_challenge'][value='E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM']", visible: false)
expect(page).to have_selector("input[name='code_challenge_method'][value='S256']", visible: false)
end
end
end
context "when signed out" do
let(:user) { create :user }
before do
allow_any_instance_of(User).to receive(:valid_ldap_authentication?)
.with(user.password).and_return(true)
end
it "prefills the username field in the signin form" do
visit new_rs_oauth_path(username: user.cn,
redirect_uri: "http://example.com",
client_id: "http://example.com",
scope: "documents,[photos], contacts:r")
expect(find("#user_cn").value).to eq(user.cn)
end
it "redirects to the OAuth dialog after sign-in" do
auth_url = new_rs_oauth_url(username: user.cn,
redirect_uri: "http://example.com",
client_id: "http://example.com",
scope: "documents,[photos], contacts:r")
visit auth_url
fill_in "User", with: user.cn
fill_in "Password", with: user.password
click_button "Log in"
expect(current_url).to eq(auth_url)
end
end
end