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
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
fragment-dev (1.4.5)
fragment-dev (1.4.6)
graphql (>= 2.2.5, < 3.0)
graphql-client (~> 0.23.0)
sorbet-runtime (~> 0.5)
Expand Down
45 changes: 45 additions & 0 deletions lib/fragment.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -13800,6 +13800,16 @@
"ofType": null
},
"defaultValue": null
},
{
"name": "repeated",
"description": "Repeated expansion configuration. When set, this condition is expanded at runtime for each element\nin the array parameter named by the key.",
"type": {
"kind": "INPUT_OBJECT",
"name": "SchemaRepeatedConfigInput",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
Expand Down Expand Up @@ -14114,6 +14124,16 @@
},
"defaultValue": null
},
{
"name": "repeated",
"description": "Repeated expansion configuration. When set, this line is expanded at runtime for each element\nin the array parameter named by the key.",
"type": {
"kind": "INPUT_OBJECT",
"name": "SchemaRepeatedConfigInput",
"ofType": null
},
"defaultValue": null
},
{
"name": "tx",
"description": "The external transaction to reconcile.\nThis field is required if the Ledger Account being posted to is a Linked Ledger Account. Otherwise, this field is disallowed.\nIt supports parameters in its attributes via handlebars syntax.\n\nSee the docs on [reconciling payments](https://fragment.dev/docs/reconcile-payments).",
Expand Down Expand Up @@ -14164,6 +14184,31 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "SchemaRepeatedConfigInput",
"description": "Configuration for repeated expansion of a line or condition. The key names a client-supplied\narray parameter whose elements each generate one copy of the line or condition at runtime.",
"fields": null,
"inputFields": [
{
"name": "key",
"description": "The key of the array parameter whose elements expand this line or condition.",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "SafeString",
"ofType": null
}
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "SchemaTxMatchInput",
Expand Down
8 changes: 6 additions & 2 deletions lib/fragment_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,12 @@ def create_token
uri = URI.parse(@oauth_url.to_s)
post = Net::HTTP::Post.new(uri.request_uri)
post.basic_auth(@client_id, @client_secret)
post.body = format('grant_type=client_credentials&scope=%<scope>s&client_id=%<id>s', scope: @oauth_scope,
id: @client_id)
post.content_type = "application/x-www-form-urlencoded"
post.body = URI.encode_www_form(
grant_type: 'client_credentials',
scope: @oauth_scope,
client_id: @client_id
)

begin
http = Net::HTTP.new(uri.host, uri.port)
Expand Down
2 changes: 1 addition & 1 deletion lib/fragment_client/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module FragmentSDK
VERSION = '1.4.5'
VERSION = '1.4.6'
end
29 changes: 29 additions & 0 deletions test/unit_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,13 @@ def test_token_request_conforms_to_oauth2_and_http_specs
refute_nil body_params['scope'],
'scope parameter should be present when configured (RFC 6749 §4.4.2)'

# RFC 6749 §4.4.2 requires the token request entity-body to use the
# application/x-www-form-urlencoded format per Appendix B, and the
# section's example request explicitly sets this Content-Type.
content_type = captured_auth_request.headers['Content-Type']
assert_match(/\Aapplication\/x-www-form-urlencoded\b/, content_type,
'Token request Content-Type should be application/x-www-form-urlencoded (RFC 6749 §4.4.2)')

# RFC 6749 §2.3.1: "Clients in possession of a client password MAY use
# the HTTP Basic authentication scheme [...] The client identifier is [...]
# used as the username; the client password [...] used as the password."
Expand Down Expand Up @@ -340,4 +347,26 @@ def test_token_request_uses_origin_form_with_custom_oauth_url
$VERBOSE = verbose
end
end

def test_token_request_uses_appendix_b_form_encoding_utf8
captured_auth_request = nil
stub_request(:post, 'https://auth.fragment.dev/oauth2/token')
.to_return do |request|
captured_auth_request = request
{ status: 200, body: { access_token: 'test_token', expires_in: 3600 }.to_json }
end

client_id = 'client id+special&utf8-umlaut-umlauts-äöü'
oauth_scope = 'https://api.fragment.dev/read write?x=1&y=2'

FragmentClient.new(client_id, 'secret', oauth_scope: oauth_scope)

# RFC 6749 §4.4.2 requires x-www-form-urlencoded per Appendix B (UTF-8).
body_params = URI.decode_www_form(captured_auth_request.body).to_h
assert_equal 'client_credentials', body_params['grant_type']
assert_equal oauth_scope, body_params['scope'],
'scope should round-trip via x-www-form-urlencoded UTF-8 encoding'
assert_equal client_id, body_params['client_id'],
'client_id should round-trip via x-www-form-urlencoded UTF-8 encoding'
end
end