Commit 4896fc7

mo <mo@mokhan.ca>
2018-10-20 17:20:44
update client validations to support dynamic client registrations params
1 parent 5128a88
Changed files (4)
app
spec
app/controllers/clients_controller.rb
@@ -7,7 +7,7 @@ class ClientsController < ApplicationController
     render status: :created, formats: :json
   rescue ActiveRecord::RecordInvalid => error
     json = {
-      error: :invalid_redirect_uri,
+      error: error.record.errors[:redirect_uris].present? ? :invalid_redirect_uri : :invalid_client_metadata,
       error_description: error.record.errors.full_messages.join(' ')
     }
     render json: json, status: :bad_request
app/models/client.rb
@@ -8,11 +8,15 @@ class Client < ApplicationRecord
   attribute :redirect_uris, :string, array: true
   enum token_endpoint_auth_method: { client_secret_none: 0, client_secret_post: 1, client_secret_basic: 2 }
 
-  validates :redirect_uris, presence: true, format: { with: URI_REGEX }
-  validates :jwks_uri, format: { with: URI_REGEX }
-  validates :logo_uri, format: { with: URI_REGEX }
+  validates :redirect_uris, presence: true#, format: { with: URI_REGEX }
+  validates :jwks_uri, format: { with: URI_REGEX }, allow_blank: true
+  validates :logo_uri, format: { with: URI_REGEX }, allow_blank: true
   validates :name, presence: true
   validates :uuid, presence: true, format: { with: UUID }
+  validates_each :redirect_uris do |record, attr, value|
+    invalid_uri = Array(value).find { |x| !x.match?(URI_REGEX) }
+    record.errors[:redirect_uris] << 'is invalid.' if invalid_uri
+  end
 
   after_initialize do
     self.uuid = SecureRandom.uuid unless uuid
@@ -37,7 +41,7 @@ class Client < ApplicationRecord
   end
 
   def valid_redirect_uri?(redirect_uri)
-    self.redirect_uri == redirect_uri
+    self.redirect_uris.include? redirect_uri
   end
 
   def valid_response_type?(response_type)
@@ -72,7 +76,7 @@ class Client < ApplicationRecord
 
   def redirect_url(fragments = {})
     URI.parse(
-      "#{redirect_uri}#" + fragments.map do |(key, value)|
+      "#{redirect_uris[0]}#" + fragments.map do |(key, value)|
         "#{key}=#{value}" if value.present?
       end.compact.join("&")
     ).to_s
spec/factories/client.rb
@@ -4,6 +4,6 @@ FactoryBot.define do
   factory :client do
     uuid { SecureRandom.uuid }
     name { FFaker::Name.name }
-    redirect_uri { FFaker::Internet.uri('https') }
+    redirect_uris { [FFaker::Internet.uri('https')] }
   end
 end
spec/models/client_spec.rb
@@ -5,9 +5,11 @@ require 'rails_helper'
 RSpec.describe Client do
   describe "#validation" do
     specify { expect(build(:client)).to be_valid }
-    specify { expect(build(:client, redirect_uri: nil)).to be_invalid }
-    specify { expect(build(:client, redirect_uri: '<script>alert("hi")</script>')).to be_invalid }
-    specify { expect(build(:client, redirect_uri: 'invalid')).to be_invalid }
+    specify { expect(build(:client, redirect_uris: nil)).to be_invalid }
+    specify { expect(build(:client, redirect_uris: [])).to be_invalid }
+    specify { expect(build(:client, redirect_uris: ['<script>alert("hi")</script>'])).to be_invalid }
+    specify { expect(build(:client, redirect_uris: ['invalid'])).to be_invalid }
+    specify { expect(build(:client, redirect_uris: 'invalid')).to be_invalid }
     specify { expect(build(:client, uuid: nil)).to be_invalid }
     specify { expect(build(:client, uuid: 'invalid')).to be_invalid }
     specify { expect(build(:client, name: nil)).to be_invalid }
@@ -17,7 +19,7 @@ RSpec.describe Client do
     subject { build(:client) }
 
     let(:code) { SecureRandom.uuid }
-    let(:redirect_uri) { subject.redirect_uri }
+    let(:redirect_uri) { subject.redirect_uris[0] }
 
     specify { expect(subject.redirect_url(code: code)).to eql("#{redirect_uri}#code=#{code}") }
     specify { expect { subject.redirect_url(state: '<script>alert("hi");</script>') }.to raise_error(URI::InvalidURIError) }