diff --git a/app/controllers/master_files_controller.rb b/app/controllers/master_files_controller.rb index c10dcf3cfd..cd845b4991 100644 --- a/app/controllers/master_files_controller.rb +++ b/app/controllers/master_files_controller.rb @@ -243,11 +243,8 @@ def hls_manifest quality = params[:quality] if request.head? auth_token = request.headers['Authorization']&.sub('Bearer ', '') - if StreamToken.valid_token?(auth_token, @master_file.id) || can?(:read, @master_file) - return head :ok - else - return head :unauthorized - end + return iiif_auth_probe_resp(success: false) unless StreamToken.valid_token?(auth_token, @master_file.id) || can?(:read, @master_file) + iiif_auth_probe_resp(success: true) else return head :unauthorized if cannot?(:read, @master_file) @hls_streams = if quality == "auto" @@ -283,16 +280,25 @@ def delete_structure def iiif_auth_token if cannot? :read, @master_file - head :unauthorized + render 'iiif_auth_token_error', layout: false, locals: { message_id: message_id } else message_id = params[:messageId] - origin = params[:origin] access_token = StreamToken.find_or_create_session_token(session, @master_file.id) expires = (StreamToken.find_by(token: access_token).expires - Time.now.utc).to_i render 'iiif_auth_token', layout: false, locals: { message_id: message_id, origin: origin, access_token: access_token, expires: expires } end end + def iiif_auth_probe_resp(success: false) + { + "@context": "http://iiif.io/api/auth/2/context.json", + "type": "AuthProbeResult2", + "status": success ? 200 : 403, + "header": success ? { "en": [I18n.t('iiif.auth.failureHeader')] } : nil, + "note": success ? { "en": [I18n.t('iiif.auth.failureDescription')] } : nil + }.compact + end + def move current_media_object = @master_file.media_object authorize! :update, current_media_object diff --git a/app/models/iiif_canvas_presenter.rb b/app/models/iiif_canvas_presenter.rb index 9a07109542..2675510e03 100644 --- a/app/models/iiif_canvas_presenter.rb +++ b/app/models/iiif_canvas_presenter.rb @@ -287,32 +287,33 @@ def structure_ng_xml def auth_service(quality) { - "context": "http://iiif.io/api/auth/1/context.json", - "@id": Rails.application.routes.url_helpers.new_user_session_url(login_popup: 1), - "@type": "AuthCookieService1", - "confirmLabel": I18n.t('iiif.auth.confirmLabel'), - "description": I18n.t('iiif.auth.description'), - "failureDescription": I18n.t('iiif.auth.failureDescription'), - "failureHeader": I18n.t('iiif.auth.failureHeader'), - "header": I18n.t('iiif.auth.header'), - "label": I18n.t('iiif.auth.label'), - "profile": "http://iiif.io/api/auth/1/login", + "id": Rails.application.routes.url_helpers.hls_manifest_master_file_url(master_file.id, quality: quality), + "type": "AuthProbeService2", + "errorNote": { "en": [I18n.t('iiif.auth.failureDescription')] }, + "errorHeading": { "en": [I18n.t('iiif.auth.failureHeader')] }, "service": [ { - "@id": Rails.application.routes.url_helpers.hls_manifest_master_file_url(master_file.id, quality: quality), - "@type": "AuthProbeService1", - "profile": "http://iiif.io/api/auth/1/probe" - }, - { - "@id": Rails.application.routes.url_helpers.iiif_auth_token_url(id: master_file.id), - "@type": "AuthTokenService1", - "profile": "http://iiif.io/api/auth/1/token" - }, - { - "@id": Rails.application.routes.url_helpers.destroy_user_session_url, - "@type": "AuthLogoutService1", - "label": I18n.t('iiif.auth.logoutLabel'), - "profile": "http://iiif.io/api/auth/1/logout" + "id": Rails.application.routes.url_helpers.new_user_session_url(login_popup: 1), + "type": "AuthAccessService2", + "confirmLabel": { "en": [I18n.t('iiif.auth.confirmLabel')] }, + "note": { "en": [I18n.t('iiif.auth.description')] }, + "heading": { "en": [I18n.t('iiif.auth.header')] }, + "label": { "en": [I18n.t('iiif.auth.label')] }, + "profile": "active", + "service": [ + { + "id": Rails.application.routes.url_helpers.iiif_auth_token_url(id: master_file.id), + "type": "AuthAccessTokenService2", + "profile": "http://iiif.io/api/auth/1/token", + "errorNote": { "en": [I18n.t('iiif.auth.failureDescription')] }, + "errorHeading": { "en": [I18n.t('iiif.auth.failureHeader')] } + }, + { + "id": Rails.application.routes.url_helpers.destroy_user_session_url, + "type": "AuthLogoutService2", + "label": { "en": [I18n.t('iiif.auth.logoutLabel')] } + } + ] } ] } diff --git a/app/views/master_files/iiif_auth_token.html.erb b/app/views/master_files/iiif_auth_token.html.erb index 72e1523c9c..53141557e6 100644 --- a/app/views/master_files/iiif_auth_token.html.erb +++ b/app/views/master_files/iiif_auth_token.html.erb @@ -17,7 +17,13 @@ Unless required by applicable law or agreed to in writing, software distributed
diff --git a/app/views/master_files/iiif_auth_token_error.html.erb b/app/views/master_files/iiif_auth_token_error.html.erb new file mode 100644 index 0000000000..9960a31686 --- /dev/null +++ b/app/views/master_files/iiif_auth_token_error.html.erb @@ -0,0 +1,30 @@ +<%# +Copyright 2011-2025, The Trustees of Indiana University and Northwestern + University. Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed + under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. See the License for the + specific language governing permissions and limitations under the License. +--- END LICENSE_HEADER BLOCK --- +%> + + + + +