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

Add OAuth2::Client#http_client #10452

Merged
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
33 changes: 33 additions & 0 deletions spec/std/http/spec_helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,36 @@ def run_server(server)
end
end
end

# Helper method which runs a *handler*
# Similar to `run_server` but doesn't go through the network stack.
def run_handler(handler)
done = Channel(Exception?).new

begin
IO::Stapled.pipe do |server_io, client_io|
processor = HTTP::Server::RequestProcessor.new(handler)
f = spawn do
processor.process(server_io, server_io)
rescue exc
done.send exc
else
done.send nil
end

client = HTTP::Client.new(client_io)

begin
wait_until_blocked f

yield client
ensure
processor.close
server_io.close
if exc = done.receive
raise exc
end
end
end
end
end
85 changes: 48 additions & 37 deletions spec/std/oauth2/client_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,34 @@ describe OAuth2::Client do
describe "get_access_token_using_*" do
describe "using HTTP Basic authentication to pass credentials" do
it "#get_access_token_using_authorization_code" do
server = HTTP::Server.new do |context|
handler = HTTP::Handler::HandlerProc.new do |context|
body = context.request.body.not_nil!.gets_to_end
response = {access_token: "access_token", body: body}
context.response.print response.to_json
end

address = server.bind_unused_port "127.0.0.1"
run_handler(handler) do |http_client|
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", scheme: "http"
client.http_client = http_client

token = client.get_access_token_using_authorization_code(authorization_code: "SDFhw39fwfg23flSfpawbef")
token.extra.not_nil!["body"].should eq %("redirect_uri=&grant_type=authorization_code&code=SDFhw39fwfg23flSfpawbef")
token.access_token.should eq "access_token"
end
end

it "configures HTTP::Client" do
server = HTTP::Server.new do |context|
body = context.request.body.not_nil!.gets_to_end
response = {access_token: "access_token", body: body}
context.response.print response.to_json
end
address = server.bind_tcp 0

run_server(server) do
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", port: address.port, scheme: "http"
client.http_client.port.should eq address.port
client.http_client.host.should eq "127.0.0.1"

token = client.get_access_token_using_authorization_code(authorization_code: "SDFhw39fwfg23flSfpawbef")
token.extra.not_nil!["body"].should eq %("redirect_uri=&grant_type=authorization_code&code=SDFhw39fwfg23flSfpawbef")
Expand All @@ -60,16 +78,15 @@ describe OAuth2::Client do
end

it "#get_access_token_using_resource_owner_credentials" do
server = HTTP::Server.new do |context|
handler = HTTP::Handler::HandlerProc.new do |context|
body = context.request.body.not_nil!.gets_to_end
response = {access_token: "access_token", body: body}
context.response.print response.to_json
end

address = server.bind_unused_port "127.0.0.1"

run_server(server) do
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", port: address.port, scheme: "http"
run_handler(handler) do |http_client|
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", scheme: "http"
client.http_client = http_client

token = client.get_access_token_using_resource_owner_credentials(username: "user123", password: "monkey", scope: "read_posts")
token.extra.not_nil!["body"].should eq %("grant_type=password&username=user123&password=monkey&scope=read_posts")
Expand All @@ -78,16 +95,15 @@ describe OAuth2::Client do
end

it "#get_access_token_using_client_credentials" do
server = HTTP::Server.new do |context|
handler = HTTP::Handler::HandlerProc.new do |context|
body = context.request.body.not_nil!.gets_to_end
response = {access_token: "access_token", body: body}
context.response.print response.to_json
end

address = server.bind_unused_port "127.0.0.1"

run_server(server) do
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", port: address.port, scheme: "http"
run_handler(handler) do |http_client|
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", scheme: "http"
client.http_client = http_client

token = client.get_access_token_using_client_credentials(scope: "read_posts")
token.extra.not_nil!["body"].should eq %("grant_type=client_credentials&scope=read_posts")
Expand All @@ -96,16 +112,15 @@ describe OAuth2::Client do
end

it "#get_access_token_using_refresh_token" do
server = HTTP::Server.new do |context|
handler = HTTP::Handler::HandlerProc.new do |context|
body = context.request.body.not_nil!.gets_to_end
response = {access_token: "access_token", body: body}
context.response.print response.to_json
end

address = server.bind_unused_port "127.0.0.1"

run_server(server) do
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", port: address.port, scheme: "http"
run_handler(handler) do |http_client|
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", scheme: "http"
client.http_client = http_client

token = client.get_access_token_using_refresh_token(scope: "read_posts", refresh_token: "some_refresh_token")
token.extra.not_nil!["body"].should eq %("grant_type=refresh_token&refresh_token=some_refresh_token&scope=read_posts")
Expand All @@ -115,16 +130,15 @@ describe OAuth2::Client do
end
describe "using Request Body to pass credentials" do
it "#get_access_token_using_authorization_code" do
server = HTTP::Server.new do |context|
handler = HTTP::Handler::HandlerProc.new do |context|
body = context.request.body.not_nil!.gets_to_end
response = {access_token: "access_token", body: body}
context.response.print response.to_json
end

