From 3a3ec61e4dd099d6ec9be0f3853adc6c7cb612b7 Mon Sep 17 00:00:00 2001 From: Kevin Duensing Date: Wed, 17 Apr 2024 16:08:40 -0400 Subject: [PATCH] Add method to request a token from STS (#16372) * Add method to request a token from STS * fix rubocop * Fix tests * Remove debugging line * change parameter to reflect actual value * Merge conflict fix * remove diff file from merge conflict --- .../travel_pay/claims_controller.rb | 6 +- .../travel_pay/pings_controller.rb | 4 +- .../app/services/travel_pay/client.rb | 57 ++++++++++++++++++- .../controllers/claims_controller_spec.rb | 12 +++- .../spec/controllers/pings_controller_spec.rb | 3 + 5 files changed, 73 insertions(+), 9 deletions(-) diff --git a/modules/travel_pay/app/controllers/travel_pay/claims_controller.rb b/modules/travel_pay/app/controllers/travel_pay/claims_controller.rb index 18136f9f7e6..59cce20d36d 100644 --- a/modules/travel_pay/app/controllers/travel_pay/claims_controller.rb +++ b/modules/travel_pay/app/controllers/travel_pay/claims_controller.rb @@ -6,9 +6,9 @@ class ClaimsController < ApplicationController def index veis_token = client.request_veis_token - # Non-intuitive Ruby behavior: #split splits a string on space by default - vagov_token = request.headers['Authorization'].split[1] - btsss_token = client.request_btsss_token(veis_token, vagov_token) + + sts_token = client.request_sts_token(@current_user) + btsss_token = client.request_btsss_token(veis_token, sts_token) begin claims = client.get_claims(veis_token, btsss_token) diff --git a/modules/travel_pay/app/controllers/travel_pay/pings_controller.rb b/modules/travel_pay/app/controllers/travel_pay/pings_controller.rb index c0d12814307..6f8964a7fd2 100644 --- a/modules/travel_pay/app/controllers/travel_pay/pings_controller.rb +++ b/modules/travel_pay/app/controllers/travel_pay/pings_controller.rb @@ -13,9 +13,9 @@ def ping end def authorized_ping - vagov_token = request.headers['Authorization'].split[1] + sts_token = client.request_sts_token(@current_user) veis_token = client.request_veis_token - btsss_token = client.request_btsss_token(veis_token, vagov_token) + btsss_token = client.request_btsss_token(veis_token, sts_token) btsss_authorized_ping_response = client.authorized_ping(veis_token, btsss_token) render json: { diff --git a/modules/travel_pay/app/services/travel_pay/client.rb b/modules/travel_pay/app/services/travel_pay/client.rb index e48b5f52c3a..24ef261c2c9 100644 --- a/modules/travel_pay/app/services/travel_pay/client.rb +++ b/modules/travel_pay/app/services/travel_pay/client.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'securerandom' + module TravelPay class Client ## @@ -24,7 +26,7 @@ def request_veis_token # # @return [Faraday::Response] # - def request_btsss_token(veis_token, vagov_token) + def request_btsss_token(veis_token, sts_token) btsss_url = Settings.travel_pay.base_url api_key = Settings.travel_pay.subscription_key client_number = Settings.travel_pay.client_number @@ -33,7 +35,7 @@ def request_btsss_token(veis_token, vagov_token) req.headers['Authorization'] = "Bearer #{veis_token}" req.headers['Ocp-Apim-Subscription-Key'] = api_key req.headers['BTSSS-API-Client-Number'] = client_number.to_s - req.body = { authJwt: vagov_token } + req.body = { authJwt: sts_token } end response.body['access_token'] end @@ -90,8 +92,59 @@ def get_claims(veis_token, btsss_token) symbolized_body[:data].sort_by(&parse_claim_date).reverse! end + def request_sts_token(user) + host_baseurl = build_host_baseurl({ ip_form: false }) + private_key_file = Settings.sign_in.sts_client.key_path + private_key = OpenSSL::PKey::RSA.new(File.read(private_key_file)) + + assertion = build_sts_assertion(user) + jwt = JWT.encode(assertion, private_key, 'RS256') + + # send to sis + response = connection(server_url: host_baseurl).post('/v0/sign_in/token') do |req| + req.params['grant_type'] = 'urn:ietf:params:oauth:grant-type:jwt-bearer' + req.params['assertion'] = jwt + end + + response.body['data']['access_token'] + end + private + def build_sts_assertion(user) + service_account_id = Settings.travel_pay.sts.service_account_id + host_baseurl = build_host_baseurl({ ip_form: false }) + audience_baseurl = build_host_baseurl({ ip_form: true }) + + current_time = Time.now.to_i + jti = SecureRandom.uuid + + { + 'iss' => host_baseurl, + 'sub' => user.email, + 'aud' => "#{audience_baseurl}/v0/sign_in/token", + 'iat' => current_time, + 'exp' => current_time + 300, + 'scopes' => [], + 'service_account_id' => service_account_id, + 'jti' => jti, + 'user_attributes' => { 'icn' => user.icn } + } + end + + def build_host_baseurl(config) + env = Settings.vsp_environment + host = Settings.hostname + + if env == 'localhost' + return 'http://127.0.0.1:3000' if config[:ip_form] + + 'http://localhost:3000' + end + + "https://#{host}" + end + def veis_params { client_id: Settings.travel_pay.veis.client_id, diff --git a/modules/travel_pay/spec/controllers/claims_controller_spec.rb b/modules/travel_pay/spec/controllers/claims_controller_spec.rb index 0762820acf5..16c2ca24639 100644 --- a/modules/travel_pay/spec/controllers/claims_controller_spec.rb +++ b/modules/travel_pay/spec/controllers/claims_controller_spec.rb @@ -12,9 +12,13 @@ .to receive(:request_veis_token) .and_return('veis_token') + allow_any_instance_of(TravelPay::Client) + .to receive(:request_sts_token) + .and_return('sts_token') + allow_any_instance_of(TravelPay::Client) .to receive(:request_btsss_token) - .with('veis_token', 'vagov_token') + .with('veis_token', 'sts_token') .and_return('btsss_token') allow_any_instance_of(TravelPay::Client) @@ -34,9 +38,13 @@ .to receive(:request_veis_token) .and_return('veis_token') + allow_any_instance_of(TravelPay::Client) + .to receive(:request_sts_token) + .and_return('sts_token') + allow_any_instance_of(TravelPay::Client) .to receive(:request_btsss_token) - .with('veis_token', 'vagov_token') + .with('veis_token', 'sts_token') .and_return('btsss_token') allow_any_instance_of(TravelPay::Client) diff --git a/modules/travel_pay/spec/controllers/pings_controller_spec.rb b/modules/travel_pay/spec/controllers/pings_controller_spec.rb index 750a96600bf..93c43f00240 100644 --- a/modules/travel_pay/spec/controllers/pings_controller_spec.rb +++ b/modules/travel_pay/spec/controllers/pings_controller_spec.rb @@ -48,6 +48,9 @@ before do btsss_authorized_ping_response = double allow(btsss_authorized_ping_response).to receive(:status).and_return(200) + allow(client) + .to receive(:request_sts_token) + .and_return('sample_sts_token') allow(client) .to receive(:request_btsss_token) .and_return('sample_btsss_token')