-
Notifications
You must be signed in to change notification settings - Fork 65
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 docs related to auth when using Kino.Proxy #433
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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,32 @@ 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. | ||
Comment on lines
+52
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @josevalim I started to wonder if we should put them in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can always add more routes in the future. I think we have a good starting set. I can also see it being used for coordinating tasks inside their own infrastructure, but still not exposing it to the world. |
||
> | ||
> If you need to authenticate requests, you should | ||
> implement your own authentication mechanism. Here's a simple example. | ||
> | ||
> ```elixir | ||
> Kino.Proxy.listen(fn conn -> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @josevalim what about this code example with a simple Bearer auth? Kino.Proxy.listen(fn conn ->
api_token = "my-secret-api-token"
with ["Bearer " <> client_token] <- Plug.Conn.get_req_header(conn, "authorization"),
true <- api_token == client_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) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, the example above is unsafe, we want to use |
||
> 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 """ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, using bearer tokens may be the best example, since tokens are most common for APIs (and Kino.Proxy would most likely be used for APIs?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed.
I'll change from HTTP basic auth to HTTP Bearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about leaving this example as simple as possible, with no auth. And the auth would be below, inside the admonition block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see. Keeping it simple is a good idea.