- Enqueue the expiry job and the "app connected" notification on after_commit instead of after_create, so they only fire once the (now transactional) code exchange commits - Enforce the PKCE code_challenge format (43-128 unreserved chars, S256) with model validations, not only at the controller - Drop the now-unused RsAuthorizationCode#expired? - Cover the client_id-vs-stored-client_id check Part of #254
This commit is contained in:
5 files changed
+51
-21
No files matched your search
@@ -3,17 +3,44 @@ require 'rails_helper'
|
||||
RSpec.describe RsAuthorizationCode, type: :model do
|
||||
let(:user) { create :user }
|
||||
|
||||
def build_code(**attrs)
|
||||
RsAuthorizationCode.create!(
|
||||
# Example value from RFC 7636, Appendix B
|
||||
let(:challenge) { "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM" }
|
||||
|
||||
def new_code(**attrs)
|
||||
RsAuthorizationCode.new(
|
||||
user: user,
|
||||
client_id: "example.com",
|
||||
redirect_uri: "https://example.com",
|
||||
permissions: %w(documents:rw),
|
||||
code_challenge: "challenge",
|
||||
code_challenge: challenge,
|
||||
**attrs
|
||||
)
|
||||
end
|
||||
|
||||
def build_code(**attrs)
|
||||
new_code(**attrs).tap(&:save!)
|
||||
end
|
||||
|
||||
describe "validations" do
|
||||
it "is valid with a well-formed S256 challenge" do
|
||||
expect(new_code).to be_valid
|
||||
end
|
||||
|
||||
it "rejects a challenge shorter than 43 characters" do
|
||||
expect(new_code(code_challenge: "short")).not_to be_valid
|
||||
end
|
||||
|
||||
it "rejects a challenge with invalid characters" do
|
||||
expect(new_code(code_challenge: "#{'a' * 42}!")).not_to be_valid
|
||||
end
|
||||
|
||||
it "rejects an unsupported challenge method" do
|
||||
code = new_code(code_challenge_method: "plain")
|
||||
expect(code).not_to be_valid
|
||||
expect(code.errors[:code_challenge_method]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
describe "#create" do
|
||||
it "generates a raw code and stores only its digest" do
|
||||
code = build_code
|
||||
@@ -49,14 +76,4 @@ RSpec.describe RsAuthorizationCode, type: :model do
|
||||
expect(RsAuthorizationCode.find_by_code(code.code)).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "#expired?" do
|
||||
it "is false before the expiry" do
|
||||
expect(build_code).not_to be_expired
|
||||
end
|
||||
|
||||
it "is true after the expiry" do
|
||||
expect(build_code(expires_at: 1.minute.ago)).to be_expired
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user