Skip to content
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

[VI-252] MAP SecurityToken duration validation #19635

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/controllers/v0/map_services_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def token
result = MAP::SecurityToken::Service.new.token(application: params[:application].to_sym, icn:, cache: false)

render json: result, status: :ok
rescue Common::Client::Errors::ClientError, Common::Exceptions::GatewayTimeout
rescue Common::Client::Errors::ClientError, Common::Exceptions::GatewayTimeout, JWT::VerificationError
render json: sts_client_error, status: :bad_gateway
rescue MAP::SecurityToken::Errors::ApplicationMismatchError
render json: application_mismatch_error, status: :bad_request
Expand Down
1 change: 1 addition & 0 deletions config/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ map_services:
oauth_url: https://veteran.apps-staging.va.gov
client_cert_path: spec/fixtures/map/oauth.crt
client_key_path: spec/fixtures/map/oauth.key
provider_cert_path: spec/fixtures/map/provider.crt
sign_up_service_url: https://cerner.apps-staging.va.gov
sign_up_service_provisioning_api_key: abcd1234
secure_token_service:
Expand Down
8 changes: 8 additions & 0 deletions lib/map/security_token/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ def client_cert_path
Settings.map_services.client_cert_path
end

def provider_cert_path
Settings.map_services.provider_cert_path
end

def service_name
'map_security_token_service'
end
Expand Down Expand Up @@ -78,6 +82,10 @@ def client_assertion_certificate
OpenSSL::X509::Certificate.new(File.read(client_cert_path))
end

def provider_certificate
OpenSSL::X509::Certificate.new(File.read(provider_cert_path))
end

def connection
@connection ||= Faraday.new(
base_path,
Expand Down
17 changes: 16 additions & 1 deletion lib/map/security_token/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,32 @@ def parse_and_raise_error(e, icn, application)

def parse_response(response, application, icn)
response_body = response.body
access_token = validate_map_token(response_body['access_token'])

{
access_token: response_body['access_token'],
access_token:,
expiration: Time.zone.now + response_body['expires_in']
}
rescue JWT::VerificationError => e
message = "#{config.logging_prefix} token failed, JWT verification error"
Rails.logger.error(message, application:, icn:)
raise e
rescue => e
message = "#{config.logging_prefix} token failed, response unknown"
Rails.logger.error(message, application:, icn:)
raise e, "#{message}, application: #{application}, icn: #{icn}"
end

def validate_map_token(encoded_token)
# waiting for MAP RS512 certificate
# public_cert = config.provider_certificate
public_cert = OpenSSL::PKey::RSA.new(2048).public_key
JWT.decode(encoded_token, public_cert, true, algorithm: 'RS512')
# potentially add more validation here

access_token
end

def client_id_from_application(application)
case application
when :chatbot
Expand Down
20 changes: 19 additions & 1 deletion spec/requests/v0/map_services_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,25 @@
end
end

context 'when MAP STS client returns an access token',
context 'when MAP STS client returns a token with an invalid duration',
vcr: { cassette_name: 'map/security_token_service_200_response_invalid_token' } do
it 'responds with error details in response body' do
call_endpoint
expect(JSON.parse(response.body)).to eq(
{
'error' => 'server_error',
'error_description' => 'STS failed to return a valid token.'
}
)
end

it 'returns HTTP status bad_gateway' do
call_endpoint
expect(response).to have_http_status(:bad_gateway)
end
end

context 'when MAP STS client returns a valid access token',
vcr: { cassette_name: 'map/security_token_service_200_response' } do
it 'responds with STS-issued token in response body' do
call_endpoint
Expand Down
Loading