-
Notifications
You must be signed in to change notification settings - Fork 166
Allow signing in to SP after session timeout #1275
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,7 @@ def update | |
| Analytics::USER_REGISTRATION_AGENCY_HANDOFF_COMPLETE, | ||
| service_provider_attributes | ||
| ) | ||
| redirect_to after_sign_in_path_for(current_user) | ||
| redirect_to sp_session[:request_url] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would someone ever get to this point without being referred by an SP?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. The |
||
| end | ||
|
|
||
| private | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,14 +17,11 @@ def new | |
| def create | ||
| track_authentication_attempt(params[:user][:email]) | ||
|
|
||
| if current_user && user_locked_out?(current_user) | ||
| render 'two_factor_authentication/shared/max_login_attempts_reached' | ||
| sign_out | ||
| return | ||
| end | ||
| return process_locked_out_user if current_user && user_locked_out?(current_user) | ||
|
|
||
| super | ||
| cache_active_profile | ||
| store_sp_metadata_in_session unless request_id.empty? | ||
| end | ||
|
|
||
| def active | ||
|
|
@@ -53,6 +50,11 @@ def check_user_needs_redirect | |
| end | ||
| end | ||
|
|
||
| def process_locked_out_user | ||
| render 'two_factor_authentication/shared/max_login_attempts_reached' | ||
| sign_out | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you think we should sign out then render? Not sure if it matters, just wondering if the page might render different content based on signed in / out status.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure. I only refactored this to please Code Climate. I didn't change the behavior.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. However, I believe this order is like that for a reason. I recall this fixed a bug at one time. |
||
| end | ||
|
|
||
| def now | ||
| @_now ||= Time.zone.now | ||
| end | ||
|
|
@@ -91,13 +93,21 @@ def cache_active_profile | |
| end | ||
|
|
||
| def user_signed_in_and_not_locked_out?(user) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need the user to get passed in here? We should have access to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't change this behavior. This method existed before this PR. Can we revisit later if necessary?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure thing! |
||
| return false unless current_user.present? | ||
|
|
||
| return false unless current_user | ||
| !user_locked_out?(user) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. based on the name of this method, I'd expect this to read
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not new to this PR. I didn't want to make any changes that were not related. I can add the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's fine, we can keep as-is |
||
| end | ||
|
|
||
| def user_locked_out?(user) | ||
| UserDecorator.new(user).blocked_from_entering_2fa_code? | ||
| end | ||
|
|
||
| def store_sp_metadata_in_session | ||
| return if sp_session[:issuer] | ||
| StoreSpMetadataInSession.new(session: session, request_id: request_id).call | ||
| end | ||
|
|
||
| def request_id | ||
| params[:user].fetch(:request_id, '') | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| class StoreSpMetadataInSession | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. having the name of a class be a verb seems like an odd pattern to introduce.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not the first introduction of this pattern. See CreateVerifiedAccountEvent, RequestPasswordReset, UpdateUser, and UpdateUserPassword. Micropurchase does this as well. I think it's fine to have some classes be verbs and others nouns, depending on the best way to describe them.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't mind verb names in service class methods. I do feel like some of the service classes in this app could perhaps be classified as something else...eg |
||
| def initialize(session:, request_id:) | ||
| @session = session | ||
| @request_id = request_id | ||
| end | ||
|
|
||
| def call | ||
| session[:sp] = { | ||
| issuer: sp_request.issuer, | ||
| loa3: loa3_requested?, | ||
| request_url: sp_request.url, | ||
| request_id: sp_request.uuid, | ||
| } | ||
| end | ||
|
|
||
| private | ||
|
|
||
| attr_reader :session, :request_id | ||
|
|
||
| def sp_request | ||
| @sp_request ||= ServiceProviderRequest.find_by(uuid: request_id) | ||
| end | ||
|
|
||
| def loa3_requested? | ||
| sp_request.loa == Saml::Idp::Constants::LOA3_AUTHN_CONTEXT_CLASSREF | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ h1.h3.my0 = decorated_session.new_session_heading | |
| html: { autocomplete: 'off', role: 'form' }) do |f| | ||
| = f.input :email, required: true, input_html: { class: 'mb4' } | ||
| = f.input :password, required: true | ||
| = f.input :request_id, as: :hidden, input_html: { value: params[:request_id] } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The underscore is only present in the confirmation email. |
||
| = f.button :submit, t('links.next'), class: 'btn-wide' | ||
|
|
||
| - link = link_to t('notices.sign_in_consent.link'), MarketingSite.privacy_url, target: '_blank' | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -74,6 +74,22 @@ | |
|
|
||
| expect(current_path).to eq sign_up_completed_path | ||
| end | ||
|
|
||
| it 'after session timeout, signing in takes user back to SP' do | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
| allow(FeatureManagement).to receive(:prefill_otp_codes?).and_return(true) | ||
|
|
||
| user = create(:user, :signed_up) | ||
| saml_authn_request = auth_request.create(saml_settings) | ||
|
|
||
| visit saml_authn_request | ||
| sp_request_id = ServiceProviderRequest.last.uuid | ||
| page.set_rack_session(sp: {}) | ||
| visit new_user_session_url(request_id: sp_request_id) | ||
| fill_in_credentials_and_submit(user.email, user.password) | ||
| click_submit_default | ||
|
|
||
| expect(current_url).to eq saml_authn_request | ||
| end | ||
| end | ||
|
|
||
| context 'fully signed up user is signed in with email and password only' do | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hallelujah! 🎉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
woooooo! Care to comment on why this now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I was getting a bunch of Reek errors locally, and instead of adding a bunch of methods to the exclusion list, I figured we'd turn it off since we'll probably keep getting more of these in the future.