-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prior to this commit, we had not wired in the logic for authorization to controlled digital lending (CDL) assets. With this change, we're adding the logic for handling a user authenticating to access a work. The logic flow is as follows: An unauthenticated user goes to a CDL asset page. They are neither authorized nor authenticated, so we direct them to the new session route. There we capture we're the URL of the requested resource and send them on their way to authenticate. When we perform the handshake with OpenID, we provide (as scope and client design decision) the URL of the CDL asset. The OpenID provider authenticates and returns to the OmniAuth callback. We use the returned scope to then grant authorization to the CDL asset (and revoke any expired authorizations). Related to: - #633 - #647
- Loading branch information
Showing
10 changed files
with
268 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
## | ||
# OVERRIDE | ||
# This decorator splices into Devise to set the store URL for potential WorkAuthorization. | ||
module DeviseSessionDecorator | ||
## | ||
# OVERRIDE | ||
# | ||
# @see OmniAuth::Strategies::OpenIDConnectDecorator#requested_work_url | ||
# @see # https://github.com/scientist-softserv/palni-palci/issues/633 | ||
def new | ||
prepare_for_conditional_work_authorization! | ||
|
||
super | ||
end | ||
end | ||
|
||
Devise::SessionsController.prepend(WorkAuthorization::StoreUrlForScope) | ||
Devise::SessionsController.prepend(DeviseSessionDecorator) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<h1><%= t('.unauthorized') %></h1> | ||
<% if respond_to?(:curation_concern) && curation_concern %> | ||
<p><%= t('.is_private', type: curation_concern.human_readable_type.downcase ) %><p> | ||
<p><%= t('.id', id: curation_concern.id) %> | ||
<% else %> | ||
<p><%= t('.page_is_private') %><p> | ||
<p>You may need to <%= link_to "re-authorize to access this resource", '#' %>.<p> | ||
<% end %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
module OmniAuth | ||
module Strategies | ||
## | ||
# OVERRIDE to provide openid {#scope} based on the current session. | ||
# | ||
# @see https://github.com/scientist-softserv/palni-palci/issues/633 | ||
module OpenIDConnectDecorator | ||
## | ||
# In OmniAuth, the options are a tenant wide configuration. However, per | ||
# the client's controlled digitial lending (CDL) system, in the options we | ||
# use for authentication we must inclue the URL of the work that the | ||
# authenticating user wants to access. | ||
# | ||
# @note In testing, when the scope did not include the sample noted in the | ||
# {#requested_work_url} method, the openid provider would return the | ||
# status 200 (e.g. Success) and a body "Failed to get response from | ||
# patron API" | ||
# | ||
# @return [Hash<Symbol,Object>] | ||
def options | ||
# If we don't include this, we keep adding to the `options[:scope]` | ||
return @decorated_options if defined? @decorated_options | ||
|
||
# TODO: What if we are not in the reshare tenant but the tenant is using | ||
# OpenID for authentication? | ||
opts = super | ||
|
||
url = requested_work_url | ||
opts[:scope] += [url] if url.present? && !opts[:scope].include?(url) | ||
|
||
Rails.logger.info("=@=@=@=@ #{self.class}#options scope value is #{opts[:scope].inspect}") | ||
|
||
@decorated_options = opts | ||
end | ||
|
||
## | ||
# @return [String] The URL of the work that was requested by the | ||
# authenticating user. | ||
# | ||
# @note {#session} method is `@env['rack.session']` | ||
# @note {#env} method is the hash representation of the Rack environment. | ||
# @note {#request} method is the {#env} as a Rack::Request object | ||
# | ||
# @note The following URL is known to be acceptable for the reshare.commons-archive.org tenant: | ||
# | ||
# https://reshare.palni-palci-staging.notch8.cloud/concern/cdls/74ebfc53-ee7c-4dc9-9dd7-693e4d840745 | ||
def requested_work_url | ||
Rails.logger.info("=@=@=@=@ #{self.class}#session['#{WorkAuthorization::StoreUrlForScope::CDL_SESSION_KEY}'] is #{session[WorkAuthorization::StoreUrlForScope::CDL_SESSION_KEY].inspect}") | ||
Rails.logger.info("=@=@=@=@ #{self.class}#params['scope'] is #{params['scope'].inspect}") | ||
session[WorkAuthorization::StoreUrlForScope::CDL_SESSION_KEY] || | ||
params['scope']&.split(%r{\s+})&.reject { |el| el.to_s == "openid" }&.first | ||
end | ||
end | ||
end | ||
end | ||
|
||
OmniAuth::Strategies::OpenIDConnect.prepend(OmniAuth::Strategies::OpenIDConnectDecorator) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
spec/omni_auth/strategies/open_id_connect_decorator_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
|
||
# rubocop:disable RSpec/MultipleDescribes | ||
RSpec.describe OmniAuth::Strategies::OpenIDConnectDecorator do | ||
let(:strategy) do | ||
Class.new do | ||
def initialize(options: {}, session: {}) | ||
@options = options | ||
@session = session | ||
end | ||
attr_reader :options, :session | ||
|
||
# Include this after the attr_reader :options to leverage super method | ||
prepend OmniAuth::Strategies::OpenIDConnectDecorator | ||
end | ||
end | ||
|
||
let(:requested_work_url) { "https://hello.world/something-special" } | ||
let(:options) { { scope: [:openid] } } | ||
let(:session) { { "cdl.requested_work_url" => requested_work_url } } | ||
let(:instance) { strategy.new(options: options, session: session) } | ||
|
||
describe '#options' do | ||
subject { instance.options } | ||
|
||
it "has a :scope key that appends the #requested_work_url" do | ||
expect(subject.fetch(:scope)).to match_array([:openid, requested_work_url]) | ||
end | ||
end | ||
|
||
describe '#requested_work_url' do | ||
subject { instance.requested_work_url } | ||
|
||
it "fetches the 'cdl.requested_work_url' session" do | ||
expect(subject).to eq(requested_work_url) | ||
end | ||
|
||
describe "when the 'cdl.requested_work_url' key is missing" do | ||
let(:session) { {} } | ||
|
||
it { is_expected.to be_nil } | ||
end | ||
end | ||
end | ||
|
||
RSpec.describe OmniAuth::Strategies::OpenIDConnect do | ||
describe '#options method' do | ||
subject(:options_method) { described_class.instance_method(:options) } | ||
|
||
context 'source_location' do | ||
subject { options_method.source_location } | ||
|
||
it { is_expected.to match_array([Rails.root.join('lib', 'omni_auth', 'strategies', 'open_id_connect_decorator.rb').to_s, Integer]) } | ||
end | ||
|
||
context 'super_method' do | ||
subject { options_method.super_method } | ||
|
||
it { is_expected.not_to be_nil } | ||
end | ||
end | ||
end | ||
# rubocop:enable RSpec/MultipleDescribes |