address = server.bind_unused_port "127.0.0.1"

run_server(server) do
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", port: address.port, scheme: "http", auth_scheme: OAuth2::AuthScheme::RequestBody
run_handler(handler) do |http_client|
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", scheme: "http", auth_scheme: OAuth2::AuthScheme::RequestBody
client.http_client = http_client

token = client.get_access_token_using_authorization_code(authorization_code: "SDFhw39fwfg23flSfpawbef")
token.extra.not_nil!["body"].should eq %("client_id=client_id&client_secret=client_secret&redirect_uri=&grant_type=authorization_code&code=SDFhw39fwfg23flSfpawbef")
Expand All @@ -133,16 +147,15 @@ describe OAuth2::Client do
end

it "#get_access_token_using_resource_owner_credentials" do
server = HTTP::Server.new do |context|
handler = HTTP::Handler::HandlerProc.new do |context|
body = context.request.body.not_nil!.gets_to_end
response = {access_token: "access_token", body: body}
context.response.print response.to_json
end

address = server.bind_unused_port "127.0.0.1"

run_server(server) do
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", port: address.port, scheme: "http", auth_scheme: OAuth2::AuthScheme::RequestBody
run_handler(handler) do |http_client|
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", scheme: "http", auth_scheme: OAuth2::AuthScheme::RequestBody
client.http_client = http_client

token = client.get_access_token_using_resource_owner_credentials(username: "user123", password: "monkey", scope: "read_posts")
token.extra.not_nil!["body"].should eq %("client_id=client_id&client_secret=client_secret&grant_type=password&username=user123&password=monkey&scope=read_posts")
Expand All @@ -151,16 +164,15 @@ describe OAuth2::Client do
end

it "#get_access_token_using_client_credentials" do
server = HTTP::Server.new do |context|
handler = HTTP::Handler::HandlerProc.new do |context|
body = context.request.body.not_nil!.gets_to_end
response = {access_token: "access_token", body: body}
context.response.print response.to_json
end

address = server.bind_unused_port "127.0.0.1"

run_server(server) do
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", port: address.port, scheme: "http", auth_scheme: OAuth2::AuthScheme::RequestBody
run_handler(handler) do |http_client|
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", scheme: "http", auth_scheme: OAuth2::AuthScheme::RequestBody
client.http_client = http_client

token = client.get_access_token_using_client_credentials(scope: "read_posts")
token.extra.not_nil!["body"].should eq %("client_id=client_id&client_secret=client_secret&grant_type=client_credentials&scope=read_posts")
Expand All @@ -169,16 +181,15 @@ describe OAuth2::Client do
end

it "#get_access_token_using_refresh_token" do
server = HTTP::Server.new do |context|
handler = HTTP::Handler::HandlerProc.new do |context|
body = context.request.body.not_nil!.gets_to_end
response = {access_token: "access_token", body: body}
context.response.print response.to_json
end

address = server.bind_unused_port "127.0.0.1"

run_server(server) do
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", port: address.port, scheme: "http", auth_scheme: OAuth2::AuthScheme::RequestBody
run_handler(handler) do |http_client|
client = OAuth2::Client.new "127.0.0.1", "client_id", "client_secret", scheme: "http", auth_scheme: OAuth2::AuthScheme::RequestBody
client.http_client = http_client

token = client.get_access_token_using_refresh_token(scope: "read_posts", refresh_token: "some_refresh_token")
token.extra.not_nil!["body"].should eq %("client_id=client_id&client_secret=client_secret&grant_type=refresh_token&refresh_token=some_refresh_token&scope=read_posts")
Expand Down
13 changes: 12 additions & 1 deletion src/oauth2/client.cr
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@
# You can also use an `OAuth2::Session` to automatically refresh expired
# tokens before each request.
class OAuth2::Client
# Sets the `HTTP::Client` to use with this client.
setter http_client : HTTP::Client?

# Returns the `HTTP::Client` to use with this client.
#
# By default, this returns a new instance every time. To reuse the same instance,
# one can be assigned with `#http_client=`.
def http_client : HTTP::Client
@http_client || HTTP::Client.new(token_uri)
end

# Creates an OAuth client.
#
# Any or all of the customizable URIs *authorize_uri* and
Expand Down Expand Up @@ -168,7 +179,7 @@ class OAuth2::Client
yield form
end

response = HTTP::Client.post token_uri, form: body, headers: headers
response = http_client.post token_uri.request_target, form: body, headers: headers
case response.status
when .ok?, .created?
OAuth2::AccessToken.from_json(response.body)
Expand Down