Bug fix: fix redirect_to URL when authenticating via livebook teams (#2857)

This commit is contained in:
Hugo Baraúna 2024-11-19 16:27:06 -03:00 committed by GitHub
parent bed5aa021c
commit 651d037194
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 49 additions and 32 deletions

View file

@ -103,14 +103,31 @@ defmodule Livebook.ZTA.LivebookTeams do
defp request_user_authentication(conn, team) do
case Teams.Requests.create_auth_request(team) do
{:ok, %{"authorize_uri" => authorize_uri}} ->
current_url = LivebookWeb.Endpoint.url() <> conn.request_path <> "?teams_identity"
# We have the browser do the redirect because the browser
# knows the current page location. Unfortunately, it is quite
# complex to know the actual host on the server, because the
# user may be running inside a proxy. So in order to make the
# feature more accessible, we do the redirecting on the client.
conn =
html(conn, """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redirecting...</title>
<script>
const redirectTo = new URL(window.location.href);
redirectTo.searchParams.append("teams_identity", "");
url =
URI.parse(authorize_uri)
|> URI.append_query("redirect_to=#{URI.encode_www_form(current_url)}")
|> URI.to_string()
const url = new URL("#{authorize_uri}");
url.searchParams.set("redirect_to", redirectTo.toString());
window.location.href = url.toString();
</script>
</head>
</html>
""")
{conn |> redirect(external: url) |> halt(), nil}
{halt(conn), nil}
_ ->
{conn

View file

@ -1,7 +1,6 @@
defmodule Livebook.ZTA.LivebookTeamsTest do
# Not async, because we alter global config (teams auth)
use Livebook.TeamsIntegrationCase, async: false
use Plug.Test
alias Livebook.ZTA.LivebookTeams
@ -19,50 +18,51 @@ defmodule Livebook.ZTA.LivebookTeamsTest do
assert_receive {:agent_joined,
%{hub_id: ^hub_id, org_id: ^org_id, deployment_group_id: ^deployment_group_id}}
{:ok,
deployment_group: deployment_group, team: team, opts: [name: test, identity_key: team.id]}
start_supervised!({LivebookTeams, name: test, identity_key: team.id})
{:ok, deployment_group: deployment_group, team: team}
end
describe "authenticate/3" do
test "redirects the user to Livebook Teams for authentication",
%{conn: conn, test: test, opts: opts} do
start_supervised({LivebookTeams, opts})
conn = Plug.Test.init_test_session(conn, %{})
assert {%{status: 302, halted: true}, nil} = LivebookTeams.authenticate(test, conn, [])
test "renders HTML with JavaScript redirect", %{conn: conn, test: test} do
conn = init_test_session(conn, %{})
assert {conn, nil} = LivebookTeams.authenticate(test, conn, [])
assert conn.halted
assert html_response(conn, 200) =~ "window.location.href = "
end
test "gets the user information from Livebook Teams",
%{conn: conn, node: node, test: test, opts: opts} do
start_supervised({LivebookTeams, opts})
conn = Plug.Test.init_test_session(conn, %{})
%{conn: conn, node: node, test: test} do
# Step 1: Get redirected to Livebook Teams
conn = init_test_session(conn, %{})
{conn, nil} = LivebookTeams.authenticate(test, conn, [])
[location] = get_resp_header(conn, "location")
[_, location] = Regex.run(~r/URL\("(.*?)"\)/, html_response(conn, 200))
uri = URI.parse(location)
assert uri.path == "/identity/authorize"
redirect_to = LivebookWeb.Endpoint.url() <> "/?teams_identity"
assert %{"code" => code, "redirect_to" => ^redirect_to} = URI.decode_query(uri.query)
assert %{"code" => code} = URI.decode_query(uri.query)
erpc_call(node, :allow_auth_request, [code])
# Step 2: Emulate the redirect back with the code for validation
conn =
conn(:get, "/", %{teams_identity: "", code: code})
|> Plug.Test.init_test_session(%{})
build_conn(:get, "/", %{teams_identity: "", code: code})
|> init_test_session(%{})
assert {conn, %{id: _id, name: _, email: _, payload: %{"access_token" => _}} = metadata} =
LivebookTeams.authenticate(test, conn, [])
assert conn.status == 302
assert get_resp_header(conn, "location") == ["/"]
assert redirected_to(conn, 302) == "/"
# Step 3: Confirm the token/metadata is valid for future requests
conn =
build_conn(:get, "/")
|> init_test_session(%{identity_data: metadata})
conn = Plug.Test.init_test_session(conn(:get, "/"), %{identity_data: metadata})
assert {%{halted: false}, ^metadata} = LivebookTeams.authenticate(test, conn, [])
end
test "redirects to Livebook Teams with invalid access token",
%{conn: conn, test: test, opts: opts} do
%{conn: conn, test: test} do
identity_data = %{
id: "11",
name: "Ada Lovelace",
@ -70,10 +70,10 @@ defmodule Livebook.ZTA.LivebookTeamsTest do
email: "user95387220@example.com"
}
start_supervised({LivebookTeams, opts})
conn = Plug.Test.init_test_session(conn, %{identity_data: identity_data})
assert {%{status: 302}, nil} = LivebookTeams.authenticate(test, conn, [])
conn = init_test_session(conn, %{identity_data: identity_data})
assert {conn, nil} = LivebookTeams.authenticate(test, conn, [])
assert conn.halted
assert html_response(conn, 200) =~ "window.location.href = "
end
end
end