Skip to content
Merged
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
27 changes: 3 additions & 24 deletions lib/workos/sso.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
91 changes: 87 additions & 4 deletions spec/lib/workos/sso_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down