From 6c5e315df43dc6937984ecab2fbea6a5b6cad684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Bara=C3=BAna?= Date: Tue, 28 May 2024 19:04:44 -0300 Subject: [PATCH 1/4] Add docs related to auth when using Kino.Proxy --- lib/kino/proxy.ex | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/lib/kino/proxy.ex b/lib/kino/proxy.ex index 60cf4db4..e78e2ec6 100644 --- a/lib/kino/proxy.ex +++ b/lib/kino/proxy.ex @@ -20,7 +20,7 @@ defmodule Kino.Proxy do Plug.Conn.send_resp(conn, 200, "hello") end - > #### Plug {: .info} + > #### Plug dependency {: .info} > > In order to use this feature, you need to add `:plug` as a dependency. @@ -29,12 +29,10 @@ defmodule Kino.Proxy do Using the proxy feature, we can use Livebook apps to build APIs. For example, we could provide a data export endpoint: - data = <<...>> - token = "auth-token" Kino.Proxy.listen(fn %{path_info: ["export", "data"]} = conn -> - ["Bearer " <> ^token] = Plug.Conn.get_req_header(conn, "authorization") + data = "some data" conn |> Plug.Conn.put_resp_header("content-type", "application/csv") @@ -46,8 +44,28 @@ defmodule Kino.Proxy do |> Plug.Conn.send_resp(200, "use /export/data to get extract the report data") end) - Once deployed as an app, the user would be able to export the data + Once deployed as an app, the API client would be able to export the data by sending a request to `/apps/:slug/proxy/export/data`. + + > #### Authentication {: .warning} + > + > The paths exposed by `Kino.Proxy` don't use the authentication mechanisms + > defined in your Livebook instance. + > + > If you need to authenticate requests, you should + > implement your own authentication mechanism. Here's a simple example. + > + > ```elixir + > Kino.Proxy.listen(fn conn -> + > import Plug.BasicAuth + > + > case Plug.BasicAuth.basic_auth(conn, username: "username", password: "password") do + > %{status: 401} = conn -> Plug.Conn.send_resp(conn) + > + > conn -> Plug.Conn.send_resp(conn, 200, "hello") + > end + > end) + > ``` """ @doc """ From 38170b00418a5bacbd7cdc9e348eea750679267e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Bara=C3=BAna?= Date: Wed, 29 May 2024 10:55:50 -0300 Subject: [PATCH 2/4] Improve proxy auth example --- lib/kino/proxy.ex | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/kino/proxy.ex b/lib/kino/proxy.ex index e78e2ec6..a4957068 100644 --- a/lib/kino/proxy.ex +++ b/lib/kino/proxy.ex @@ -57,15 +57,17 @@ defmodule Kino.Proxy do > > ```elixir > Kino.Proxy.listen(fn conn -> - > import Plug.BasicAuth + > api_token = "my-secret-api-token" > - > case Plug.BasicAuth.basic_auth(conn, username: "username", password: "password") do - > %{status: 401} = conn -> Plug.Conn.send_resp(conn) - > - > conn -> Plug.Conn.send_resp(conn, 200, "hello") + > case Plug.Conn.get_req_header(conn, "authorization") do + > ["Bearer " <> ^api_token] -> + > Plug.Conn.send_resp(conn, 200, "hello") + > _ -> + > conn + > |> Plug.Conn.put_resp_header("www-authenticate", "Bearer") + > |> Plug.Conn.send_resp(401, "Unauthorized") > end > end) - > ``` """ @doc """ From f88c37794f290c053b751eadd46ec45902b85635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20K=C5=82osko?= Date: Wed, 29 May 2024 16:07:46 +0200 Subject: [PATCH 3/4] Update lib/kino/proxy.ex --- lib/kino/proxy.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/kino/proxy.ex b/lib/kino/proxy.ex index a4957068..8971f3ac 100644 --- a/lib/kino/proxy.ex +++ b/lib/kino/proxy.ex @@ -62,6 +62,7 @@ defmodule Kino.Proxy do > case Plug.Conn.get_req_header(conn, "authorization") do > ["Bearer " <> ^api_token] -> > Plug.Conn.send_resp(conn, 200, "hello") + > > _ -> > conn > |> Plug.Conn.put_resp_header("www-authenticate", "Bearer") From e93ed92c82d853354c09e1e82908fc4977286412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Bara=C3=BAna?= Date: Mon, 3 Jun 2024 09:51:09 -0300 Subject: [PATCH 4/4] Uses in the doc example --- lib/kino/proxy.ex | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/kino/proxy.ex b/lib/kino/proxy.ex index 8971f3ac..f9a84128 100644 --- a/lib/kino/proxy.ex +++ b/lib/kino/proxy.ex @@ -57,18 +57,19 @@ defmodule Kino.Proxy do > > ```elixir > Kino.Proxy.listen(fn conn -> - > api_token = "my-secret-api-token" - > - > case Plug.Conn.get_req_header(conn, "authorization") do - > ["Bearer " <> ^api_token] -> - > Plug.Conn.send_resp(conn, 200, "hello") + > expected_token = "my-secret-api-token" > + > with ["Bearer " <> user_token] <- Plug.Conn.get_req_header(conn, "authorization"), + > true <- Plug.Crypto.secure_compare(user_token, expected_token) do + > Plug.Conn.send_resp(conn, 200, "hello") + > else > _ -> > conn > |> Plug.Conn.put_resp_header("www-authenticate", "Bearer") > |> Plug.Conn.send_resp(401, "Unauthorized") > end > end) + > ``` """ @doc """