-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DPC-3999 IAL/1 for main login page; IAL/2 for invitations page (#2149)
## 🎫 Ticket https://jira.cms.gov/browse/DPC-3999 ## 🛠 Changes - Basic login page switched from IAL/2 to IAL/1 - Accept/confirm invitation endpoints moved from CDInvitation Controller to a new Invitation Controller - New login ViewComponent created for Invitations - Login endpoint added to invitation controller to make IAL/2 request to login.gov ## ℹ️ Context for reviewers - The new login component is simply a clone of the old one. They are going to be quite different from each other in the future. - The AuthorizedOfficialInvitationsController was just a placeholder. - The invitations are remaining within the organizations resource just to reduce url hacking. - The update to the LoginDotGov controller was to account for given/family name only being available via the invitations login flow. ## ✅ Acceptance Validation Manual testing: - Login page just IAL/1 - Invitation page shows login if not logged in - Invitation page login is at IAL/2 ## 🔒 Security Implications - [ ] This PR adds a new software dependency or dependencies. - [ ] This PR modifies or invalidates one or more of our security controls. - [ ] This PR stores or transmits data that was not stored or transmitted before. - [ ] This PR requires additional review of its security implications for other reasons. If any security implications apply, add Jason Ashbaugh (GitHub username: StewGoin) as a reviewer and do not merge this PR without his approval.
- Loading branch information
1 parent
04eafc2
commit 3d0e118
Showing
19 changed files
with
498 additions
and
244 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
50 changes: 50 additions & 0 deletions
50
dpc-portal/app/components/page/session/invitation_login_component.html.erb
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,50 @@ | ||
<section class="usa-section"> | ||
<div class="grid-row margin-x-neg-205 flex-justify-center"> | ||
<div class="grid-col-12 mobile-lg:grid-col-10 tablet:grid-col-8 desktop:grid-col-6 padding-x-205 margin-bottom-4"> | ||
<h1 class="desktop:display-none font-sans-lg margin-bottom-4 tablet:margin-top-neg-3"> | ||
Welcome to the production portal for the Data at the Point of Care (DPC) API | ||
</h1> | ||
<div class="bg-white padding-y-3 padding-x-5 border border-base-lighter"> | ||
<h1 class="margin-bottom-0">Sign in to your account</h1> | ||
<p>You can access or create your account by signing in below.</p> | ||
<%= button_to login_organization_invitation_url(@invitation.provider_organization, @invitation), class: 'usa-button width-full margin-bottom-3', data: { turbo: false } do %> | ||
Sign in with <span class="login-button__logo">Login.gov</span> | ||
<% end %> | ||
</div> | ||
</div> | ||
<div class="grid-col-12 mobile-lg:grid-col-10 tablet:grid-col-8 desktop:grid-col-6 padding-x-205"> | ||
<div class="border-top border-base-lighter padding-top-4 desktop:border-0 desktop:padding-top-0"> | ||
<h2 class="display-none desktop:display-block margin-top-0"> | ||
Welcome to the production portal for the Data at the Point of Care (DPC) API | ||
</h2> | ||
<div class="usa-prose"> | ||
<p>Use this portal to get production credentials, manage X, and do X. If you're an | ||
Authorized Official, you'll need to take the following steps:</p> | ||
<section class="usa-graphic-list"> | ||
<div class="usa-graphic-list__row"> | ||
<div class="usa-media-block margin-y-2"> | ||
<%= image_tag 'circle-gray-20.svg', class: ['usa-media-block__img', 'height-7', 'width-7'] %> | ||
<div class="usa-media-block__body"> | ||
<p><strong>Add an organization.</strong> Vivavmus nec velit sed leo scelerisque laoreet vestibulum.</p> | ||
</div> | ||
</div> | ||
<div class="usa-media-block margin-y-2"> | ||
<%= image_tag 'circle-gray-20.svg', class: ['usa-media-block__img', 'height-7', 'width-7'] %> | ||
<div class="usa-media-block__body"> | ||
<p><strong>Invite a credential delegate.</strong> Vivavmus nec velit sed leo scelerisque laoreet vestibulum.</p> | ||
</div> | ||
</div> | ||
<div class="usa-media-block margin-y-2"> | ||
<%= image_tag 'circle-gray-20.svg', class: ['usa-media-block__img', 'height-7', 'width-7'] %> | ||
<div class="usa-media-block__body"> | ||
<p><strong>Lorem ipsum.</strong> Vivavmus nec velit sed leo scelerisque laoreet</p> | ||
</div> | ||
</div> | ||
</div> | ||
</section> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</section> | ||
|
13 changes: 13 additions & 0 deletions
13
dpc-portal/app/components/page/session/invitation_login_component.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,13 @@ | ||
# frozen_string_literal: true | ||
|
||
module Page | ||
module Session | ||
# Component for Invitatation login (IAL/2 flow) | ||
class InvitationLoginComponent < ViewComponent::Base | ||
def initialize(invitation) | ||
super | ||
@invitation = invitation | ||
end | ||
end | ||
end | ||
end |
14 changes: 14 additions & 0 deletions
14
dpc-portal/app/components/page/session/invitation_login_component_preview.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,14 @@ | ||
# frozen_string_literal: true | ||
|
||
module Page | ||
module Session | ||
# Preview of Invitatation login (IAL/2 flow) | ||
class InvitationLoginComponentPreview < ViewComponent::Preview | ||
def default | ||
provider_organization = ProviderOrganization.new(id: 4, name: 'Health Hut') | ||
invitation = Invitation.new(id: 2, provider_organization:) | ||
render(Page::Session::InvitationLoginComponent.new(invitation)) | ||
end | ||
end | ||
end | ||
end |
9 changes: 0 additions & 9 deletions
9
dpc-portal/app/controllers/authorized_official_invitations_controller.rb
This file was deleted.
Oops, something went wrong.
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,89 @@ | ||
# frozen_string_literal: true | ||
|
||
# Handles acceptance of invitations | ||
class InvitationsController < ApplicationController | ||
before_action :load_organization | ||
before_action :load_invitation | ||
before_action :authenticate_user!, except: %i[login] | ||
before_action :invitation_matches_cd, only: %i[confirm] | ||
|
||
def accept | ||
if current_user.email != @cd_invitation.invited_email | ||
return render(Page::CredentialDelegate::BadInvitationComponent.new('pii_mismatch'), | ||
status: :forbidden) | ||
end | ||
|
||
render(Page::CredentialDelegate::AcceptInvitationComponent.new(@organization, @cd_invitation)) | ||
end | ||
|
||
def confirm | ||
CdOrgLink.create!(user: current_user, provider_organization: @organization, invitation: @cd_invitation) | ||
@cd_invitation.update!(invited_given_name: nil, invited_family_name: nil, invited_phone: nil, invited_email: nil) | ||
flash[:notice] = "Invitation accepted. You can now manage this organization's credentials. Learn more." | ||
redirect_to organizations_path | ||
end | ||
|
||
def login | ||
login_session | ||
client_id = "urn:gov:cms:openidconnect.profiles:sp:sso:cms:dpc:#{ENV.fetch('ENV')}" | ||
url = URI::HTTPS.build(host: 'idp.int.identitysandbox.gov', | ||
path: '/openid_connect/authorize', | ||
query: { acr_values: 'http://idmanagement.gov/ns/assurance/ial/2', | ||
client_id:, | ||
redirect_uri: "#{redirect_host}/portal/users/auth/openid_connect/callback", | ||
response_type: 'code', | ||
scope: 'openid email all_emails profile phone social_security_number', | ||
nonce: @nonce, | ||
state: @state }.to_query) | ||
redirect_to url, allow_other_host: true | ||
end | ||
|
||
private | ||
|
||
def authenticate_user! | ||
return if current_user | ||
|
||
render(Page::Session::InvitationLoginComponent.new(@cd_invitation)) | ||
end | ||
|
||
def invitation_matches_cd | ||
unless @cd_invitation.match_user?(current_user) | ||
return render(Page::CredentialDelegate::BadInvitationComponent.new('pii_mismatch'), | ||
status: :forbidden) | ||
end | ||
return if params[:verification_code] == @cd_invitation.verification_code | ||
|
||
@cd_invitation.errors.add(:verification_code, :bad_code, message: 'tbd') | ||
render(Page::CredentialDelegate::AcceptInvitationComponent.new(@organization, @cd_invitation), | ||
status: :bad_request) | ||
end | ||
|
||
def load_invitation | ||
@cd_invitation = Invitation.find(params[:id]) | ||
if @organization != @cd_invitation.provider_organization | ||
render(Page::CredentialDelegate::BadInvitationComponent.new('invalid'), status: :not_found) | ||
elsif @cd_invitation.expired? || @cd_invitation.accepted? || @cd_invitation.cancelled_at.present? | ||
render(Page::CredentialDelegate::BadInvitationComponent.new('invalid'), | ||
status: :forbidden) | ||
end | ||
rescue ActiveRecord::RecordNotFound | ||
render(Page::CredentialDelegate::BadInvitationComponent.new('invalid'), status: :not_found) | ||
end | ||
|
||
def login_session | ||
session[:user_return_to] = accept_organization_invitation_url(@organization, params[:id]) | ||
session['omniauth.nonce'] = @nonce = SecureRandom.hex(16) | ||
session['omniauth.state'] = @state = SecureRandom.hex(16) | ||
end | ||
|
||
def redirect_host | ||
case ENV.fetch('ENV', nil) | ||
when 'local' | ||
'http://localhost:3100' | ||
when 'prod' | ||
'https://dpc.cms.gov' | ||
else | ||
"https://#{ENV.fetch('ENV', nil)}.dpc.cms.gov" | ||
end | ||
end | ||
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
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
34 changes: 34 additions & 0 deletions
34
dpc-portal/spec/components/page/session/invitation_login_component_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,34 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe Page::Session::InvitationLoginComponent, type: :component do | ||
include ComponentSupport | ||
describe 'login component' do | ||
let(:provider_organization) { build(:provider_organization, dpc_api_organization_id: 'foo') } | ||
let(:invitation) { create(:invitation, :cd, provider_organization:) } | ||
let(:component) { described_class.new(invitation) } | ||
before { render_inline(component) } | ||
it 'should be a usa section' do | ||
expect(page).to have_selector('section.usa-section') | ||
end | ||
|
||
it 'should have a login button' do | ||
expect(page).to have_selector('button.usa-button') | ||
expect(page.find('button.usa-button')).to have_content('Sign in with') | ||
expect(page).to have_selector('button.usa-button span.login-button__logo') | ||
expect(page.find('button.usa-button span.login-button__logo')).to have_content('Login.gov') | ||
end | ||
|
||
it 'should post to appropriate url' do | ||
path = "organizations/#{provider_organization.id}/invitations/#{invitation.id}/login" | ||
url = "http://test.host/portal/#{path}" | ||
expect(page.find('form')[:action]).to eq url | ||
expect(page.find('form')[:method]).to eq 'post' | ||
end | ||
|
||
it 'should have two columns' do | ||
expect(page.find_all('.grid-col-12').size).to eq 2 | ||
end | ||
end | ||
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
Oops, something went wrong.