diff --git a/lib/workos/sso.rb b/lib/workos/sso.rb index bd7f52e9..87e90a33 100644 --- a/lib/workos/sso.rb +++ b/lib/workos/sso.rb @@ -120,8 +120,9 @@ def profile_and_token(code:, client_id: nil) code: code, } - response = client.request(post_request(path: '/sso/token', body: body)) - check_and_raise_profile_and_token_error(response: response) + response = execute_request( + request: post_request(path: '/sso/token', body: body), + ) WorkOS::ProfileAndToken.new(response.body) end @@ -229,28 +230,6 @@ def validate_authorization_url_arguments( raise ArgumentError, "#{provider} is not a valid value." \ " `provider` must be in #{PROVIDERS}" end - - def check_and_raise_profile_and_token_error(response:) - begin - body = JSON.parse(response.body) - return if body['access_token'] && body['profile'] - - message = body['message'] - error = body['error'] - error_description = body['error_description'] - request_id = response['x-request-id'] - rescue StandardError - message = 'Something went wrong' - end - - raise APIError.new( - message: message, - error: error, - error_description: error_description, - http_status: nil, - request_id: request_id, - ) - end end end end diff --git a/spec/lib/workos/sso_spec.rb b/spec/lib/workos/sso_spec.rb index d3037e63..6753e306 100644 --- a/spec/lib/workos/sso_spec.rb +++ b/spec/lib/workos/sso_spec.rb @@ -416,10 +416,73 @@ expect do described_class.profile_and_token(**args) end.to raise_error( - WorkOS::APIError, - 'error: some error, error_description: some error description - request ID: request-id', + WorkOS::UnprocessableEntityError, + 'Status 422, some error - request ID: request-id', ) end + + it 'raises an exception with proper error object attributes' do + expect do + described_class.profile_and_token(**args) + end.to raise_error(WorkOS::UnprocessableEntityError) + end + + it 'includes proper error attributes' do + error = begin + described_class.profile_and_token(**args) + rescue WorkOS::UnprocessableEntityError => e + e + end + + expect(error.http_status).to eq(422) + expect(error.request_id).to eq('request-id') + expect(error.error).to eq('some error') + expect(error.message).to include('some error') + end + end + + context 'with detailed field validation errors' do + before do + stub_request(:post, 'https://api.workos.com/sso/token'). + with(headers: headers, body: request_body). + to_return( + headers: { 'X-Request-ID' => 'request-id' }, + status: 422, + body: { + "message": 'Validation failed', + "code": 'invalid_request_parameters', + "errors": [ + { + "field": 'code', + "code": 'missing_required_parameter', + "message": 'The code parameter is required', + } + ], + }.to_json, + ) + end + + it 'raises an exception with detailed field errors' do + expect do + described_class.profile_and_token(**args) + end.to raise_error(WorkOS::UnprocessableEntityError) + end + + it 'includes detailed field error attributes' do + error = begin + described_class.profile_and_token(**args) + rescue WorkOS::UnprocessableEntityError => e + e + end + + expect(error.http_status).to eq(422) + expect(error.request_id).to eq('request-id') + expect(error.code).to eq('invalid_request_parameters') + expect(error.errors).not_to be_nil + expect(error.errors).to include('code: missing_required_parameter') + expect(error.message).to include('Validation failed') + expect(error.message).to include('(code: missing_required_parameter)') + end end context 'with an expired code' do @@ -440,11 +503,31 @@ expect do described_class.profile_and_token(**args) end.to raise_error( - WorkOS::APIError, - "error: invalid_grant, error_description: The code '01DVX3C5Z367SFHR8QNDMK7V24'" \ + WorkOS::InvalidRequestError, + "Status 400, error: invalid_grant, error_description: The code '01DVX3C5Z367SFHR8QNDMK7V24'" \ ' has expired or is invalid. - request ID: request-id', ) end + + it 'raises an exception with proper error object attributes' do + expect do + described_class.profile_and_token(**args) + end.to raise_error(WorkOS::InvalidRequestError) + end + + it 'includes proper error attributes' do + error = begin + described_class.profile_and_token(**args) + rescue WorkOS::InvalidRequestError => e + e + end + + expect(error.http_status).to eq(400) + expect(error.request_id).to eq('request-id') + expect(error.error).to eq('invalid_grant') + expect(error.error_description).to eq("The code '01DVX3C5Z367SFHR8QNDMK7V24' has expired or is invalid.") + expect(error.message).to include('invalid_grant') + end end end