2018-09-20 02:29:36 +03:00
|
|
|
!:
|
|
|
|
:: lighter than eyre
|
|
|
|
::
|
2020-12-06 11:38:37 +03:00
|
|
|
|= our=ship
|
2019-07-04 09:09:44 +03:00
|
|
|
=, eyre
|
2018-09-20 02:29:36 +03:00
|
|
|
:: internal data structures
|
|
|
|
::
|
|
|
|
=> =~
|
|
|
|
::
|
|
|
|
:: internal data structures that won't go in zuse
|
|
|
|
::
|
|
|
|
|%
|
|
|
|
+$ move
|
|
|
|
::
|
|
|
|
$: :: duct: request identifier
|
|
|
|
::
|
|
|
|
=duct
|
|
|
|
::
|
|
|
|
::
|
2020-12-08 03:47:06 +03:00
|
|
|
card=(wind note gift)
|
2018-09-20 02:29:36 +03:00
|
|
|
==
|
2020-05-05 08:28:37 +03:00
|
|
|
:: +note: private request from eyre to another vane
|
2018-09-20 02:29:36 +03:00
|
|
|
::
|
|
|
|
+$ note
|
2023-06-28 00:15:00 +03:00
|
|
|
$% [%a $>(?(%plea %keen %yawn) task:ames)]
|
|
|
|
[%b $>(?(%rest %wait) task:behn)]
|
|
|
|
[%c $>(%warp task:clay)]
|
|
|
|
[%d $>(%flog task:dill)]
|
|
|
|
[%g $>(%deal task:gall)]
|
|
|
|
==
|
2020-05-05 08:28:37 +03:00
|
|
|
:: +sign: private response from another vane to eyre
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
|
|
|
+$ sign
|
2023-06-28 00:15:00 +03:00
|
|
|
$% [%ames $>(?(%done %boon %lost %tune) gift:ames)]
|
|
|
|
[%behn $>(%wake gift:behn)]
|
|
|
|
[%gall gift:gall]
|
|
|
|
[%clay gift:clay]
|
|
|
|
==
|
2018-09-20 02:29:36 +03:00
|
|
|
--
|
|
|
|
:: more structures
|
|
|
|
::
|
|
|
|
|%
|
|
|
|
++ axle
|
2019-02-09 02:03:46 +03:00
|
|
|
$: :: date: date at which http-server's state was updated to this data structure
|
2018-09-20 02:29:36 +03:00
|
|
|
::
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
date=%~2023.5.15
|
2018-09-20 02:29:36 +03:00
|
|
|
:: server-state: state of inbound requests
|
|
|
|
::
|
|
|
|
=server-state
|
|
|
|
==
|
|
|
|
:: +server-state: state relating to open inbound HTTP connections
|
|
|
|
::
|
|
|
|
+$ server-state
|
|
|
|
$: :: bindings: actions to dispatch to when a binding matches
|
|
|
|
::
|
|
|
|
:: Eyre is responsible for keeping its bindings sorted so that it
|
|
|
|
:: will trigger on the most specific binding first. Eyre should send
|
|
|
|
:: back an error response if an already bound binding exists.
|
|
|
|
::
|
|
|
|
:: TODO: It would be nice if we had a path trie. We could decompose
|
|
|
|
:: the :binding into a (map (unit @t) (trie knot =action)).
|
|
|
|
::
|
2023-03-03 02:00:27 +03:00
|
|
|
bindings=(list [=binding =duct =action])
|
2023-03-25 07:18:25 +03:00
|
|
|
:: cache: mapping from url to versioned entry
|
|
|
|
::
|
|
|
|
cache=(map url=@t [aeon=@ud val=(unit cache-entry)])
|
2020-09-30 16:07:27 +03:00
|
|
|
:: cors-registry: state used and managed by the +cors core
|
|
|
|
::
|
|
|
|
=cors-registry
|
2018-09-24 21:48:19 +03:00
|
|
|
:: connections: open http connections not fully complete
|
2018-09-21 02:36:04 +03:00
|
|
|
::
|
2023-03-03 02:00:27 +03:00
|
|
|
connections=(map duct outstanding-connection)
|
2023-05-19 12:31:01 +03:00
|
|
|
:: auth: state managed by the +authentication core
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
2023-05-19 12:31:01 +03:00
|
|
|
auth=authentication-state
|
2018-11-15 21:27:10 +03:00
|
|
|
:: channel-state: state managed by the +channel core
|
|
|
|
::
|
|
|
|
=channel-state
|
2019-03-21 08:28:32 +03:00
|
|
|
:: domains: domain-names that resolve to us
|
|
|
|
::
|
|
|
|
domains=(set turf)
|
|
|
|
:: http-config: our server configuration
|
|
|
|
::
|
|
|
|
=http-config
|
|
|
|
:: ports: live servers
|
|
|
|
::
|
|
|
|
ports=[insecure=@ud secure=(unit @ud)]
|
2019-04-10 00:03:21 +03:00
|
|
|
:: outgoing-duct: to unix
|
|
|
|
::
|
|
|
|
outgoing-duct=duct
|
2023-02-08 23:19:14 +03:00
|
|
|
:: verb: verbosity
|
2023-02-08 22:43:13 +03:00
|
|
|
::
|
2023-02-08 23:19:14 +03:00
|
|
|
verb=@
|
2018-09-24 21:48:19 +03:00
|
|
|
==
|
2018-11-15 21:27:10 +03:00
|
|
|
:: channel-request: an action requested on a channel
|
|
|
|
::
|
|
|
|
+$ channel-request
|
|
|
|
$% :: %ack: acknowledges that the client has received events up to :id
|
|
|
|
::
|
2018-11-21 04:06:04 +03:00
|
|
|
[%ack event-id=@ud]
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
:: %poke: pokes an application, validating :noun against :mark
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
[%poke request-id=@ud ship=@p app=term mark=@tas =noun]
|
|
|
|
:: %poke-json: pokes an application, translating :json to :mark
|
|
|
|
::
|
|
|
|
[%poke-json request-id=@ud ship=@p app=term mark=@tas =json]
|
2019-11-07 09:19:32 +03:00
|
|
|
:: %watch: subscribes to an application path
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
2019-11-14 06:38:13 +03:00
|
|
|
[%subscribe request-id=@ud ship=@p app=term =path]
|
2019-11-07 09:19:32 +03:00
|
|
|
:: %leave: unsubscribes from an application path
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
2019-11-14 06:38:13 +03:00
|
|
|
[%unsubscribe request-id=@ud subscription-id=@ud]
|
2019-06-14 00:53:04 +03:00
|
|
|
:: %delete: kills a channel
|
|
|
|
::
|
|
|
|
[%delete ~]
|
2018-11-15 21:27:10 +03:00
|
|
|
==
|
2020-10-19 16:56:05 +03:00
|
|
|
:: clog-timeout: the delay between acks after which clog-threshold kicks in
|
|
|
|
::
|
|
|
|
++ clog-timeout ~s30
|
|
|
|
:: clog-threshold: maximum per-subscription event buildup, after clog-timeout
|
|
|
|
::
|
|
|
|
++ clog-threshold 50
|
2018-11-20 01:59:58 +03:00
|
|
|
:: channel-timeout: the delay before a channel should be reaped
|
|
|
|
::
|
2019-01-11 03:35:09 +03:00
|
|
|
++ channel-timeout ~h12
|
2020-05-30 03:29:20 +03:00
|
|
|
:: session-timeout: the delay before an idle session expires
|
2020-05-29 16:28:13 +03:00
|
|
|
::
|
|
|
|
++ session-timeout ~d7
|
2018-09-20 02:29:36 +03:00
|
|
|
--
|
|
|
|
:: utilities
|
|
|
|
::
|
|
|
|
|%
|
2019-01-30 22:06:24 +03:00
|
|
|
:: +combine-octs: combine multiple octs into one
|
|
|
|
::
|
|
|
|
++ combine-octs
|
|
|
|
|= a=(list octs)
|
|
|
|
^- octs
|
|
|
|
:- %+ roll a
|
|
|
|
|= [=octs sum=@ud]
|
|
|
|
(add sum p.octs)
|
|
|
|
(can 3 a)
|
2019-01-12 01:15:17 +03:00
|
|
|
:: +prune-events: removes all items from the front of the queue up to :id
|
|
|
|
::
|
2020-10-19 16:56:05 +03:00
|
|
|
:: also produces, per request-id, the amount of events that have got acked,
|
|
|
|
:: for use with +subtract-acked-events.
|
|
|
|
::
|
2019-01-12 01:15:17 +03:00
|
|
|
++ prune-events
|
2020-10-19 16:56:05 +03:00
|
|
|
=| acked=(map @ud @ud)
|
2020-10-18 12:18:29 +03:00
|
|
|
|= [q=(qeu [id=@ud @ud channel-event]) id=@ud]
|
2020-10-19 16:56:05 +03:00
|
|
|
^+ [acked q]
|
2019-01-12 01:15:17 +03:00
|
|
|
:: if the queue is now empty, that's fine
|
|
|
|
::
|
2019-01-12 02:18:53 +03:00
|
|
|
?: =(~ q)
|
2020-10-19 16:56:05 +03:00
|
|
|
[acked ~]
|
2019-01-12 01:15:17 +03:00
|
|
|
::
|
2020-10-19 16:56:05 +03:00
|
|
|
=/ next=[item=[id=@ud request-id=@ud channel-event] _q] ~(get to q)
|
2019-01-12 01:15:17 +03:00
|
|
|
:: if the head of the queue is newer than the acknowledged id, we're done
|
|
|
|
::
|
2019-01-17 01:58:07 +03:00
|
|
|
?: (gth id.item.next id)
|
2020-10-19 16:56:05 +03:00
|
|
|
[acked q]
|
|
|
|
:: otherwise, note the ack, and check next item
|
|
|
|
::
|
|
|
|
%_ $
|
|
|
|
q +:next
|
2019-01-12 01:15:17 +03:00
|
|
|
::
|
2020-10-19 16:56:05 +03:00
|
|
|
acked
|
|
|
|
=, item.next
|
|
|
|
%+ ~(put by acked) request-id
|
|
|
|
+((~(gut by acked) request-id 0))
|
|
|
|
==
|
|
|
|
:: +subtract-acked-events: update the subscription map's pending ack counts
|
|
|
|
::
|
|
|
|
++ subtract-acked-events
|
|
|
|
|= [acked=(map @ud @ud) unacked=(map @ud @ud)]
|
|
|
|
^+ unacked
|
|
|
|
%+ roll ~(tap by acked)
|
|
|
|
|= [[rid=@ud ack=@ud] unacked=_unacked]
|
|
|
|
?~ sus=(~(get by unacked) rid)
|
|
|
|
unacked
|
|
|
|
%+ ~(put by unacked) rid
|
|
|
|
?: (lte u.sus ack) 0
|
|
|
|
(sub u.sus ack)
|
2022-11-28 20:30:04 +03:00
|
|
|
:: +find-channel-mode: deduce requested mode from headers
|
|
|
|
::
|
|
|
|
++ find-channel-mode
|
|
|
|
|= [met=method:http hes=header-list:http]
|
|
|
|
^- ?(%json %jam)
|
|
|
|
=+ ^- [hed=@t jam=@t]
|
2023-04-12 19:42:35 +03:00
|
|
|
?: ?=(%'GET' met) ['x-channel-format' 'application/x-urb-jam']
|
2023-04-12 20:19:13 +03:00
|
|
|
['content-type' 'application/x-urb-jam']
|
2022-11-28 20:30:04 +03:00
|
|
|
=+ typ=(bind (get-header:http hed hes) :(cork trip cass crip))
|
|
|
|
?:(=(`jam typ) %jam %json)
|
2018-11-15 21:27:10 +03:00
|
|
|
:: +parse-channel-request: parses a list of channel-requests
|
|
|
|
::
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
++ parse-channel-request
|
|
|
|
|= [mode=?(%json %jam) body=octs]
|
|
|
|
^- (each (list channel-request) @t)
|
|
|
|
?- mode
|
|
|
|
%json
|
2023-06-30 22:25:19 +03:00
|
|
|
?~ maybe-json=(de:json:html q.body)
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
|+'put body not json'
|
|
|
|
?~ maybe-requests=(parse-channel-request-json u.maybe-json)
|
|
|
|
|+'invalid channel json'
|
|
|
|
&+u.maybe-requests
|
|
|
|
::
|
|
|
|
%jam
|
|
|
|
?~ maybe-noun=(bind (slaw %uw q.body) cue)
|
|
|
|
|+'invalid request format'
|
|
|
|
?~ maybe-reqs=((soft (list channel-request)) u.maybe-noun)
|
|
|
|
~& [%miss u.maybe-noun]
|
|
|
|
|+'invalid request data'
|
|
|
|
&+u.maybe-reqs
|
|
|
|
==
|
|
|
|
:: +parse-channel-request-json: parses a json list of channel-requests
|
|
|
|
::
|
2018-11-16 00:43:10 +03:00
|
|
|
:: Parses a json array into a list of +channel-request. If any of the items
|
|
|
|
:: in the list fail to parse, the entire thing fails so we can 400 properly
|
|
|
|
:: to the client.
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
++ parse-channel-request-json
|
2018-11-16 00:43:10 +03:00
|
|
|
|= request-list=json
|
|
|
|
^- (unit (list channel-request))
|
|
|
|
:: parse top
|
|
|
|
::
|
|
|
|
=, dejs-soft:format
|
|
|
|
=- ((ar -) request-list)
|
|
|
|
::
|
|
|
|
|= item=json
|
|
|
|
^- (unit channel-request)
|
|
|
|
::
|
|
|
|
?~ maybe-key=((ot action+so ~) item)
|
|
|
|
~
|
|
|
|
?: =('ack' u.maybe-key)
|
2018-11-21 04:06:04 +03:00
|
|
|
((pe %ack (ot event-id+ni ~)) item)
|
2018-11-16 00:43:10 +03:00
|
|
|
?: =('poke' u.maybe-key)
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
%. item
|
|
|
|
%+ pe %poke-json
|
|
|
|
(ot id+ni ship+(su fed:ag) app+so mark+(su sym) json+some ~)
|
2018-11-16 00:43:10 +03:00
|
|
|
?: =('subscribe' u.maybe-key)
|
|
|
|
%. item
|
2019-11-14 06:38:13 +03:00
|
|
|
%+ pe %subscribe
|
2021-04-07 22:14:13 +03:00
|
|
|
(ot id+ni ship+(su fed:ag) app+so path+(su stap) ~)
|
2018-11-16 00:43:10 +03:00
|
|
|
?: =('unsubscribe' u.maybe-key)
|
|
|
|
%. item
|
2019-11-14 06:38:13 +03:00
|
|
|
%+ pe %unsubscribe
|
2019-03-27 01:52:32 +03:00
|
|
|
(ot id+ni subscription+ni ~)
|
2019-06-14 00:53:04 +03:00
|
|
|
?: =('delete' u.maybe-key)
|
|
|
|
`[%delete ~]
|
2018-11-16 00:43:10 +03:00
|
|
|
:: if we reached this, we have an invalid action key. fail parsing.
|
|
|
|
::
|
|
|
|
~
|
2023-05-22 20:48:28 +03:00
|
|
|
:: +auth-styling: css for login and eauth pages
|
|
|
|
::
|
|
|
|
++ auth-styling
|
|
|
|
'''
|
|
|
|
@import url("https://rsms.me/inter/inter.css");
|
|
|
|
@font-face {
|
|
|
|
font-family: "Source Code Pro";
|
|
|
|
src: url("https://storage.googleapis.com/media.urbit.org/fonts/scp-regular.woff");
|
|
|
|
font-weight: 400;
|
|
|
|
font-display: swap;
|
|
|
|
}
|
|
|
|
:root {
|
|
|
|
--red05: rgba(255,65,54,0.05);
|
|
|
|
--red100: rgba(255,65,54,1);
|
|
|
|
--blue05: rgba(33,157,255,0.05);
|
|
|
|
--blue30: rgba(33,157,255,0.3);
|
|
|
|
--blue100: rgba(33,157,255,1);
|
|
|
|
--black05: rgba(0,0,0,0.05);
|
|
|
|
--black20: rgba(0,0,0,0.2);
|
|
|
|
--black60: rgba(0,0,0,0.6);
|
|
|
|
--white: rgba(255,255,255,1);
|
|
|
|
}
|
|
|
|
html {
|
|
|
|
font-family: Inter, sans-serif;
|
|
|
|
height: 100%;
|
|
|
|
margin: 0;
|
|
|
|
width: 100%;
|
|
|
|
background: var(--white);
|
|
|
|
color: var(--black100);
|
|
|
|
-webkit-font-smoothing: antialiased;
|
|
|
|
line-height: 1.5;
|
|
|
|
font-size: 12px;
|
|
|
|
display: flex;
|
|
|
|
flex-flow: row nowrap;
|
|
|
|
justify-content: center;
|
|
|
|
}
|
|
|
|
body {
|
|
|
|
display: flex;
|
|
|
|
flex-flow: column nowrap;
|
|
|
|
justify-content: center;
|
|
|
|
max-width: 300px;
|
|
|
|
padding: 1rem;
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
body.local #eauth,
|
|
|
|
body.eauth #local {
|
|
|
|
display: none;
|
|
|
|
min-height: 100%;
|
|
|
|
}
|
|
|
|
#eauth input {
|
|
|
|
/*NOTE dumb hack to get approx equal height with #local */
|
|
|
|
margin-bottom: 15px;
|
|
|
|
}
|
|
|
|
body nav div {
|
|
|
|
display: inline-block;
|
|
|
|
padding: 8px 16px;
|
|
|
|
border-radius: 4px;
|
|
|
|
color: var(--blue100);
|
|
|
|
border: 1px solid var(--blue100);
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
body.local nav div.local,
|
|
|
|
body.eauth nav div.eauth {
|
|
|
|
background-color: var(--blue100);
|
|
|
|
color: var(--white);
|
|
|
|
cursor: default;
|
|
|
|
}
|
|
|
|
nav div.local {
|
|
|
|
border-right: none;
|
|
|
|
border-top-right-radius: 0;
|
|
|
|
border-bottom-right-radius: 0;
|
|
|
|
}
|
|
|
|
nav div.eauth {
|
|
|
|
border-left: none;
|
|
|
|
border-top-left-radius: 0;
|
|
|
|
border-bottom-left-radius: 0;
|
|
|
|
}
|
|
|
|
body > *,
|
|
|
|
form > input {
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
form {
|
|
|
|
display: flex;
|
|
|
|
flex-flow: column;
|
|
|
|
align-items: flex-start;
|
|
|
|
}
|
|
|
|
input {
|
|
|
|
background: transparent;
|
|
|
|
border: 1px solid var(--black20);
|
|
|
|
padding: 8px;
|
|
|
|
border-radius: 4px;
|
|
|
|
font-size: inherit;
|
|
|
|
color: var(--black);
|
|
|
|
box-shadow: none;
|
|
|
|
}
|
|
|
|
input:disabled {
|
|
|
|
background: var(--black05);
|
|
|
|
color: var(--black60);
|
|
|
|
}
|
|
|
|
input:focus {
|
|
|
|
outline: none;
|
|
|
|
border-color: var(--blue30);
|
|
|
|
}
|
|
|
|
input:invalid:not(:focus) {
|
|
|
|
background: var(--red05);
|
|
|
|
border-color: var(--red100);
|
|
|
|
outline: none;
|
|
|
|
color: var(--red100);
|
|
|
|
}
|
|
|
|
button[type=submit] {
|
|
|
|
margin-top: 16px;
|
|
|
|
padding: 8px 16px;
|
|
|
|
border-radius: 4px;
|
|
|
|
background: var(--blue100);
|
|
|
|
color: var(--white);
|
|
|
|
border: 1px solid var(--blue100);
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
input:invalid ~ button[type=submit] {
|
|
|
|
border-color: currentColor;
|
|
|
|
background: var(--blue05);
|
|
|
|
color: var(--blue30);
|
|
|
|
pointer-events: none;
|
|
|
|
}
|
|
|
|
span.guest {
|
|
|
|
color: var(--black20);
|
|
|
|
}
|
|
|
|
span.failed {
|
|
|
|
display: flex;
|
|
|
|
flex-flow: row nowrap;
|
|
|
|
height: 16px;
|
|
|
|
align-items: center;
|
|
|
|
margin-top: 6px;
|
|
|
|
color: var(--red100);
|
|
|
|
}
|
|
|
|
span.failed svg {
|
|
|
|
height: 12px;
|
|
|
|
margin-right: 6px;
|
|
|
|
}
|
|
|
|
span.failed circle,
|
|
|
|
span.failed line {
|
|
|
|
fill: transparent;
|
|
|
|
stroke: currentColor
|
|
|
|
}
|
|
|
|
.mono {
|
|
|
|
font-family: 'Source Code Pro', monospace;
|
|
|
|
}
|
|
|
|
@media all and (prefers-color-scheme: dark) {
|
|
|
|
:root {
|
|
|
|
--white: rgb(51, 51, 51);
|
|
|
|
--black100: rgba(255,255,255,1);
|
|
|
|
--black05: rgba(255,255,255,0.05);
|
|
|
|
--black20: rgba(255,255,255,0.2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
'''
|
2018-09-27 02:18:40 +03:00
|
|
|
:: +login-page: internal page to login to an Urbit
|
|
|
|
::
|
|
|
|
++ login-page
|
2023-05-19 11:35:23 +03:00
|
|
|
|= [redirect-url=(unit @t) our=@p =identity eauth=(unit ?) failed=?]
|
2018-09-27 02:18:40 +03:00
|
|
|
^- octs
|
|
|
|
=+ redirect-str=?~(redirect-url "" (trip u.redirect-url))
|
|
|
|
%- as-octs:mimes:html
|
|
|
|
%- crip
|
|
|
|
%- en-xml:html
|
2020-12-03 06:36:39 +03:00
|
|
|
=/ favicon %+
|
|
|
|
weld "<svg width='10' height='10' viewBox='0 0 10 10' xmlns='http://www.w3.org/2000/svg'>"
|
|
|
|
"<circle r='3.09' cx='5' cy='5' /></svg>"
|
2018-09-27 02:18:40 +03:00
|
|
|
;html
|
|
|
|
;head
|
2019-07-02 01:16:52 +03:00
|
|
|
;meta(charset "utf-8");
|
2020-02-11 03:48:47 +03:00
|
|
|
;meta(name "viewport", content "width=device-width, initial-scale=1, shrink-to-fit=no");
|
2020-12-03 06:36:39 +03:00
|
|
|
;link(rel "icon", type "image/svg+xml", href (weld "data:image/svg+xml;utf8," favicon));
|
2022-05-29 23:22:20 +03:00
|
|
|
;title:"Urbit"
|
2023-05-22 20:48:28 +03:00
|
|
|
;style:"{(trip auth-styling)}"
|
2023-05-19 11:35:23 +03:00
|
|
|
;style:"{?^(eauth "" "nav \{ display: none; }")}"
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
;script:"our = '{(scow %p our)}';"
|
|
|
|
;script:'''
|
2023-05-19 11:35:23 +03:00
|
|
|
let name, pass;
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
function setup(isEauth) {
|
|
|
|
name = document.getElementById('name');
|
2023-05-19 11:35:23 +03:00
|
|
|
pass = document.getElementById('pass');
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
if (isEauth) goEauth(); else goLocal();
|
|
|
|
}
|
|
|
|
function goLocal() {
|
|
|
|
document.body.className = 'local';
|
2023-05-19 11:35:23 +03:00
|
|
|
pass.focus();
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
}
|
|
|
|
function goEauth() {
|
|
|
|
document.body.className = 'eauth';
|
2023-05-19 11:35:23 +03:00
|
|
|
name.focus();
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
}
|
|
|
|
function doEauth() {
|
|
|
|
console.log('mb get value from event', event);
|
|
|
|
console.log('compare', name.value, our);
|
|
|
|
if (name.value == our) {
|
|
|
|
event.preventDefault();
|
|
|
|
goLocal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
'''
|
2018-09-27 02:18:40 +03:00
|
|
|
==
|
|
|
|
;body
|
2023-05-19 11:35:23 +03:00
|
|
|
=class "{?:(=(`& eauth) "eauth" "local")}"
|
|
|
|
=onload "setup({?:(=(`& eauth) "true" "false")})"
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
;nav
|
|
|
|
;div.local(onclick "goLocal()"):"Local"
|
|
|
|
;div.eauth(onclick "goEauth()"):"EAuth"
|
|
|
|
==
|
|
|
|
;div#local
|
|
|
|
;p:"Urbit ID"
|
|
|
|
;input(value "{(scow %p our)}", disabled "true", class "mono");
|
|
|
|
;p:"Access Key"
|
|
|
|
;form(action "/~/login", method "post", enctype "application/x-www-form-urlencoded")
|
|
|
|
;input
|
|
|
|
=type "password"
|
|
|
|
=name "password"
|
2023-05-19 11:35:23 +03:00
|
|
|
=id "pass"
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
=placeholder "sampel-ticlyt-migfun-falmel"
|
|
|
|
=class "mono"
|
|
|
|
=required "true"
|
|
|
|
=minlength "27"
|
|
|
|
=maxlength "27"
|
2023-05-19 11:35:23 +03:00
|
|
|
=pattern "((?:[a-z]\{6}-)\{3}(?:[a-z]\{6}))";
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
;input(type "hidden", name "redirect", value redirect-str);
|
|
|
|
;+ ?. failed ;span;
|
|
|
|
;span.failed
|
|
|
|
;svg(xmlns "http://www.w3.org/2000/svg", viewBox "0 0 12 12")
|
|
|
|
;circle(cx "6", cy "6", r "5.5");
|
|
|
|
;line(x1 "3.27", y1 "3.27", x2 "8.73", y2 "8.73");
|
|
|
|
;line(x1 "8.73", y1 "3.27", x2 "3.27", y2 "8.73");
|
|
|
|
==
|
|
|
|
Key is incorrect
|
2020-02-11 03:48:47 +03:00
|
|
|
==
|
2020-12-03 06:36:39 +03:00
|
|
|
;button(type "submit"):"Continue"
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
==
|
|
|
|
==
|
|
|
|
;div#eauth
|
|
|
|
;form(action "/~/login", method "post", onsubmit "return doEauth()")
|
|
|
|
;p:"Urbit ID"
|
2023-05-19 11:35:23 +03:00
|
|
|
;input.mono
|
|
|
|
=name "name"
|
|
|
|
=id "name"
|
|
|
|
=placeholder "{(scow %p our)}"
|
|
|
|
=required "true"
|
|
|
|
=minlength "4"
|
|
|
|
=maxlength "57"
|
|
|
|
=pattern "~((([a-z]\{6})\{1,2}-\{0,2})+|[a-z]\{3})";
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
;p
|
|
|
|
; You will be redirected to your own web interface, to authorize
|
|
|
|
; logging in to
|
|
|
|
;span.mono:"{(scow %p our)}"
|
|
|
|
; .
|
|
|
|
==
|
|
|
|
;input(type "hidden", name "redirect", value redirect-str);
|
|
|
|
;button(name "eauth", type "submit"):"Continue..."
|
|
|
|
==
|
2018-09-27 02:18:40 +03:00
|
|
|
==
|
2023-05-09 16:10:14 +03:00
|
|
|
;* ?. ?=(%fake -.identity) ~
|
|
|
|
=+ id=(trim 29 (scow %p who.identity))
|
|
|
|
;+ ;span.guest.mono
|
|
|
|
; Current guest identity:
|
|
|
|
;br;
|
|
|
|
; {p.id}
|
|
|
|
;br;
|
|
|
|
; {q.id}
|
|
|
|
==
|
2018-09-27 02:18:40 +03:00
|
|
|
==
|
2020-12-03 06:36:39 +03:00
|
|
|
;script:'''
|
|
|
|
var failSpan = document.querySelector('.failed');
|
|
|
|
if (failSpan) {
|
|
|
|
document.querySelector("input[type=password]")
|
|
|
|
.addEventListener('keyup', function (event) {
|
|
|
|
failSpan.style.display = 'none';
|
|
|
|
});
|
|
|
|
}
|
|
|
|
'''
|
2018-09-27 02:18:40 +03:00
|
|
|
==
|
2023-05-23 20:31:01 +03:00
|
|
|
:: +eauth-error-page: render an eauth error reporting page
|
|
|
|
::
|
|
|
|
:: optionally redirects the user back to either the login page if we're
|
|
|
|
:: acting as server, or the host if we're the client.
|
|
|
|
::
|
|
|
|
++ eauth-error-page
|
|
|
|
|= $= return
|
|
|
|
$? ~ :: no known return target
|
|
|
|
[%server last=@t] :: we are the host, return to login
|
|
|
|
[%client goal=@t] :: we are the client, return to host
|
|
|
|
==
|
|
|
|
^- octs
|
|
|
|
%- as-octs:mimes:html
|
|
|
|
%- crip
|
|
|
|
%- en-xml:html
|
|
|
|
=/ return=(unit @t)
|
|
|
|
?- return
|
|
|
|
~ ~
|
|
|
|
[%server *] %- some
|
|
|
|
%^ cat 3 '/~/login?eauth&redirect='
|
|
|
|
(crip (en-urlt:html (trip last.return)))
|
|
|
|
[%client *] `goal.return ::TODO plus nonce? or abort?
|
|
|
|
==
|
|
|
|
=/ favicon %+
|
|
|
|
weld "<svg width='10' height='10' viewBox='0 0 10 10' xmlns='http://www.w3.org/2000/svg'>"
|
|
|
|
"<circle r='3.09' cx='5' cy='5' /></svg>"
|
|
|
|
=/ msg=tape
|
|
|
|
?~ return "Something went wrong!"
|
|
|
|
"Something went wrong! You will be redirected back..."
|
|
|
|
;html
|
|
|
|
;head
|
|
|
|
;* ?~ return ~
|
|
|
|
:_ ~
|
|
|
|
;meta(http-equiv "Refresh", content "5; url={(trip u.return)}");
|
|
|
|
;meta(charset "utf-8");
|
|
|
|
;meta(name "viewport", content "width=device-width, initial-scale=1, shrink-to-fit=no");
|
|
|
|
;link(rel "icon", type "image/svg+xml", href (weld "data:image/svg+xml;utf8," favicon));
|
|
|
|
;title:"Urbit"
|
|
|
|
;style:'''
|
|
|
|
@import url("https://rsms.me/inter/inter.css");
|
|
|
|
:root {
|
|
|
|
--black60: rgba(0,0,0,0.6);
|
|
|
|
--white: rgba(255,255,255,1);
|
|
|
|
}
|
|
|
|
html {
|
|
|
|
font-family: Inter, sans-serif;
|
|
|
|
height: 100%;
|
|
|
|
margin: 0;
|
|
|
|
width: 100%;
|
|
|
|
background: var(--white);
|
|
|
|
color: var(--black60);
|
|
|
|
-webkit-font-smoothing: antialiased;
|
|
|
|
line-height: 1.5;
|
|
|
|
font-size: 12px;
|
|
|
|
display: flex;
|
|
|
|
flex-flow: row nowrap;
|
|
|
|
justify-content: center;
|
|
|
|
}
|
|
|
|
body {
|
|
|
|
display: flex;
|
|
|
|
flex-flow: column nowrap;
|
|
|
|
justify-content: center;
|
|
|
|
max-width: 300px;
|
|
|
|
padding: 1rem;
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
'''
|
|
|
|
==
|
|
|
|
;body:"{msg}"
|
|
|
|
==
|
2018-11-21 04:06:04 +03:00
|
|
|
:: +render-tang-to-marl: renders a tang and adds <br/> tags between each line
|
2018-10-11 01:26:51 +03:00
|
|
|
::
|
2018-11-21 04:06:04 +03:00
|
|
|
++ render-tang-to-marl
|
2020-11-26 17:09:31 +03:00
|
|
|
|= [wid=@u tan=tang]
|
2018-10-11 01:26:51 +03:00
|
|
|
^- marl
|
2020-11-25 23:22:55 +03:00
|
|
|
=/ raw=(list tape) (zing (turn tan |=(a=tank (wash 0^wid a))))
|
2018-10-11 01:26:51 +03:00
|
|
|
::
|
|
|
|
|- ^- marl
|
|
|
|
?~ raw ~
|
|
|
|
[;/(i.raw) ;br; $(raw t.raw)]
|
2018-11-21 04:06:04 +03:00
|
|
|
:: +render-tang-to-wall: renders tang as text lines
|
|
|
|
::
|
|
|
|
++ render-tang-to-wall
|
2020-11-26 17:09:31 +03:00
|
|
|
|= [wid=@u tan=tang]
|
2018-11-21 04:06:04 +03:00
|
|
|
^- wall
|
|
|
|
(zing (turn tan |=(a=tank (wash 0^wid a))))
|
|
|
|
:: +wall-to-octs: text to binary output
|
|
|
|
::
|
|
|
|
++ wall-to-octs
|
|
|
|
|= =wall
|
|
|
|
^- (unit octs)
|
|
|
|
::
|
|
|
|
?: =(~ wall)
|
|
|
|
~
|
|
|
|
::
|
|
|
|
:- ~
|
|
|
|
%- as-octs:mimes:html
|
|
|
|
%- crip
|
2021-03-28 10:57:33 +03:00
|
|
|
%- zing ^- ^wall
|
|
|
|
%- zing ^- (list ^wall)
|
2018-11-21 04:06:04 +03:00
|
|
|
%+ turn wall
|
|
|
|
|= t=tape
|
2021-03-28 10:57:33 +03:00
|
|
|
^- ^wall
|
|
|
|
~[t "\0a"]
|
2018-10-10 21:51:52 +03:00
|
|
|
:: +internal-server-error: 500 page, with a tang
|
|
|
|
::
|
|
|
|
++ internal-server-error
|
2018-10-11 01:26:51 +03:00
|
|
|
|= [authorized=? url=@t t=tang]
|
2018-10-10 21:51:52 +03:00
|
|
|
^- octs
|
|
|
|
%- as-octs:mimes:html
|
|
|
|
%- crip
|
|
|
|
%- en-xml:html
|
|
|
|
;html
|
|
|
|
;head
|
|
|
|
;title:"500 Internal Server Error"
|
|
|
|
==
|
|
|
|
;body
|
|
|
|
;h1:"Internal Server Error"
|
2020-11-04 03:02:11 +03:00
|
|
|
;p:"There was an error while handling the request for {(trip url)}."
|
2018-10-10 21:51:52 +03:00
|
|
|
;* ?: authorized
|
|
|
|
;=
|
2018-11-21 04:06:04 +03:00
|
|
|
;code:"*{(render-tang-to-marl 80 t)}"
|
2018-10-10 21:51:52 +03:00
|
|
|
==
|
|
|
|
~
|
|
|
|
==
|
|
|
|
==
|
2019-03-27 01:52:32 +03:00
|
|
|
:: +error-page: error page, with an error string if logged in
|
2019-03-21 02:00:46 +03:00
|
|
|
::
|
2019-03-21 23:58:37 +03:00
|
|
|
++ error-page
|
|
|
|
|= [code=@ud authorized=? url=@t t=tape]
|
2019-03-21 02:00:46 +03:00
|
|
|
^- octs
|
2019-03-21 23:58:37 +03:00
|
|
|
::
|
|
|
|
=/ code-as-tape=tape (format-ud-as-integer code)
|
|
|
|
=/ message=tape
|
2020-11-04 03:02:11 +03:00
|
|
|
?+ code "{(scow %ud code)} Error"
|
2020-06-12 03:13:13 +03:00
|
|
|
%400 "Bad Request"
|
|
|
|
%403 "Forbidden"
|
|
|
|
%404 "Not Found"
|
|
|
|
%405 "Method Not Allowed"
|
|
|
|
%500 "Internal Server Error"
|
|
|
|
==
|
2019-03-21 23:58:37 +03:00
|
|
|
::
|
2019-03-21 02:00:46 +03:00
|
|
|
%- as-octs:mimes:html
|
|
|
|
%- crip
|
|
|
|
%- en-xml:html
|
|
|
|
;html
|
|
|
|
;head
|
2019-03-21 23:58:37 +03:00
|
|
|
;title:"{code-as-tape} {message}"
|
2019-03-21 02:00:46 +03:00
|
|
|
==
|
|
|
|
;body
|
2019-03-21 23:58:37 +03:00
|
|
|
;h1:"{message}"
|
2020-11-04 03:02:11 +03:00
|
|
|
;p:"There was an error while handling the request for {(trip url)}."
|
2019-03-21 02:00:46 +03:00
|
|
|
;* ?: authorized
|
|
|
|
;=
|
|
|
|
;code:"{t}"
|
|
|
|
==
|
|
|
|
~
|
|
|
|
==
|
|
|
|
==
|
2018-10-10 21:51:52 +03:00
|
|
|
:: +format-ud-as-integer: prints a number for consumption outside urbit
|
|
|
|
::
|
|
|
|
++ format-ud-as-integer
|
|
|
|
|= a=@ud
|
2019-01-17 02:24:30 +03:00
|
|
|
^- tape
|
|
|
|
?: =(0 a) ['0' ~]
|
2018-10-10 21:51:52 +03:00
|
|
|
%- flop
|
|
|
|
|- ^- tape
|
|
|
|
?:(=(0 a) ~ [(add '0' (mod a 10)) $(a (div a 10))])
|
2019-06-04 00:34:01 +03:00
|
|
|
:: +host-matches: %.y if the site :binding should be used to handle :host
|
|
|
|
::
|
|
|
|
++ host-matches
|
|
|
|
|= [binding=(unit @t) host=(unit @t)]
|
|
|
|
^- ?
|
|
|
|
:: if the binding allows for matching anything, match
|
|
|
|
::
|
|
|
|
?~ binding
|
|
|
|
%.y
|
|
|
|
:: if the host is ~, that means we're trying to bind nothing to a real
|
|
|
|
:: binding. fail.
|
|
|
|
::
|
|
|
|
?~ host
|
|
|
|
%.n
|
|
|
|
:: otherwise, do a straight comparison
|
|
|
|
::
|
|
|
|
=(u.binding u.host)
|
2020-06-11 02:42:21 +03:00
|
|
|
:: +find-suffix: returns [~ /tail] if :full is (weld :prefix /tail)
|
2018-10-11 21:28:27 +03:00
|
|
|
::
|
2020-06-11 02:42:21 +03:00
|
|
|
++ find-suffix
|
2018-10-11 21:28:27 +03:00
|
|
|
|= [prefix=path full=path]
|
2020-06-11 02:42:21 +03:00
|
|
|
^- (unit path)
|
2018-10-11 21:28:27 +03:00
|
|
|
?~ prefix
|
2020-06-11 02:42:21 +03:00
|
|
|
`full
|
2018-10-11 21:28:27 +03:00
|
|
|
?~ full
|
2020-06-11 02:42:21 +03:00
|
|
|
~
|
2018-10-11 21:28:27 +03:00
|
|
|
?. =(i.prefix i.full)
|
2020-06-11 02:42:21 +03:00
|
|
|
~
|
2018-10-11 21:28:27 +03:00
|
|
|
$(prefix t.prefix, full t.full)
|
2018-10-04 00:05:36 +03:00
|
|
|
:: +simplified-url-parser: returns [(each @if @t) (unit port=@ud)]
|
|
|
|
::
|
|
|
|
++ simplified-url-parser
|
|
|
|
;~ plug
|
|
|
|
;~ pose
|
|
|
|
%+ stag %ip
|
|
|
|
=+ tod=(ape:ag ted:ab)
|
|
|
|
%+ bass 256
|
|
|
|
;~(plug tod (stun [3 3] ;~(pfix dot tod)))
|
|
|
|
::
|
|
|
|
(stag %site (cook crip (star ;~(pose dot alp))))
|
|
|
|
==
|
|
|
|
;~ pose
|
|
|
|
(stag ~ ;~(pfix col dim:ag))
|
|
|
|
(easy ~)
|
|
|
|
==
|
|
|
|
==
|
2022-09-24 12:52:34 +03:00
|
|
|
:: +host-sans-port: strip the :<port> from a host string
|
|
|
|
::
|
|
|
|
++ host-sans-port
|
|
|
|
;~ sfix
|
|
|
|
%+ cook crip
|
|
|
|
%- star
|
|
|
|
;~ less
|
|
|
|
;~(plug col (punt dem) ;~(less next (easy ~)))
|
|
|
|
next
|
|
|
|
==
|
|
|
|
(star next)
|
|
|
|
==
|
2018-10-26 02:32:54 +03:00
|
|
|
:: +per-server-event: per-event server core
|
2018-09-20 02:29:36 +03:00
|
|
|
::
|
|
|
|
++ per-server-event
|
2021-06-15 00:15:45 +03:00
|
|
|
~% %eyre-per-server-event ..part ~
|
2018-11-15 21:27:10 +03:00
|
|
|
:: gate that produces the +per-server-event core from event information
|
|
|
|
::
|
2020-12-06 13:55:19 +03:00
|
|
|
|= [[eny=@ =duct now=@da rof=roof] state=server-state]
|
2019-11-14 00:39:29 +03:00
|
|
|
=/ eyre-id (scot %ta (cat 3 'eyre_' (scot %uv (sham duct))))
|
2018-09-20 02:29:36 +03:00
|
|
|
|%
|
2019-04-30 23:38:40 +03:00
|
|
|
:: +request-local: bypass authentication for local lens connections
|
|
|
|
::
|
|
|
|
++ request-local
|
|
|
|
|= [secure=? =address =request:http]
|
|
|
|
^- [(list move) server-state]
|
|
|
|
::
|
|
|
|
=/ act [%app app=%lens]
|
2019-11-09 10:31:11 +03:00
|
|
|
::
|
2023-03-03 02:00:27 +03:00
|
|
|
=/ connection=outstanding-connection
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
[act [& secure address request] [*@uv [%ours ~]] ~ 0]
|
2019-04-30 23:38:40 +03:00
|
|
|
::
|
|
|
|
=. connections.state
|
2023-02-09 01:03:02 +03:00
|
|
|
%. (~(put by connections.state) duct connection)
|
2023-02-09 20:55:08 +03:00
|
|
|
(trace 2 |.("{<duct>} creating local"))
|
2019-04-30 23:38:40 +03:00
|
|
|
::
|
|
|
|
:_ state
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(subscribe-to-app [%ours ~] app.act inbound-request.connection)
|
2018-09-21 02:36:04 +03:00
|
|
|
:: +request: starts handling an inbound http request
|
|
|
|
::
|
2018-09-20 02:29:36 +03:00
|
|
|
++ request
|
2019-02-09 00:16:42 +03:00
|
|
|
|= [secure=? =address =request:http]
|
2018-09-20 02:29:36 +03:00
|
|
|
^- [(list move) server-state]
|
2020-10-09 15:07:05 +03:00
|
|
|
=* headers header-list.request
|
2020-05-31 18:43:35 +03:00
|
|
|
:: for requests from localhost, respect the "forwarded" header
|
|
|
|
::
|
2020-10-29 16:24:24 +03:00
|
|
|
=/ [secure=? =^address]
|
|
|
|
=* same [secure address]
|
|
|
|
?. =([%ipv4 .127.0.0.1] address) same
|
|
|
|
?~ forwards=(forwarded-params headers) same
|
|
|
|
:- (fall (forwarded-secure u.forwards) secure)
|
|
|
|
(fall (forwarded-for u.forwards) address)
|
2018-09-20 02:29:36 +03:00
|
|
|
::
|
2020-10-09 15:07:05 +03:00
|
|
|
=/ host (get-header:http 'host' headers)
|
2023-03-03 02:00:27 +03:00
|
|
|
=/ [=action suburl=@t]
|
2020-06-11 02:42:21 +03:00
|
|
|
(get-action-for-binding host url.request)
|
2018-10-10 21:51:52 +03:00
|
|
|
::
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::TODO we might want to mint new identities only for requests that end
|
|
|
|
:: up going into userspace, not the ones that get handled by eyre.
|
|
|
|
:: perhaps that distinction, where userspace requests are async, but
|
|
|
|
:: eyre-handled requests are always synchronous, provides a fruitful
|
|
|
|
:: angle for refactoring...
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=^ [suv=@uv =identity som=(list move)] state
|
|
|
|
(session-for-request:authentication request)
|
|
|
|
=; [moz=(list move) sat=server-state]
|
|
|
|
[(weld som moz) sat]
|
|
|
|
::
|
|
|
|
=/ authenticated ?=(%ours -.identity)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: if we have no eauth endpoint yet, and the request is authenticated,
|
|
|
|
:: deduce it from the hostname
|
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
=? endpoint.auth.state
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
?& authenticated
|
|
|
|
?=(^ host)
|
2023-05-19 12:31:01 +03:00
|
|
|
?=(~ auth.endpoint.auth.state)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
==
|
|
|
|
%- (trace 2 |.("eauth: storing endpoint at {(trip u.host)}"))
|
2023-06-09 16:46:04 +03:00
|
|
|
:+ user.endpoint.auth.state
|
|
|
|
`(cat 3 ?:(secure 'https://' 'http://') u.host)
|
|
|
|
now
|
2018-09-21 02:36:04 +03:00
|
|
|
:: record that we started an asynchronous response
|
|
|
|
::
|
2023-03-03 02:00:27 +03:00
|
|
|
=/ connection=outstanding-connection
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
[action [authenticated secure address request] [suv identity] ~ 0]
|
2018-10-25 00:31:19 +03:00
|
|
|
=. connections.state
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:: NB: required by +handle-response and +handle-request:authentication.
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: XX optimize, not all requests are asynchronous
|
2023-05-04 01:40:22 +03:00
|
|
|
::
|
2018-10-25 00:31:19 +03:00
|
|
|
(~(put by connections.state) duct connection)
|
2022-09-29 03:31:47 +03:00
|
|
|
:: redirect to https if insecure, redirects enabled
|
|
|
|
:: and secure port live
|
2022-09-03 17:58:09 +03:00
|
|
|
::
|
|
|
|
?: ?& !secure
|
|
|
|
redirect.http-config.state
|
|
|
|
?=(^ secure.ports.state)
|
|
|
|
==
|
|
|
|
=/ location=@t
|
2022-10-01 12:31:59 +03:00
|
|
|
%+ rap 3
|
|
|
|
:~ 'https://'
|
|
|
|
(rash (fall host '') host-sans-port)
|
|
|
|
?: =(443 u.secure.ports.state)
|
|
|
|
''
|
|
|
|
(crip ":{(a-co:co u.secure.ports.state)}")
|
|
|
|
?: ?=([[~ ~] ~] (parse-request-line url.request))
|
|
|
|
'/'
|
|
|
|
url.request
|
2022-09-03 17:58:09 +03:00
|
|
|
==
|
|
|
|
%- handle-response
|
|
|
|
:* %start
|
|
|
|
:- status-code=301
|
|
|
|
headers=['location' location]~
|
|
|
|
data=~
|
|
|
|
complete=%.y
|
|
|
|
==
|
2020-09-30 16:07:27 +03:00
|
|
|
:: figure out whether this is a cors request,
|
|
|
|
:: whether the origin is approved or not,
|
|
|
|
:: and maybe add it to the "pending approval" set
|
|
|
|
::
|
|
|
|
=/ origin=(unit origin)
|
2020-10-09 15:07:05 +03:00
|
|
|
(get-header:http 'origin' headers)
|
2020-09-30 16:07:27 +03:00
|
|
|
=^ cors-approved requests.cors-registry.state
|
|
|
|
=, cors-registry.state
|
|
|
|
?~ origin [| requests]
|
|
|
|
?: (~(has in approved) u.origin) [& requests]
|
|
|
|
?: (~(has in rejected) u.origin) [| requests]
|
|
|
|
[| (~(put in requests) u.origin)]
|
|
|
|
:: if this is a cors preflight request from an approved origin
|
|
|
|
:: handle it synchronously
|
|
|
|
::
|
|
|
|
?: &(?=(^ origin) cors-approved ?=(%'OPTIONS' method.request))
|
|
|
|
%- handle-response
|
|
|
|
=; =header-list:http
|
|
|
|
[%start [204 header-list] ~ &]
|
2020-10-09 15:07:05 +03:00
|
|
|
:: allow the method and headers that were asked for,
|
|
|
|
:: falling back to wildcard if none specified
|
|
|
|
::
|
2020-09-30 16:07:27 +03:00
|
|
|
::NOTE +handle-response will add the rest of the headers
|
2020-10-09 15:07:05 +03:00
|
|
|
::
|
|
|
|
:~ :- 'Access-Control-Allow-Methods'
|
|
|
|
=- (fall - '*')
|
|
|
|
(get-header:http 'access-control-request-method' headers)
|
|
|
|
::
|
|
|
|
:- 'Access-Control-Allow-Headers'
|
|
|
|
=- (fall - '*')
|
|
|
|
(get-header:http 'access-control-request-headers' headers)
|
2020-09-30 16:07:27 +03:00
|
|
|
==
|
2023-03-25 07:18:25 +03:00
|
|
|
:: handle requests to the cache
|
|
|
|
::
|
|
|
|
=/ entry (~(get by cache.state) url.request)
|
|
|
|
?: &(?=(^ entry) ?=(%'GET' method.request))
|
|
|
|
(handle-cache-req authenticated request val.u.entry)
|
2018-09-27 21:16:59 +03:00
|
|
|
::
|
2019-01-11 03:35:09 +03:00
|
|
|
?- -.action
|
2018-09-20 02:29:36 +03:00
|
|
|
%gen
|
2020-05-05 08:28:37 +03:00
|
|
|
=/ bek=beak [our desk.generator.action da+now]
|
2020-11-22 00:04:18 +03:00
|
|
|
=/ sup=spur path.generator.action
|
2023-05-22 16:12:09 +03:00
|
|
|
=/ ski (rof ~ /eyre %ca bek sup)
|
2020-05-08 08:29:25 +03:00
|
|
|
=/ cag=cage (need (need ski))
|
|
|
|
?> =(%vase p.cag)
|
|
|
|
=/ gat=vase !<(vase q.cag)
|
2020-07-03 08:08:38 +03:00
|
|
|
=/ res=toon
|
2023-05-22 16:12:09 +03:00
|
|
|
%- mock :_ (look rof ~ /eyre)
|
2020-07-03 08:08:38 +03:00
|
|
|
:_ [%9 2 %0 1] |.
|
2020-05-05 08:28:37 +03:00
|
|
|
%+ slam
|
|
|
|
%+ slam gat
|
2020-07-03 00:41:59 +03:00
|
|
|
!>([[now=now eny=eny bek=bek] ~ ~])
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::TODO should get passed the requester's identity
|
2020-05-05 08:28:37 +03:00
|
|
|
!>([authenticated request])
|
2020-07-03 08:08:38 +03:00
|
|
|
?: ?=(%2 -.res)
|
2020-05-05 08:28:37 +03:00
|
|
|
=+ connection=(~(got by connections.state) duct)
|
|
|
|
%^ return-static-data-on-duct 500 'text/html'
|
|
|
|
%: internal-server-error
|
|
|
|
authenticated.inbound-request.connection
|
|
|
|
url.request.inbound-request.connection
|
2020-07-03 08:08:38 +03:00
|
|
|
leaf+"generator crashed"
|
2020-05-05 08:28:37 +03:00
|
|
|
p.res
|
|
|
|
==
|
2020-07-03 08:08:38 +03:00
|
|
|
?: ?=(%1 -.res)
|
|
|
|
=+ connection=(~(got by connections.state) duct)
|
|
|
|
%^ return-static-data-on-duct 500 'text/html'
|
|
|
|
%: internal-server-error
|
|
|
|
authenticated.inbound-request.connection
|
|
|
|
url.request.inbound-request.connection
|
|
|
|
leaf+"scry blocked on"
|
2020-12-06 13:55:19 +03:00
|
|
|
(fall (bind (bind ((soft path) p.res) smyt) (late ~)) ~)
|
2020-07-03 08:08:38 +03:00
|
|
|
==
|
|
|
|
=/ result ;;(simple-payload:http +.p.res)
|
2020-05-05 08:28:37 +03:00
|
|
|
:: ensure we have a valid content-length header
|
2018-09-21 02:36:04 +03:00
|
|
|
::
|
2020-05-05 08:28:37 +03:00
|
|
|
:: We pass on the response and the headers the generator produces, but
|
|
|
|
:: ensure that we have a single content-length header set correctly in
|
|
|
|
:: the returned if this has a body, and has no content-length if there
|
|
|
|
:: is no body returned to the client.
|
2018-10-10 21:51:52 +03:00
|
|
|
::
|
2020-05-05 08:28:37 +03:00
|
|
|
=. headers.response-header.result
|
|
|
|
?~ data.result
|
|
|
|
(delete-header:http 'content-length' headers.response-header.result)
|
2018-10-11 01:26:51 +03:00
|
|
|
::
|
2020-05-05 08:28:37 +03:00
|
|
|
%^ set-header:http 'content-length'
|
|
|
|
(crip (format-ud-as-integer p.u.data.result))
|
|
|
|
headers.response-header.result
|
|
|
|
::
|
|
|
|
%- handle-response
|
|
|
|
^- http-event:http
|
|
|
|
:* %start
|
|
|
|
response-header.result
|
|
|
|
data.result
|
|
|
|
complete=%.y
|
|
|
|
==
|
2018-09-20 02:29:36 +03:00
|
|
|
::
|
|
|
|
%app
|
2018-09-21 02:36:04 +03:00
|
|
|
:_ state
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(subscribe-to-app identity app.action inbound-request.connection)
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
2018-11-15 21:27:10 +03:00
|
|
|
%authentication
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
(handle-request:authentication secure host address [suv identity] request)
|
|
|
|
::
|
|
|
|
%eauth
|
|
|
|
(on-request:eauth:authentication [suv identity] request)
|
2020-06-03 02:40:32 +03:00
|
|
|
::
|
|
|
|
%logout
|
2023-05-06 00:30:53 +03:00
|
|
|
(handle-logout:authentication [suv identity] request)
|
2018-11-13 22:12:59 +03:00
|
|
|
::
|
2018-11-15 21:27:10 +03:00
|
|
|
%channel
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(handle-request:by-channel [suv identity] address request)
|
2020-06-11 02:45:05 +03:00
|
|
|
::
|
|
|
|
%scry
|
|
|
|
(handle-scry authenticated address request(url suburl))
|
2022-08-01 01:50:36 +03:00
|
|
|
::
|
|
|
|
%name
|
2023-05-06 00:38:40 +03:00
|
|
|
(handle-name identity request)
|
|
|
|
::
|
|
|
|
%host
|
|
|
|
%^ return-static-data-on-duct 200 'text/plain'
|
|
|
|
(as-octs:mimes:html (scot %p our))
|
2019-01-11 03:35:09 +03:00
|
|
|
::
|
|
|
|
%four-oh-four
|
|
|
|
%^ return-static-data-on-duct 404 'text/html'
|
2019-03-21 23:58:37 +03:00
|
|
|
(error-page 404 authenticated url.request ~)
|
2018-09-27 02:18:40 +03:00
|
|
|
==
|
2023-05-06 00:38:40 +03:00
|
|
|
:: +handle-name: respond with the requester's @p
|
2022-08-01 01:50:36 +03:00
|
|
|
::
|
|
|
|
++ handle-name
|
2023-05-06 00:38:40 +03:00
|
|
|
|= [=identity =request:http]
|
|
|
|
^- (quip move server-state)
|
2022-08-01 01:50:36 +03:00
|
|
|
?. =(%'GET' method.request)
|
2023-05-06 00:38:40 +03:00
|
|
|
%^ return-static-data-on-duct 405 'text/html'
|
|
|
|
(error-page 405 & url.request "may only GET name")
|
2022-08-01 01:50:36 +03:00
|
|
|
%^ return-static-data-on-duct 200 'text/plain'
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
=/ nom=@p
|
|
|
|
?+(-.identity who.identity %ours our)
|
|
|
|
(as-octs:mimes:html (scot %p nom))
|
2023-03-25 07:18:25 +03:00
|
|
|
:: +handle-cache-req: respond with cached value, 404 or 500
|
|
|
|
::
|
|
|
|
++ handle-cache-req
|
|
|
|
|= [authenticated=? =request:http entry=(unit cache-entry)]
|
|
|
|
|^ ^- (quip move server-state)
|
|
|
|
?~ entry
|
|
|
|
(error-response 404 "cache entry for that binding was deleted")
|
|
|
|
?: &(auth.u.entry !authenticated)
|
|
|
|
(error-response 403 ~)
|
|
|
|
=* body body.u.entry
|
|
|
|
?- -.body
|
|
|
|
%payload
|
|
|
|
%- handle-response
|
|
|
|
:* %start
|
|
|
|
response-header.simple-payload.body
|
|
|
|
data.simple-payload.body
|
|
|
|
complete=%.y
|
|
|
|
==
|
|
|
|
==
|
|
|
|
::
|
|
|
|
++ error-response
|
|
|
|
|= [status=@ud =tape]
|
|
|
|
^- (quip move server-state)
|
|
|
|
%^ return-static-data-on-duct status 'text/html'
|
|
|
|
(error-page status authenticated url.request tape)
|
|
|
|
--
|
2020-06-11 02:45:05 +03:00
|
|
|
:: +handle-scry: respond with scry result, 404 or 500
|
|
|
|
::
|
|
|
|
++ handle-scry
|
|
|
|
|= [authenticated=? =address =request:http]
|
|
|
|
|^ ^- (quip move server-state)
|
2020-06-12 01:57:25 +03:00
|
|
|
?. authenticated
|
2022-08-11 19:30:37 +03:00
|
|
|
(error-response 403 ~)
|
2020-06-12 01:57:25 +03:00
|
|
|
?. =(%'GET' method.request)
|
2022-08-11 19:30:37 +03:00
|
|
|
(error-response 405 "may only GET scries")
|
2020-06-11 02:45:05 +03:00
|
|
|
:: make sure the path contains an app to scry into
|
|
|
|
::
|
|
|
|
=+ req=(parse-request-line url.request)
|
|
|
|
?. ?=(^ site.req)
|
2022-08-11 19:30:37 +03:00
|
|
|
(error-response 400 "scry path must start with app name")
|
2020-06-11 02:45:05 +03:00
|
|
|
:: attempt the scry that was asked for
|
|
|
|
::
|
|
|
|
=/ res=(unit (unit cage))
|
2020-06-12 03:03:55 +03:00
|
|
|
(do-scry %gx i.site.req (snoc t.site.req (fall ext.req %mime)))
|
2022-08-11 19:30:37 +03:00
|
|
|
?~ res (error-response 500 "failed scry")
|
|
|
|
?~ u.res (error-response 404 "no scry result")
|
2020-06-11 02:45:05 +03:00
|
|
|
=* mark p.u.u.res
|
|
|
|
=* vase q.u.u.res
|
2023-06-15 18:30:51 +03:00
|
|
|
?: =(%mime mark)
|
|
|
|
=/ =mime !<(mime vase)
|
|
|
|
%^ return-static-data-on-duct 200
|
|
|
|
(rsh 3 (spat p.mime)) q.mime
|
2020-06-12 03:03:55 +03:00
|
|
|
:: attempt to find conversion gate to mime
|
2020-06-11 02:45:05 +03:00
|
|
|
::
|
2023-06-15 18:30:51 +03:00
|
|
|
=/ tub=(unit [tub=tube:clay mov=move])
|
2021-06-19 05:13:55 +03:00
|
|
|
(find-tube i.site.req mark %mime)
|
2022-08-11 19:30:37 +03:00
|
|
|
?~ tub (error-response 500 "no tube from {(trip mark)} to mime")
|
2020-06-11 02:45:05 +03:00
|
|
|
:: attempt conversion, then send results
|
|
|
|
::
|
|
|
|
=/ mym=(each mime tang)
|
2023-06-15 18:30:51 +03:00
|
|
|
(mule |.(!<(mime (tub.u.tub vase))))
|
|
|
|
=^ cards state
|
|
|
|
?- -.mym
|
|
|
|
%| (error-response 500 "failed tube from {(trip mark)} to mime")
|
|
|
|
%& %+ return-static-data-on-duct 200
|
|
|
|
[(rsh 3 (spat p.p.mym)) q.p.mym]
|
|
|
|
==
|
|
|
|
[[mov.u.tub cards] state]
|
2020-06-11 02:45:05 +03:00
|
|
|
::
|
|
|
|
++ find-tube
|
2021-06-19 05:13:55 +03:00
|
|
|
|= [dap=term from=mark to=mark]
|
2023-06-15 18:30:51 +03:00
|
|
|
^- (unit [tube:clay move])
|
2021-06-19 05:13:55 +03:00
|
|
|
=/ des=(unit (unit cage))
|
2023-04-27 03:25:23 +03:00
|
|
|
(do-scry %gd dap /$)
|
2021-06-19 05:13:55 +03:00
|
|
|
?. ?=([~ ~ *] des) ~
|
|
|
|
=+ !<(=desk q.u.u.des)
|
2020-06-11 02:45:05 +03:00
|
|
|
=/ tub=(unit (unit cage))
|
2021-06-19 05:13:55 +03:00
|
|
|
(do-scry %cc desk /[from]/[to])
|
2020-06-11 02:45:05 +03:00
|
|
|
?. ?=([~ ~ %tube *] tub) ~
|
2023-06-15 18:30:51 +03:00
|
|
|
:- ~
|
|
|
|
:- !<(tube:clay q.u.u.tub)
|
|
|
|
:^ duct %pass /conversion-cache/[from]
|
|
|
|
[%c %warp our desk `[%sing %c da+now /[from]/[to]]]
|
2020-06-11 02:45:05 +03:00
|
|
|
::
|
|
|
|
++ do-scry
|
|
|
|
|= [care=term =desk =path]
|
|
|
|
^- (unit (unit cage))
|
2023-05-22 16:12:09 +03:00
|
|
|
(rof ~ /eyre care [our desk da+now] path)
|
2020-06-11 02:45:05 +03:00
|
|
|
::
|
2022-08-11 19:30:37 +03:00
|
|
|
++ error-response
|
|
|
|
|= [status=@ud =tape]
|
|
|
|
^- (quip move server-state)
|
|
|
|
%^ return-static-data-on-duct status 'text/html'
|
|
|
|
(error-page status authenticated url.request tape)
|
2020-06-11 02:45:05 +03:00
|
|
|
--
|
2019-11-13 11:38:35 +03:00
|
|
|
:: +subscribe-to-app: subscribe to app and poke it with request data
|
2019-11-09 10:31:11 +03:00
|
|
|
::
|
2019-11-13 11:38:35 +03:00
|
|
|
++ subscribe-to-app
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
|= [=identity app=term =inbound-request:eyre]
|
2019-11-13 11:38:35 +03:00
|
|
|
^- (list move)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:~ %+ deal-as
|
|
|
|
/watch-response/[eyre-id]
|
|
|
|
[identity our app %watch /http-response/[eyre-id]]
|
|
|
|
::
|
|
|
|
%+ deal-as
|
|
|
|
/run-app-request/[eyre-id]
|
|
|
|
:^ identity our app
|
|
|
|
:+ %poke %handle-http-request
|
|
|
|
!>(`[@ta inbound-request:eyre]`[eyre-id inbound-request])
|
2019-11-09 10:31:11 +03:00
|
|
|
==
|
2018-10-22 21:36:30 +03:00
|
|
|
:: +cancel-request: handles a request being externally aborted
|
|
|
|
::
|
|
|
|
++ cancel-request
|
|
|
|
^- [(list move) server-state]
|
|
|
|
::
|
2018-10-24 00:25:20 +03:00
|
|
|
?~ connection=(~(get by connections.state) duct)
|
|
|
|
:: nothing has handled this connection
|
|
|
|
::
|
|
|
|
[~ state]
|
|
|
|
::
|
2018-10-24 01:08:17 +03:00
|
|
|
=. connections.state (~(del by connections.state) duct)
|
|
|
|
::
|
2018-10-24 00:25:20 +03:00
|
|
|
?- -.action.u.connection
|
2020-05-05 08:28:37 +03:00
|
|
|
%gen [~ state]
|
2018-10-24 00:25:20 +03:00
|
|
|
%app
|
|
|
|
:_ state
|
|
|
|
:_ ~
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=, u.connection
|
|
|
|
%- (trace 1 |.("leaving subscription to {<app.action>}"))
|
|
|
|
(deal-as /watch-response/[eyre-id] identity our app.action %leave ~)
|
2018-10-24 00:25:20 +03:00
|
|
|
::
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
?(%authentication %eauth %logout)
|
|
|
|
::NOTE expiry timer will clean up cancelled eauth attempts
|
2018-10-24 00:25:20 +03:00
|
|
|
[~ state]
|
2018-11-13 22:12:59 +03:00
|
|
|
::
|
2018-11-15 21:27:10 +03:00
|
|
|
%channel
|
2018-11-22 00:37:26 +03:00
|
|
|
on-cancel-request:by-channel
|
2019-01-11 03:35:09 +03:00
|
|
|
::
|
2023-05-06 00:38:40 +03:00
|
|
|
?(%scry %four-oh-four %name %host)
|
|
|
|
:: it should be impossible for these to be asynchronous
|
2019-01-11 03:35:09 +03:00
|
|
|
::
|
|
|
|
!!
|
2018-10-24 00:25:20 +03:00
|
|
|
==
|
2018-09-27 02:18:40 +03:00
|
|
|
:: +return-static-data-on-duct: returns one piece of data all at once
|
|
|
|
::
|
|
|
|
++ return-static-data-on-duct
|
|
|
|
|= [code=@ content-type=@t data=octs]
|
|
|
|
^- [(list move) server-state]
|
|
|
|
::
|
2019-01-11 03:35:09 +03:00
|
|
|
%- handle-response
|
|
|
|
:* %start
|
2019-02-09 00:16:42 +03:00
|
|
|
:- status-code=code
|
2018-09-27 02:18:40 +03:00
|
|
|
^= headers
|
2018-10-01 21:37:30 +03:00
|
|
|
:~ ['content-type' content-type]
|
2019-01-17 02:24:30 +03:00
|
|
|
['content-length' (crip (format-ud-as-integer p.data))]
|
2018-09-27 02:18:40 +03:00
|
|
|
==
|
|
|
|
data=[~ data]
|
|
|
|
complete=%.y
|
2018-09-20 02:29:36 +03:00
|
|
|
==
|
2018-09-27 02:18:40 +03:00
|
|
|
:: +authentication: per-event authentication as this Urbit's owner
|
|
|
|
::
|
|
|
|
:: Right now this hard codes the authentication page using the old +code
|
|
|
|
:: system, but in the future should be pluggable so we can use U2F or
|
|
|
|
:: WebAuthn or whatever is more secure than passwords.
|
|
|
|
::
|
|
|
|
++ authentication
|
|
|
|
|%
|
2020-06-03 02:40:32 +03:00
|
|
|
:: +handle-request: handles an http request for the login page
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
|
|
|
++ handle-request
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
|= [secure=? host=(unit @t) =address [session-id=@uv =identity] =request:http]
|
2018-09-27 02:18:40 +03:00
|
|
|
^- [(list move) server-state]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: parse the arguments out of request uri
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
=+ request-line=(parse-request-line url.request)
|
|
|
|
=/ redirect (get-header:http 'redirect' args.request-line)
|
2023-05-19 11:35:23 +03:00
|
|
|
=/ with-eauth=(unit ?)
|
|
|
|
?: =(~ eauth-url:eauth) ~
|
|
|
|
`?=(^ (get-header:http 'eauth' args.request-line))
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:: if we received a simple get: redirect if logged in, otherwise
|
2023-04-24 23:50:11 +03:00
|
|
|
:: show login page
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
?: =('GET' method.request)
|
2023-04-24 23:50:11 +03:00
|
|
|
?. (request-is-logged-in request)
|
|
|
|
%^ return-static-data-on-duct 200 'text/html'
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
(login-page redirect our identity with-eauth %.n)
|
2023-04-24 23:50:11 +03:00
|
|
|
=/ session-id (session-id-from-request request)
|
|
|
|
:: session-id should always be populated here since we are logged in
|
|
|
|
?~ session-id
|
|
|
|
%^ return-static-data-on-duct 200 'text/html'
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
(login-page redirect our identity with-eauth %.n)
|
2023-04-24 23:50:11 +03:00
|
|
|
=/ cookie-line=@t
|
|
|
|
(session-cookie-string u.session-id &)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=/ actual-redirect
|
2023-04-24 23:50:11 +03:00
|
|
|
?~ redirect '/'
|
|
|
|
?:(=(u.redirect '') '/' u.redirect)
|
|
|
|
%- handle-response
|
|
|
|
:* %start
|
|
|
|
:- status-code=303
|
|
|
|
^= headers
|
|
|
|
:~ ['location' actual-redirect]
|
|
|
|
['set-cookie' cookie-line]
|
|
|
|
==
|
|
|
|
data=~
|
|
|
|
complete=%.y
|
|
|
|
==
|
2018-09-27 02:18:40 +03:00
|
|
|
:: if we are not a post, return an error
|
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
?. =('POST' method.request)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
%^ return-static-data-on-duct 405 'text/html'
|
|
|
|
(login-page ~ our identity with-eauth %.n)
|
2018-09-27 02:18:40 +03:00
|
|
|
:: we are a post, and must process the body type as form data
|
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
?~ body.request
|
2023-05-09 16:10:14 +03:00
|
|
|
%^ return-static-data-on-duct 400 'text/html'
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
(login-page ~ our identity with-eauth %.n)
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
|
|
|
=/ parsed=(unit (list [key=@t value=@t]))
|
2019-02-09 00:16:42 +03:00
|
|
|
(rush q.u.body.request yquy:de-purl:html)
|
2018-09-27 02:18:40 +03:00
|
|
|
?~ parsed
|
2023-05-09 16:10:14 +03:00
|
|
|
%^ return-static-data-on-duct 400 'text/html'
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
(login-page ~ our identity with-eauth %.n)
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
2020-06-10 21:37:12 +03:00
|
|
|
=/ redirect=(unit @t) (get-header:http 'redirect' u.parsed)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
?^ (get-header:http 'eauth' u.parsed)
|
|
|
|
?~ ship=(biff (get-header:http 'name' u.parsed) (cury slaw %p))
|
|
|
|
%^ return-static-data-on-duct 400 'text/html'
|
2023-05-19 11:35:23 +03:00
|
|
|
(login-page redirect our identity `& %.n)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::TODO redirect logic here and elsewhere is ugly
|
|
|
|
=/ redirect (fall redirect '')
|
2023-06-09 16:46:04 +03:00
|
|
|
=/ base=(unit @t)
|
|
|
|
?~ host ~
|
|
|
|
`(cat 3 ?:(secure 'https://' 'http://') u.host)
|
|
|
|
(start:server:eauth u.ship base ?:(=(redirect '') '/' redirect))
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-05-19 11:35:23 +03:00
|
|
|
=. with-eauth (bind with-eauth |=(? |))
|
2019-02-09 00:16:42 +03:00
|
|
|
?~ password=(get-header:http 'password' u.parsed)
|
2023-05-09 16:10:14 +03:00
|
|
|
%^ return-static-data-on-duct 400 'text/html'
|
2023-05-19 11:35:23 +03:00
|
|
|
(login-page redirect our identity with-eauth %.n)
|
2018-09-27 02:18:40 +03:00
|
|
|
:: check that the password is correct
|
|
|
|
::
|
|
|
|
?. =(u.password code)
|
2023-05-09 16:10:14 +03:00
|
|
|
%^ return-static-data-on-duct 400 'text/html'
|
2023-05-19 11:35:23 +03:00
|
|
|
(login-page redirect our identity with-eauth %.y)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:: clean up the session they're changing out from
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=^ moz state
|
2023-05-09 16:10:14 +03:00
|
|
|
(close-session session-id |)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:: initialize the new session
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=^ fex state (start-session %local)
|
|
|
|
:: associate the new session with the request that caused the login
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:: if we don't do this here, +handle-response will include the old
|
|
|
|
:: session's cookie, confusing the client.
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=. connections.state
|
|
|
|
%+ ~(jab by connections.state) duct
|
|
|
|
|= o=outstanding-connection
|
|
|
|
o(session-id session.fex)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: store the hostname used for this login, later reuse it for eauth
|
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
=? endpoint.auth.state ?=(^ host)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
%- (trace 2 |.("eauth: storing endpoint at {(trip u.host)}"))
|
2023-06-09 16:46:04 +03:00
|
|
|
:+ user.endpoint.auth.state
|
|
|
|
`(cat 3 ?:(secure 'https://' 'http://') u.host)
|
|
|
|
now
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=; out=[moves=(list move) server-state]
|
|
|
|
out(moves [give-session-tokens :(weld moz moves.fex moves.out)])
|
|
|
|
::NOTE that we don't provide a 'set-cookie' header here.
|
|
|
|
:: +handle-response does that for us.
|
|
|
|
?~ redirect
|
|
|
|
(handle-response %start 204^~ ~ &)
|
2020-03-10 03:16:43 +03:00
|
|
|
=/ actual-redirect ?:(=(u.redirect '') '/' u.redirect)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(handle-response %start 303^['location' actual-redirect]~ ~ &)
|
2020-06-03 02:40:32 +03:00
|
|
|
:: +handle-logout: handles an http request for logging out
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
2020-06-03 02:40:32 +03:00
|
|
|
++ handle-logout
|
2023-05-06 00:30:53 +03:00
|
|
|
|= [[session-id=@uv =identity] =request:http]
|
2020-06-03 02:40:32 +03:00
|
|
|
^- [(list move) server-state]
|
2023-05-06 00:30:53 +03:00
|
|
|
:: whatever we end up doing, we always respond with a redirect
|
2020-06-03 02:40:32 +03:00
|
|
|
::
|
|
|
|
=/ response=$>(%start http-event:http)
|
2023-05-06 00:30:53 +03:00
|
|
|
=/ redirect=(unit @t)
|
|
|
|
%+ get-header:http 'redirect'
|
|
|
|
args:(parse-request-line url.request)
|
2020-06-03 02:40:32 +03:00
|
|
|
:* %start
|
2023-05-06 00:30:53 +03:00
|
|
|
response-header=[303 ['location' (fall redirect '/~/login')]~]
|
2020-06-03 02:40:32 +03:00
|
|
|
data=~
|
|
|
|
complete=%.y
|
|
|
|
==
|
2023-05-06 00:30:53 +03:00
|
|
|
:: read options from the body
|
|
|
|
:: all: log out all sessions with this identity?
|
|
|
|
:: sid: which session do we log out? (defaults to requester's)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: hos: host to log out from, for eauth logins (sid signifies the nonce)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
::
|
2023-05-06 00:30:53 +03:00
|
|
|
=/ arg=header-list:http
|
|
|
|
?~ body.request ~
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(fall (rush q.u.body.request yquy:de-purl:html) ~)
|
2023-05-06 00:30:53 +03:00
|
|
|
=/ all=?
|
|
|
|
?=(^ (get-header:http 'all' arg))
|
|
|
|
=/ sid=(unit @uv)
|
|
|
|
?. ?=(%ours -.identity) `session-id
|
|
|
|
?~ sid=(get-header:http 'sid' arg) `session-id
|
|
|
|
:: if you provided the parameter, but it doesn't parse, we just
|
|
|
|
:: no-op. otherwise, a poorly-implemented frontend might result in
|
|
|
|
:: accidental log-outs, which would be very annoying.
|
|
|
|
::
|
|
|
|
(slaw %uv u.sid)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
=/ hos=(unit @p)
|
|
|
|
?. ?=(%ours -.identity) ~
|
|
|
|
(biff (get-header:http 'host' arg) (cury slaw %p))
|
2023-05-06 00:30:53 +03:00
|
|
|
?~ sid
|
|
|
|
(handle-response response)
|
2023-06-27 23:58:22 +03:00
|
|
|
:: if this is an eauth remote logout, send the %shut
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-27 23:58:22 +03:00
|
|
|
=* auth auth.state
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
?: ?=(^ hos)
|
|
|
|
=^ moz state (handle-response response)
|
2023-06-27 23:58:22 +03:00
|
|
|
:- [(send-plea:client:eauth u.hos %0 %shut u.sid) moz]
|
|
|
|
=/ book (~(gut by visiting.auth) u.hos *logbook)
|
|
|
|
=. qeu.book (~(put to qeu.book) u.sid)
|
|
|
|
=. visiting.auth (~(put by visiting.auth) u.hos book)
|
|
|
|
state
|
2023-05-06 00:30:53 +03:00
|
|
|
:: if the requester is logging themselves out, make them drop the cookie
|
|
|
|
::
|
|
|
|
=? headers.response-header.response =(u.sid session-id)
|
|
|
|
:_ headers.response-header.response
|
|
|
|
['set-cookie' (session-cookie-string session-id |)]
|
|
|
|
:: close the session as requested, then send the response
|
|
|
|
::
|
|
|
|
=^ moz1 state (close-session u.sid all)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=^ moz2 state (handle-response response)
|
|
|
|
[[give-session-tokens (weld moz1 moz2)] state]
|
2020-05-30 03:29:20 +03:00
|
|
|
:: +session-id-from-request: attempt to find a session cookie
|
2018-09-27 02:18:40 +03:00
|
|
|
::
|
2020-05-30 03:29:20 +03:00
|
|
|
++ session-id-from-request
|
2019-02-09 00:16:42 +03:00
|
|
|
|= =request:http
|
2020-05-30 03:29:20 +03:00
|
|
|
^- (unit @uv)
|
2018-09-27 21:16:59 +03:00
|
|
|
:: are there cookies passed with this request?
|
|
|
|
::
|
|
|
|
:: TODO: In HTTP2, the client is allowed to put multiple 'Cookie'
|
|
|
|
:: headers.
|
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
?~ cookie-header=(get-header:http 'cookie' header-list.request)
|
2020-05-30 03:29:20 +03:00
|
|
|
~
|
2018-09-27 21:16:59 +03:00
|
|
|
:: is the cookie line is valid?
|
|
|
|
::
|
|
|
|
?~ cookies=(rush u.cookie-header cock:de-purl:html)
|
2020-05-30 03:29:20 +03:00
|
|
|
~
|
2018-09-27 21:16:59 +03:00
|
|
|
:: is there an urbauth cookie?
|
|
|
|
::
|
2020-11-04 03:02:11 +03:00
|
|
|
?~ urbauth=(get-header:http (crip "urbauth-{(scow %p our)}") u.cookies)
|
2020-05-30 03:29:20 +03:00
|
|
|
~
|
|
|
|
:: if it's formatted like a valid session cookie, produce it
|
2018-09-27 21:16:59 +03:00
|
|
|
::
|
2020-05-30 03:29:20 +03:00
|
|
|
`(unit @)`(rush u.urbauth ;~(pfix (jest '0v') viz:ag))
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:: +request-is-logged-in: checks to see if the request has non-guest id
|
2020-05-30 03:29:20 +03:00
|
|
|
::
|
|
|
|
++ request-is-logged-in
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
|= =request:http
|
|
|
|
^- ?
|
|
|
|
?~ session-id=(session-id-from-request request)
|
|
|
|
|
|
2023-05-19 12:31:01 +03:00
|
|
|
?~ session=(~(get by sessions.auth.state) u.session-id)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
|
|
|
|
|
&(!?=(%fake -.identity.u.session) (lte now expiry-time.u.session))
|
|
|
|
:: +request-is-authenticated: checks to see if the request is "us"
|
|
|
|
::
|
|
|
|
:: We are considered authenticated if this request has an urbauth
|
|
|
|
:: Cookie for the local identity that is not expired.
|
|
|
|
::
|
|
|
|
++ request-is-authenticated
|
2020-05-30 03:29:20 +03:00
|
|
|
|= =request:http
|
|
|
|
^- ?
|
|
|
|
:: does the request pass a session cookie?
|
2018-09-27 21:16:59 +03:00
|
|
|
::
|
2020-05-30 03:29:20 +03:00
|
|
|
?~ session-id=(session-id-from-request request)
|
2018-09-27 21:16:59 +03:00
|
|
|
%.n
|
|
|
|
:: is this a session that we know about?
|
|
|
|
::
|
2023-05-19 12:31:01 +03:00
|
|
|
?~ session=(~(get by sessions.auth.state) `@uv`u.session-id)
|
2018-09-27 21:16:59 +03:00
|
|
|
%.n
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:: does this session have our id, and is it still valid?
|
|
|
|
::
|
|
|
|
&(?=(%ours -.identity.u.session) (lte now expiry-time.u.session))
|
|
|
|
:: +start-session: create a new session with %local or %guest identity
|
|
|
|
::
|
|
|
|
++ start-session
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
|= kind=?(%local %guest [%eauth who=@p])
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
^- [[session=@uv =identity moves=(list move)] server-state]
|
|
|
|
=; [key=@uv sid=identity]
|
|
|
|
:- :+ key sid
|
|
|
|
:: if no session existed previously, we must kick off the
|
|
|
|
:: session expiry timer
|
|
|
|
::
|
2023-05-19 12:31:01 +03:00
|
|
|
?^ sessions.auth.state ~
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
[duct %pass /sessions/expire %b %wait (add now session-timeout)]~
|
2023-05-19 12:31:01 +03:00
|
|
|
=- state(sessions.auth -)
|
|
|
|
%+ ~(put by sessions.auth.state) key
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
[sid (add now session-timeout) ~]
|
|
|
|
:: create a new session with a fake identity
|
|
|
|
::
|
|
|
|
=/ sik=@uv new-session-key
|
|
|
|
:- sik
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
?: ?=(%local kind) [%ours ~]
|
|
|
|
?: ?=([%eauth @] kind) [%real who.kind]
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:- %fake
|
|
|
|
:: pre-scramble our ship name into its displayed value, and
|
|
|
|
:: truncate it to be at most moon-length, so that we can overlay
|
2023-05-09 16:31:47 +03:00
|
|
|
:: it onto the end of a comet name for visual consistency.
|
|
|
|
:: to prevent escalation, make sure the guest identity isn't ours.
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
::
|
2023-05-09 16:31:47 +03:00
|
|
|
|-
|
|
|
|
=; nom=@p
|
|
|
|
?. =(our nom) nom
|
|
|
|
$(eny (shas %next-name eny))
|
2023-05-16 22:46:48 +03:00
|
|
|
%+ end 3^16
|
|
|
|
%^ cat 3
|
|
|
|
(end 3^8 (fein:ob our))
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(~(raw og (shas %fake-name eny)) 128)
|
|
|
|
:: +session-for-request: get the session details for the request
|
|
|
|
::
|
|
|
|
:: creates a guest session if the request does not have a valid session.
|
|
|
|
:: there is no need to call +give-session-tokens after this, because
|
|
|
|
:: guest session do not make valid "auth session" tokens.
|
|
|
|
::
|
|
|
|
++ session-for-request
|
|
|
|
|= =request:http
|
|
|
|
^- [[session=@uv =identity moves=(list move)] server-state]
|
|
|
|
=* new (start-session %guest)
|
|
|
|
?~ sid=(session-id-from-request request)
|
|
|
|
new
|
2023-05-19 12:31:01 +03:00
|
|
|
?~ ses=(~(get by sessions.auth.state) u.sid)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
new
|
|
|
|
?: (gth now expiry-time.u.ses)
|
|
|
|
new
|
|
|
|
[[u.sid identity.u.ses ~] state]
|
|
|
|
:: +close-session: delete a session and its associated channels
|
|
|
|
::
|
|
|
|
:: if :all is true, deletes all sessions that share the same identity.
|
|
|
|
:: if this closes an %ours session, the caller is responsible for
|
|
|
|
:: also calling +give-session-tokens afterwards.
|
|
|
|
::
|
|
|
|
++ close-session
|
|
|
|
|= [session-id=@uv all=?]
|
|
|
|
^- [(list move) server-state]
|
2023-05-19 12:31:01 +03:00
|
|
|
?~ ses=(~(get by sessions.auth.state) session-id)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
[~ state]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: delete the session(s) and find the associated ids & channels
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
::
|
2023-05-19 12:31:01 +03:00
|
|
|
=^ [siz=(list @uv) channels=(list @t)] sessions.auth.state
|
|
|
|
=* sessions sessions.auth.state
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:: either delete just the specific session and its channels,
|
|
|
|
::
|
|
|
|
?. all
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:- [[session-id]~ ~(tap in channels.u.ses)]
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(~(del by sessions) session-id)
|
|
|
|
:: or delete all sessions with the identity from :session-id
|
|
|
|
::
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
%+ roll ~(tap by sessions)
|
|
|
|
|= $: [sid=@uv s=session]
|
|
|
|
[[siz=(list @uv) caz=(list @t)] sez=(map @uv session)]
|
|
|
|
==
|
|
|
|
^+ [[siz caz] sez]
|
|
|
|
?. =(identity.s identity.u.ses)
|
|
|
|
:: identity doesn't match, so re-store this session
|
|
|
|
::
|
|
|
|
[[siz caz] (~(put by sez) sid s)]
|
|
|
|
:: identity matches, so register this session as closed
|
|
|
|
::
|
|
|
|
[[[sid siz] (weld caz ~(tap in channels.s))] sez]
|
|
|
|
:: close all affected channels and send their responses
|
|
|
|
::
|
|
|
|
=| moves1=(list move)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
|- ^- (quip move server-state)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
?^ channels
|
|
|
|
%- %+ trace 1
|
|
|
|
|.("{(trip i.channels)} discarding channel due to closed session")
|
|
|
|
=^ moz state
|
|
|
|
(discard-channel:by-channel i.channels |)
|
|
|
|
$(moves1 (weld moves1 moz), channels t.channels)
|
|
|
|
:: lastly, %real sessions require additional cleanup
|
|
|
|
::
|
|
|
|
?. ?=(%real -.identity.u.ses) [moves1 state]
|
2023-05-19 12:31:01 +03:00
|
|
|
=^ moves2 visitors.auth.state
|
|
|
|
%+ roll ~(tap by visitors.auth.state)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
|= [[nonce=@uv visa=visitor] [moz=(list move) viz=(map @uv visitor)]]
|
|
|
|
?^ +.visa [moz (~(put by viz) nonce visa)]
|
|
|
|
:_ viz
|
|
|
|
%+ weld moz
|
2023-06-09 16:46:04 +03:00
|
|
|
?~ duct.visa ~
|
|
|
|
[(send-boon:server:eauth(duct u.duct.visa) %0 %shut nonce)]~
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
[(weld `(list move)`moves1 `(list move)`moves2) state]
|
2018-09-27 02:18:40 +03:00
|
|
|
:: +code: returns the same as |code
|
|
|
|
::
|
|
|
|
++ code
|
|
|
|
^- @ta
|
2020-12-06 06:23:57 +03:00
|
|
|
=/ res=(unit (unit cage))
|
2023-05-22 16:12:09 +03:00
|
|
|
(rof ~ /eyre %j [our %code da+now] /(scot %p our))
|
2020-12-06 06:23:57 +03:00
|
|
|
(rsh 3 (scot %p ;;(@ q.q:(need (need res)))))
|
2020-06-03 02:40:32 +03:00
|
|
|
:: +session-cookie-string: compose session cookie
|
2020-05-30 03:29:20 +03:00
|
|
|
::
|
|
|
|
++ session-cookie-string
|
2020-06-03 02:40:32 +03:00
|
|
|
|= [session=@uv extend=?]
|
2020-05-30 03:29:20 +03:00
|
|
|
^- @t
|
|
|
|
%- crip
|
|
|
|
=; max-age=tape
|
2023-02-13 21:58:59 +03:00
|
|
|
"urbauth-{(scow %p our)}={(scow %uv session)}; Path=/; Max-Age={max-age}"
|
2020-05-30 03:29:20 +03:00
|
|
|
%- format-ud-as-integer
|
2020-06-03 02:40:32 +03:00
|
|
|
?. extend 0
|
2020-05-30 03:29:20 +03:00
|
|
|
(div (msec:milly session-timeout) 1.000)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-05-19 12:31:01 +03:00
|
|
|
::
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
++ eauth
|
2023-05-19 12:31:01 +03:00
|
|
|
=* auth auth.state
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
|%
|
|
|
|
++ server
|
|
|
|
|%
|
|
|
|
:: +start: initiate an eauth login attempt for the :ship identity
|
|
|
|
::
|
|
|
|
++ start
|
2023-06-09 16:46:04 +03:00
|
|
|
|= [=ship base=(unit @t) last=@t]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
^- [(list move) server-state]
|
|
|
|
%- (trace 2 |.("eauth: starting eauth into {(scow %p ship)}"))
|
2023-06-28 00:02:43 +03:00
|
|
|
=/ nonce=@uv
|
|
|
|
|-
|
|
|
|
=+ n=(~(raw og (shas %eauth-nonce eny)) 64)
|
|
|
|
?. (~(has by visitors.auth) n) n
|
|
|
|
$(eny (shas %try-again n))
|
2023-06-09 16:46:04 +03:00
|
|
|
=/ visit=visitor [~ `[duct now] ship base last ~]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
=. visitors.auth (~(put by visitors.auth) nonce visit)
|
|
|
|
:_ state
|
2023-06-09 16:46:04 +03:00
|
|
|
:: we delay serving an http response until we receive a scry %tune
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
:~ (send-keen %keen ship nonce now)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
(start-timeout /visitors/(scot %uv nonce))
|
|
|
|
==
|
2023-06-09 16:46:04 +03:00
|
|
|
:: +on-tune: receive a client-url remote scry result
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
++ on-tune
|
|
|
|
|= [ship=@p nonce=@uv url=@t]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
^- [(list move) server-state]
|
2023-06-09 16:46:04 +03:00
|
|
|
%- (trace 2 |.("eauth: %tune from {(scow %p ship)}"))
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: guarantee the ship still controls the nonce
|
|
|
|
::
|
|
|
|
=/ visa=visitor (~(got by visitors.auth) nonce)
|
2023-06-09 16:46:04 +03:00
|
|
|
?> &(?=(^ +.visa) =(ship ship.visa))
|
|
|
|
:: redirect the visitor to their own confirmation page
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
=. visitors.auth (~(put by visitors.auth) nonce visa(pend ~))
|
|
|
|
%- handle-response(duct http:(need pend.visa))
|
|
|
|
=; url=@t [%start 303^['location' url]~ ~ &]
|
|
|
|
%+ rap 3
|
|
|
|
:~ url
|
|
|
|
'?server=' (scot %p our)
|
|
|
|
'&nonce=' (scot %uv nonce)
|
|
|
|
==
|
|
|
|
:: +on-plea: receive an eauth network message from a client
|
|
|
|
::
|
|
|
|
++ on-plea
|
|
|
|
|= [=ship plea=eauth-plea]
|
|
|
|
^- [(list move) server-state]
|
|
|
|
%- (trace 2 |.("eauth: {(trip +<.plea)} from {(scow %p ship)}"))
|
|
|
|
=; res=[(list move) server-state]
|
|
|
|
=^ moz state res
|
|
|
|
[[[duct %give %done ~] moz] state]
|
|
|
|
?- +<.plea
|
|
|
|
%open
|
|
|
|
:: this attempt may or may not have been started in +start yet
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
=/ visa=visitor
|
|
|
|
%+ ~(gut by visitors.auth) nonce.plea
|
|
|
|
[~ ~ ship ~ '/' ~]
|
|
|
|
?> ?=(^ +.visa)
|
|
|
|
?> =(ship ship.visa)
|
|
|
|
::NOTE that token might still be empty, in which case the http
|
|
|
|
:: client will probably signal an abort when they return
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
=. duct.visa `duct
|
|
|
|
=. toke.visa token.plea
|
|
|
|
=. visitors.auth (~(put by visitors.auth) nonce.plea visa)
|
|
|
|
:: if the eauth attempt was started on our side, we may know the
|
|
|
|
:: specific base url the user used; make sure they go back there
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
=/ url=@t
|
|
|
|
%- need
|
|
|
|
?~ base.visa eauth-url
|
|
|
|
eauth-url(user.endpoint.auth base.visa)
|
|
|
|
[[(send-boon %0 %okay nonce.plea url)]~ state]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
%shut
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: the visitor wants the associated session gone
|
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
?~ visa=(~(get by visitors.auth) nonce.plea) [~ state]
|
|
|
|
=. visitors.auth (~(del by visitors.auth) nonce.plea)
|
|
|
|
=? sessions.auth ?=(@ +.u.visa)
|
|
|
|
(~(del by sessions.auth) sesh.u.visa)
|
|
|
|
[[(send-boon %0 %shut nonce.plea)]~ state]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
==
|
|
|
|
:: +cancel: the client aborted the eauth attempt, so clean it up
|
|
|
|
::
|
|
|
|
++ cancel
|
|
|
|
|= [nonce=@uv last=@t]
|
|
|
|
^- [(list move) server-state]
|
|
|
|
:: if the eauth attempt doesn't exist, or it was already completed,
|
|
|
|
:: we cannot cancel it
|
|
|
|
::
|
|
|
|
?~ visa=(~(get by visitors.auth) nonce) [~ state]
|
|
|
|
?@ +.u.visa [~ state]
|
2023-06-09 16:46:04 +03:00
|
|
|
:: delete the attempt, and go back to the login page
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
|
|
|
%- (trace 2 |.("eauth: cancelling login"))
|
|
|
|
=. visitors.auth (~(del by visitors.auth) nonce)
|
|
|
|
=^ moz state
|
2023-05-23 23:38:56 +03:00
|
|
|
=/ url=@t
|
|
|
|
%^ cat 3 '/~/login?eauth&redirect='
|
|
|
|
(crip (en-urlt:html (trip last)))
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
(handle-response %start 303^['location' url]~ ~ &)
|
|
|
|
:_ state
|
2023-06-09 16:46:04 +03:00
|
|
|
%+ weld moz
|
|
|
|
?~ duct.u.visa ~
|
|
|
|
[(send-boon(duct u.duct.u.visa) %0 %shut nonce)]~
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: +expire: host-side cancel an eauth attempt if it's still pending
|
|
|
|
::
|
|
|
|
++ expire
|
|
|
|
|= nonce=@uv
|
|
|
|
^- [(list move) server-state]
|
|
|
|
?~ visa=(~(get by visitors.auth) nonce)
|
|
|
|
[~ state]
|
|
|
|
?@ +.u.visa [~ state]
|
2023-06-09 16:46:04 +03:00
|
|
|
%- (trace 2 |.("eauth: expiring"))
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
=^ moz state
|
|
|
|
?~ pend.u.visa [~ state]
|
2023-06-09 16:46:04 +03:00
|
|
|
%- return-static-data-on-duct(duct http.u.pend.u.visa)
|
|
|
|
[503 'text/html' (eauth-error-page %server last.u.visa)]
|
|
|
|
=? moz ?=(^ pend.u.visa)
|
|
|
|
[(send-keen %yawn ship.u.visa nonce keen.u.pend.u.visa) moz]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
=. visitors.auth (~(del by visitors.auth) nonce)
|
|
|
|
:_ state
|
2023-06-09 16:46:04 +03:00
|
|
|
%+ weld moz
|
|
|
|
?~ duct.u.visa ~
|
|
|
|
[(send-boon(duct u.duct.u.visa) %0 %shut nonce)]~
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: +finalize: eauth attempt was approved: mint the client a new session
|
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
:: gives the http response on the current duct
|
|
|
|
::
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
++ finalize
|
2023-06-09 16:46:04 +03:00
|
|
|
|= [=plea=^duct nonce=@uv =ship last=@t]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
^- [(list move) server-state]
|
|
|
|
%- (trace 2 |.("eauth: finalizing login for {(scow %p ship)}"))
|
|
|
|
:: clean up the session they're changing out from,
|
|
|
|
:: mint the new session,
|
|
|
|
:: associate it with the nonce,
|
|
|
|
:: and the finalization request,
|
|
|
|
:: and send the visitor the cookie + final redirect
|
|
|
|
::
|
|
|
|
=^ moz1 state
|
|
|
|
(close-session session-id:(~(got by connections.state) duct) |)
|
|
|
|
=^ [sid=@uv * moz2=(list move)] state
|
|
|
|
(start-session %eauth ship)
|
2023-06-09 16:46:04 +03:00
|
|
|
=. visitors.auth
|
|
|
|
%+ ~(jab by visitors.auth) nonce
|
|
|
|
|=(v=visitor v(+ sid))
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
=. connections.state
|
2023-06-09 16:46:04 +03:00
|
|
|
%+ ~(jab by connections.state) duct
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
|= o=outstanding-connection
|
|
|
|
o(session-id sid)
|
|
|
|
=^ moz3 state
|
2023-06-09 16:46:04 +03:00
|
|
|
=; hed (handle-response %start 303^hed ~ &)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:~ ['location' last]
|
|
|
|
['set-cookie' (session-cookie-string sid &)]
|
|
|
|
==
|
|
|
|
[:(weld moz1 moz2 moz3) state]
|
2023-06-09 16:46:04 +03:00
|
|
|
:: +on-fail: we crashed or received an empty %tune, clean up
|
|
|
|
::
|
|
|
|
++ on-fail
|
|
|
|
|= [=ship nonce=@uv]
|
|
|
|
^- [(list move) server-state]
|
|
|
|
:: if the eauth attempt doesn't exist, or it was already completed,
|
|
|
|
:: we can no-op here
|
|
|
|
::
|
|
|
|
?~ visa=(~(get by visitors.auth) nonce) [~ state]
|
|
|
|
?@ +.u.visa [~ state]
|
|
|
|
:: delete the attempt, and go back to the login page
|
|
|
|
::
|
|
|
|
%- (trace 2 |.("eauth: failed login"))
|
|
|
|
=. visitors.auth (~(del by visitors.auth) nonce)
|
|
|
|
=^ moz state
|
|
|
|
?~ pend.u.visa [~ state]
|
|
|
|
%- return-static-data-on-duct(duct http.u.pend.u.visa)
|
|
|
|
[503 'text/html' (eauth-error-page %server last.u.visa)]
|
|
|
|
:_ state
|
|
|
|
%+ weld moz
|
|
|
|
?~ duct.u.visa ~
|
|
|
|
[(send-boon(duct u.duct.u.visa) %0 %shut nonce)]~
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
|
|
|
::TODO +on-request?
|
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
++ send-keen
|
|
|
|
|= [kind=?(%keen %yawn) =ship nonce=@uv =time]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
^- move
|
2023-06-09 16:46:04 +03:00
|
|
|
%- (trace 2 |.("eauth: %{(trip kind)} into {(scow %p ship)}"))
|
|
|
|
:: we round down the time to make it more likely to hit cache,
|
|
|
|
:: at the expense of not working if the endpoint changed within
|
|
|
|
:: the last hour.
|
|
|
|
::
|
|
|
|
=/ =wire /eauth/keen/(scot %p ship)/(scot %uv nonce)
|
|
|
|
=. time (sub time (mod time ~h1))
|
|
|
|
=/ =spar:ames [ship /e/x/(scot %da time)//eauth/url]
|
|
|
|
[duct %pass wire %a ?-(kind %keen keen+spar, %yawn yawn+spar)]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
++ send-boon
|
|
|
|
|= boon=eauth-boon
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
^- move
|
2023-06-09 16:46:04 +03:00
|
|
|
%- (trace 2 |.("eauth: sending {(trip +<.boon)}"))
|
|
|
|
[duct %give %boon boon]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
--
|
|
|
|
::
|
|
|
|
++ client
|
|
|
|
|%
|
2023-06-09 16:46:04 +03:00
|
|
|
:: +start: as the client, approve or abort an eauth attempt
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
:: assumes the duct is of an incoming eauth start/approve request
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
++ start
|
|
|
|
|= [host=ship nonce=@uv grant=?]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
^- [(list move) server-state]
|
2023-06-09 16:46:04 +03:00
|
|
|
=/ token=@uv (~(raw og (shas %eauth-token eny)) 128)
|
|
|
|
:: we always send an %open, because we need to redirect the user
|
|
|
|
:: back to the host. and we always set a timeout, because we may
|
|
|
|
:: not get a response quickly enough.
|
|
|
|
::
|
|
|
|
:- :~ (send-plea host %0 %open nonce ?:(grant `token ~))
|
|
|
|
(start-timeout /visiting/(scot %p host)/(scot %uv nonce))
|
|
|
|
==
|
|
|
|
:: make sure we aren't attempting with this nonce already,
|
|
|
|
:: then remember the secret so we can include it in the redirect
|
|
|
|
::
|
2023-06-27 23:58:22 +03:00
|
|
|
=/ book (~(gut by visiting.auth) host *logbook)
|
|
|
|
?< (~(has by map.book) nonce)
|
2023-06-09 16:46:04 +03:00
|
|
|
=. visiting.auth
|
|
|
|
%+ ~(put by visiting.auth) host
|
2023-06-27 23:58:22 +03:00
|
|
|
:- (~(put to qeu.book) nonce)
|
|
|
|
(~(put by map.book) nonce [`duct ?:(grant `token ~)])
|
2023-06-09 16:46:04 +03:00
|
|
|
state
|
2023-06-27 23:58:22 +03:00
|
|
|
:: +on-done: receive n/ack for plea we sent
|
|
|
|
::
|
|
|
|
++ on-done
|
|
|
|
|= [host=ship good=?]
|
|
|
|
^- [(list move) server-state]
|
|
|
|
%- %- trace
|
|
|
|
?: good
|
|
|
|
[2 |.("eauth: ack from {(scow %p host)}")]
|
|
|
|
[1 |.("eauth: nack from {(scow %p host)}")]
|
|
|
|
=/ book (~(gut by visiting.auth) host *logbook)
|
|
|
|
?~ ~(top to qeu.book)
|
|
|
|
%. [~ state]
|
|
|
|
(trace 0 |.("eauth: done on empty queue from {(scow %p host)}"))
|
|
|
|
=^ nonce=@uv qeu.book ~(get to qeu.book)
|
|
|
|
?: good
|
|
|
|
=. visiting.auth
|
|
|
|
?: =([~ ~] book)
|
|
|
|
(~(del by visiting.auth) host)
|
|
|
|
(~(put by visiting.auth) host book)
|
|
|
|
[~ state]
|
|
|
|
=/ port (~(get by map.book) nonce)
|
|
|
|
?~ port [~ state]
|
|
|
|
:: delete the attempt/session, serve response if needed
|
|
|
|
::
|
|
|
|
=. visiting.auth
|
|
|
|
=. map.book
|
|
|
|
(~(del by map.book) nonce)
|
|
|
|
?: =([~ ~] book)
|
|
|
|
(~(del by visiting.auth) host)
|
|
|
|
(~(put by visiting.auth) host book)
|
|
|
|
::
|
|
|
|
?@ u.port [~ state]
|
|
|
|
?~ pend.u.port [~ state]
|
|
|
|
%^ return-static-data-on-duct(duct u.pend.u.port) 503 'text/html'
|
|
|
|
(eauth-error-page ~)
|
2023-06-09 16:46:04 +03:00
|
|
|
:: +on-boon: receive an eauth network response from a host
|
|
|
|
::
|
|
|
|
:: crashes on unexpected circumstances, in response to which we
|
|
|
|
:: should abort the eauth attempt
|
|
|
|
::
|
|
|
|
++ on-boon
|
|
|
|
|= [host=ship boon=eauth-boon]
|
|
|
|
^- [(list move) server-state]
|
|
|
|
%- (trace 2 |.("eauth: %{(trip +<.boon)} from {(scow %p host)}"))
|
|
|
|
?- +<.boon
|
|
|
|
%okay
|
2023-06-27 23:58:22 +03:00
|
|
|
=/ book (~(got by visiting.auth) host)
|
|
|
|
=/ port (~(got by map.book) nonce.boon)
|
2023-06-09 16:46:04 +03:00
|
|
|
?> ?=(^ port)
|
|
|
|
?> ?=(^ pend.port)
|
|
|
|
:: update the outgoing sessions map, deleting if we aborted
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
|
|
|
=. visiting.auth
|
2023-06-09 16:46:04 +03:00
|
|
|
?^ toke.port
|
|
|
|
%+ ~(put by visiting.auth) host
|
2023-06-27 23:58:22 +03:00
|
|
|
:- qeu.book
|
2023-06-09 16:46:04 +03:00
|
|
|
::NOTE optimistic
|
2023-06-27 23:58:22 +03:00
|
|
|
(~(put by map.book) nonce.boon now)
|
|
|
|
=. map.book
|
|
|
|
(~(del by map.book) nonce.boon)
|
|
|
|
?: =([~ ~] book)
|
|
|
|
(~(del by visiting.auth) host)
|
|
|
|
(~(put by visiting.auth) host book)
|
2023-06-09 16:46:04 +03:00
|
|
|
:: always serve a redirect, with either the token, or abort signal
|
|
|
|
::
|
|
|
|
=; url=@t
|
|
|
|
%- handle-response(duct u.pend.port)
|
|
|
|
[%start 303^['location' url]~ ~ &]
|
|
|
|
%+ rap 3
|
|
|
|
:* url.boon
|
|
|
|
'?nonce=' (scot %uv nonce.boon)
|
|
|
|
?~ toke.port ['&abort']~
|
|
|
|
~['&token=' (scot %uv u.toke.port)]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
==
|
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
%shut
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: the host has deleted the corresponding session
|
|
|
|
::
|
|
|
|
=. visiting.auth
|
2023-06-27 23:58:22 +03:00
|
|
|
=/ book
|
|
|
|
(~(gut by visiting.auth) host *logbook)
|
|
|
|
=. map.book
|
|
|
|
(~(del by map.book) nonce.boon)
|
|
|
|
?: =([~ ~] book)
|
|
|
|
(~(del by visiting.auth) host)
|
|
|
|
(~(put by visiting.auth) host book)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
[~ state]
|
|
|
|
==
|
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
++ expire
|
|
|
|
|= [host=ship nonce=@uv]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
^- [(list move) server-state]
|
2023-06-27 23:58:22 +03:00
|
|
|
=/ book (~(gut by visiting.auth) host *logbook)
|
|
|
|
=/ port (~(get by map.book) nonce)
|
2023-06-09 16:46:04 +03:00
|
|
|
:: if the attempt was completed, we don't expire it
|
|
|
|
::
|
|
|
|
?~ port [~ state]
|
|
|
|
?@ u.port [~ state]
|
|
|
|
:: delete pending attempts, serve response if needed
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
%- %+ trace 1
|
|
|
|
|.("eauth: attempt into {(scow %p host)} expired")
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
=. visiting.auth
|
2023-06-27 23:58:22 +03:00
|
|
|
=. map.book
|
|
|
|
(~(del by map.book) nonce)
|
|
|
|
?: =([~ ~] book)
|
|
|
|
(~(del by visiting.auth) host)
|
|
|
|
(~(put by visiting.auth) host book)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
?~ pend.u.port [~ state]
|
|
|
|
%^ return-static-data-on-duct(duct u.pend.u.port) 503 'text/html'
|
|
|
|
(eauth-error-page ~)
|
2023-05-23 23:37:05 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
++ send-plea
|
|
|
|
|= [=ship plea=eauth-plea]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
^- move
|
2023-06-09 16:46:04 +03:00
|
|
|
::NOTE no nonce in the wire, to avoid proliferating flows
|
|
|
|
=/ =wire /eauth/plea/(scot %p ship)
|
|
|
|
%- (trace 2 |.("eauth: {(trip +<.plea)} into {(scow %p ship)}"))
|
|
|
|
[[/eyre/eauth/synthetic]~ %pass wire %a %plea ship %e /eauth/0 plea]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
|
|
|
++ confirmation-page
|
|
|
|
|= [server=ship nonce=@uv]
|
|
|
|
^- octs
|
|
|
|
%- as-octs:mimes:html
|
|
|
|
%- crip
|
|
|
|
%- en-xml:html
|
|
|
|
=/ favicon %+
|
|
|
|
weld "<svg width='10' height='10' viewBox='0 0 10 10' xmlns='http://www.w3.org/2000/svg'>"
|
|
|
|
"<circle r='3.09' cx='5' cy='5' /></svg>"
|
|
|
|
;html
|
|
|
|
;head
|
|
|
|
;meta(charset "utf-8");
|
|
|
|
;meta(name "viewport", content "width=device-width, initial-scale=1, shrink-to-fit=no");
|
|
|
|
;link(rel "icon", type "image/svg+xml", href (weld "data:image/svg+xml;utf8," favicon));
|
|
|
|
;title:"Urbit"
|
2023-05-22 20:48:28 +03:00
|
|
|
;style:"{(trip auth-styling)}"
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
;style:'''
|
2023-05-22 20:48:28 +03:00
|
|
|
form {
|
|
|
|
border: 1px solid var(--black20);
|
|
|
|
border-radius: 4px;
|
|
|
|
padding: 1rem;
|
|
|
|
align-items: stretch;
|
|
|
|
font-size: 14px;
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
}
|
2023-05-22 20:48:28 +03:00
|
|
|
.red {
|
|
|
|
background: var(--black05) !important;
|
|
|
|
color: var(--black60) !important;
|
|
|
|
border: 1px solid var(--black60) !important;
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
}
|
2023-05-22 20:48:28 +03:00
|
|
|
code {
|
|
|
|
font-weight: bold;
|
|
|
|
font-family: "Source Code Pro", monospace;
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
}
|
2023-05-22 20:48:28 +03:00
|
|
|
button {
|
|
|
|
display: inline-block;
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
}
|
|
|
|
'''
|
|
|
|
==
|
|
|
|
;body
|
|
|
|
;form(action "/~/eauth", method "post")
|
2023-06-16 22:22:37 +03:00
|
|
|
; Hello, {(scow %p our)}.
|
2023-05-22 20:48:28 +03:00
|
|
|
; You are trying to log in to:
|
|
|
|
;code:"{(scow %p server)}"
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
;input(type "hidden", name "server", value (scow %p server));
|
|
|
|
;input(type "hidden", name "nonce", value (scow %uv nonce));
|
|
|
|
;button(type "submit", name "grant", value "grant"):"approve"
|
2023-05-22 20:48:28 +03:00
|
|
|
;button(type "submit", name "reject", class "red"):"reject"
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
==
|
|
|
|
==
|
|
|
|
==
|
|
|
|
--
|
|
|
|
:: +on-request: http request to the /~/eauth endpoint
|
|
|
|
::
|
|
|
|
++ on-request
|
|
|
|
|= [[session-id=@uv =identity] =request:http]
|
|
|
|
^- [(list move) server-state]
|
2023-05-19 20:23:24 +03:00
|
|
|
:: we may need the requester to log in before proceeding
|
|
|
|
::
|
|
|
|
=* login
|
2023-05-19 23:53:02 +03:00
|
|
|
=; url=@t (handle-response %start 303^['location' url]~ ~ &)
|
2023-05-19 20:23:24 +03:00
|
|
|
%^ cat 3 '/~/login?redirect='
|
|
|
|
(crip (en-urlt:html (trip url.request)))
|
2023-05-23 20:31:01 +03:00
|
|
|
:: or give them a generic, static error page in unexpected cases
|
|
|
|
::
|
|
|
|
=* error %^ return-static-data-on-duct 400 'text/html'
|
|
|
|
(eauth-error-page ~)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: GET requests either render the confirmation page,
|
|
|
|
:: or finalize an eauth flow
|
|
|
|
::
|
|
|
|
?: ?=(%'GET' method.request)
|
|
|
|
=/ args=(map @t @t) (malt args:(parse-request-line url.request))
|
|
|
|
=/ server=(unit @p) (biff (~(get by args) 'server') (cury slaw %p))
|
|
|
|
=/ nonce=(unit @uv) (biff (~(get by args) 'nonce') (cury slaw %uv))
|
|
|
|
=/ token=(unit @uv) (biff (~(get by args) 'token') (cury slaw %uv))
|
|
|
|
=/ abort=? (~(has by args) 'abort')
|
|
|
|
::
|
2023-05-23 20:31:01 +03:00
|
|
|
?~ nonce error
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
|
|
|
?^ server
|
|
|
|
:: request for confirmation page
|
|
|
|
::
|
2023-05-19 20:23:24 +03:00
|
|
|
?. ?=(%ours -.identity) login
|
2023-06-27 23:58:22 +03:00
|
|
|
=/ book (~(gut by visiting.auth) u.server *logbook)
|
|
|
|
=/ door (~(get by map.book) u.nonce)
|
2023-06-09 16:46:04 +03:00
|
|
|
?~ door
|
|
|
|
:: nonce not yet used, render the confirmation page as normal
|
|
|
|
::
|
|
|
|
%^ return-static-data-on-duct 200 'text/html'
|
|
|
|
(confirmation-page:client u.server u.nonce)
|
|
|
|
:: if we're still awaiting a redirect target, we choose to serve
|
|
|
|
:: this latest request instead
|
|
|
|
::
|
|
|
|
?@ u.door error
|
|
|
|
?~ pend.u.door error
|
2023-06-27 23:58:22 +03:00
|
|
|
=. map.book (~(put by map.book) u.nonce u.door(pend `duct))
|
|
|
|
=. visiting.auth (~(put by visiting.auth) u.server book)
|
2023-06-09 16:46:04 +03:00
|
|
|
%- return-static-data-on-duct(duct u.pend.u.door)
|
|
|
|
[202 'text/plain' (as-octs:mimes:html 'continued elsewhere...')]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: important to provide an error response for unexpected states
|
|
|
|
::
|
|
|
|
=/ visa=(unit visitor) (~(get by visitors.auth) u.nonce)
|
|
|
|
?~ visa error
|
|
|
|
?@ +.u.visa error
|
2023-05-23 20:31:01 +03:00
|
|
|
=* error %^ return-static-data-on-duct 400 'text/html'
|
|
|
|
(eauth-error-page %server last.u.visa)
|
2023-06-09 16:46:04 +03:00
|
|
|
:: request for finalization, must either abort or provide a token
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-05-19 20:23:24 +03:00
|
|
|
::NOTE yes, this means that unauthenticated clients can abort
|
|
|
|
:: any eauth attempt they know the nonce for, but that should
|
|
|
|
:: be pretty benign
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
?: abort (cancel:^server u.nonce last.u.visa)
|
|
|
|
?~ token error
|
2023-06-09 16:46:04 +03:00
|
|
|
:: if this request provides a token, but the client didn't, complain
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
?~ toke.u.visa error
|
|
|
|
:: verify the request
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
|
|
|
?. =(u.token u.toke.u.visa)
|
2023-05-23 23:39:48 +03:00
|
|
|
%- (trace 1 |.("eauth: token mismatch"))
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
error
|
2023-06-09 16:46:04 +03:00
|
|
|
?~ duct.u.visa error
|
|
|
|
(finalize:^server u.duct.u.visa u.nonce ship.u.visa last.u.visa)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
|
|
|
?. ?=(%'POST' method.request)
|
|
|
|
%^ return-static-data-on-duct 405 'text/html'
|
2023-05-23 20:31:01 +03:00
|
|
|
(eauth-error-page ~)
|
2023-05-19 20:23:24 +03:00
|
|
|
?. =(%ours -.identity) login
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
:: POST requests are always submissions of the confirmation page
|
|
|
|
::
|
|
|
|
=/ args=(map @t @t)
|
|
|
|
(malt (fall (rush q:(fall body.request *octs) yquy:de-purl:html) ~))
|
|
|
|
=/ server=(unit @p) (biff (~(get by args) 'server') (cury slaw %p))
|
|
|
|
=/ nonce=(unit @uv) (biff (~(get by args) 'nonce') (cury slaw %uv))
|
|
|
|
=/ grant=? =(`'grant' (~(get by args) 'grant'))
|
|
|
|
::
|
|
|
|
=* error %^ return-static-data-on-duct 400 'text/html'
|
2023-05-23 20:31:01 +03:00
|
|
|
(eauth-error-page ~)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
?~ server error
|
|
|
|
?~ nonce error
|
2023-06-27 23:58:22 +03:00
|
|
|
=/ book (~(gut by visiting.auth) u.server *logbook)
|
|
|
|
?: (~(has by map.book) u.nonce) error
|
2023-06-09 16:46:04 +03:00
|
|
|
(start:client u.server u.nonce grant)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
|
|
|
++ eauth-url
|
|
|
|
^- (unit @t)
|
|
|
|
=/ end=(unit @t) (clap user.endpoint.auth auth.endpoint.auth head)
|
2023-05-19 12:08:52 +03:00
|
|
|
?~ end ~
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
`(cat 3 u.end '/~/eauth')
|
|
|
|
::
|
|
|
|
++ start-timeout
|
|
|
|
|= =path
|
|
|
|
^- move
|
|
|
|
[duct %pass [%eauth %expire path] %b %wait (add now ~m5)]
|
|
|
|
--
|
2018-09-27 02:18:40 +03:00
|
|
|
--
|
2018-11-15 21:27:10 +03:00
|
|
|
:: +channel: per-event handling of requests to the channel system
|
|
|
|
::
|
|
|
|
:: Eyre offers a remote interface to your Urbit through channels, which
|
2019-03-18 23:48:00 +03:00
|
|
|
:: are persistent connections on the server which can be disconnected and
|
|
|
|
:: reconnected on the client.
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
2018-11-21 04:06:04 +03:00
|
|
|
++ by-channel
|
2018-11-15 21:27:10 +03:00
|
|
|
:: moves: the moves to be sent out at the end of this event, reversed
|
|
|
|
::
|
|
|
|
=| moves=(list move)
|
|
|
|
|%
|
|
|
|
:: +handle-request: handles an http request for the subscription system
|
|
|
|
::
|
|
|
|
++ handle-request
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
|= [[session-id=@uv =identity] =address =request:http]
|
2018-11-15 21:27:10 +03:00
|
|
|
^- [(list move) server-state]
|
|
|
|
:: parse out the path key the subscription is on
|
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
=+ request-line=(parse-request-line url.request)
|
2018-11-15 21:27:10 +03:00
|
|
|
?. ?=([@t @t @t ~] site.request-line)
|
2019-01-09 01:44:03 +03:00
|
|
|
:: url is not of the form '/~/channel/'
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
|
|
|
%^ return-static-data-on-duct 400 'text/html'
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(error-page 400 & url.request "malformed channel url")
|
2018-11-21 04:06:04 +03:00
|
|
|
:: channel-id: unique channel id parsed out of url
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
2018-11-21 04:06:04 +03:00
|
|
|
=+ channel-id=i.t.t.site.request-line
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
?: =('PUT' method.request)
|
2018-11-15 21:27:10 +03:00
|
|
|
:: PUT methods starts/modifies a channel, and returns a result immediately
|
|
|
|
::
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(on-put-request channel-id identity request)
|
2018-11-21 04:06:04 +03:00
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
?: =('GET' method.request)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(on-get-request channel-id [session-id identity] request)
|
2019-07-02 22:22:13 +03:00
|
|
|
?: =('POST' method.request)
|
|
|
|
:: POST methods are used solely for deleting channels
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(on-put-request channel-id identity request)
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
2023-02-09 22:51:34 +03:00
|
|
|
((trace 0 |.("session not a put")) `state)
|
2018-11-22 00:37:26 +03:00
|
|
|
:: +on-cancel-request: cancels an ongoing subscription
|
|
|
|
::
|
|
|
|
:: One of our long lived sessions just got closed. We put the associated
|
|
|
|
:: session back into the waiting state.
|
|
|
|
::
|
|
|
|
++ on-cancel-request
|
|
|
|
^- [(list move) server-state]
|
|
|
|
:: lookup the session id by duct
|
|
|
|
::
|
2023-02-14 19:46:07 +03:00
|
|
|
%- (trace 1 |.("{<duct>} moving channel to waiting state"))
|
2018-11-22 00:37:26 +03:00
|
|
|
::
|
2023-02-09 21:58:24 +03:00
|
|
|
?~ maybe-channel-id=(~(get by duct-to-key.channel-state.state) duct)
|
2023-02-14 19:46:07 +03:00
|
|
|
((trace 0 |.("{<duct>} no channel to move")) `state)
|
2019-01-11 03:35:09 +03:00
|
|
|
::
|
2019-10-10 14:33:11 +03:00
|
|
|
=/ maybe-session
|
|
|
|
(~(get by session.channel-state.state) u.maybe-channel-id)
|
2023-02-09 21:58:24 +03:00
|
|
|
?~ maybe-session
|
|
|
|
((trace 1 |.("{<maybe-session>} session doesn't exist")) `state)
|
2019-10-10 14:33:11 +03:00
|
|
|
::
|
|
|
|
=/ heartbeat-cancel=(list move)
|
|
|
|
?~ heartbeat.u.maybe-session ~
|
|
|
|
:~ %^ cancel-heartbeat-move
|
|
|
|
u.maybe-channel-id
|
|
|
|
date.u.heartbeat.u.maybe-session
|
|
|
|
duct.u.heartbeat.u.maybe-session
|
|
|
|
==
|
|
|
|
::
|
2018-11-22 00:37:26 +03:00
|
|
|
=/ expiration-time=@da (add now channel-timeout)
|
|
|
|
::
|
2019-10-10 14:33:11 +03:00
|
|
|
:- %+ weld heartbeat-cancel
|
|
|
|
[(set-timeout-move u.maybe-channel-id expiration-time) moves]
|
2018-11-22 00:37:26 +03:00
|
|
|
%_ state
|
|
|
|
session.channel-state
|
|
|
|
%+ ~(jab by session.channel-state.state) u.maybe-channel-id
|
|
|
|
|= =channel
|
|
|
|
:: if we are canceling a known channel, it should have a listener
|
|
|
|
::
|
|
|
|
?> ?=([%| *] state.channel)
|
2019-10-10 14:33:11 +03:00
|
|
|
channel(state [%& [expiration-time duct]], heartbeat ~)
|
2018-11-22 00:37:26 +03:00
|
|
|
::
|
|
|
|
duct-to-key.channel-state
|
|
|
|
(~(del by duct-to-key.channel-state.state) duct)
|
|
|
|
==
|
|
|
|
:: +set-timeout-timer-for: sets a timeout timer on a channel
|
|
|
|
::
|
|
|
|
:: This creates a channel if it doesn't exist, cancels existing timers
|
|
|
|
:: if they're already set (we cannot have duplicate timers), and (if
|
|
|
|
:: necessary) moves channels from the listening state to the expiration
|
|
|
|
:: state.
|
|
|
|
::
|
|
|
|
++ update-timeout-timer-for
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
|= [mode=?(%json %jam) =identity channel-id=@t]
|
2018-11-22 00:37:26 +03:00
|
|
|
^+ ..update-timeout-timer-for
|
|
|
|
:: when our callback should fire
|
|
|
|
::
|
|
|
|
=/ expiration-time=@da (add now channel-timeout)
|
|
|
|
:: if the channel doesn't exist, create it and set a timer
|
|
|
|
::
|
|
|
|
?~ maybe-channel=(~(get by session.channel-state.state) channel-id)
|
|
|
|
::
|
|
|
|
%_ ..update-timeout-timer-for
|
|
|
|
session.channel-state.state
|
|
|
|
%+ ~(put by session.channel-state.state) channel-id
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
[mode identity [%& expiration-time duct] 0 now ~ ~ ~ ~]
|
2018-11-22 00:37:26 +03:00
|
|
|
::
|
|
|
|
moves
|
|
|
|
[(set-timeout-move channel-id expiration-time) moves]
|
|
|
|
==
|
|
|
|
:: if the channel has an active listener, we aren't setting any timers
|
|
|
|
::
|
|
|
|
?: ?=([%| *] state.u.maybe-channel)
|
|
|
|
..update-timeout-timer-for
|
|
|
|
:: we have a previous timer; cancel the old one and set the new one
|
|
|
|
::
|
|
|
|
%_ ..update-timeout-timer-for
|
|
|
|
session.channel-state.state
|
|
|
|
%+ ~(jab by session.channel-state.state) channel-id
|
|
|
|
|= =channel
|
|
|
|
channel(state [%& [expiration-time duct]])
|
|
|
|
::
|
|
|
|
moves
|
|
|
|
:* (cancel-timeout-move channel-id p.state.u.maybe-channel)
|
|
|
|
(set-timeout-move channel-id expiration-time)
|
|
|
|
moves
|
|
|
|
==
|
|
|
|
==
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
2019-10-07 02:26:03 +03:00
|
|
|
++ set-heartbeat-move
|
|
|
|
|= [channel-id=@t heartbeat-time=@da]
|
|
|
|
^- move
|
|
|
|
:^ duct %pass /channel/heartbeat/[channel-id]
|
|
|
|
[%b %wait heartbeat-time]
|
|
|
|
::
|
|
|
|
++ cancel-heartbeat-move
|
|
|
|
|= [channel-id=@t heartbeat-time=@da =^duct]
|
|
|
|
^- move
|
|
|
|
:^ duct %pass /channel/heartbeat/[channel-id]
|
|
|
|
[%b %rest heartbeat-time]
|
|
|
|
::
|
2018-11-22 00:37:26 +03:00
|
|
|
++ set-timeout-move
|
|
|
|
|= [channel-id=@t expiration-time=@da]
|
|
|
|
^- move
|
|
|
|
[duct %pass /channel/timeout/[channel-id] %b %wait expiration-time]
|
|
|
|
::
|
|
|
|
++ cancel-timeout-move
|
|
|
|
|= [channel-id=@t expiration-time=@da =^duct]
|
|
|
|
^- move
|
|
|
|
:^ duct %pass /channel/timeout/[channel-id]
|
|
|
|
[%b %rest expiration-time]
|
2018-11-21 04:06:04 +03:00
|
|
|
:: +on-get-request: handles a GET request
|
|
|
|
::
|
|
|
|
:: GET requests open a channel for the server to send events to the
|
|
|
|
:: client in text/event-stream format.
|
|
|
|
::
|
|
|
|
++ on-get-request
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
|= [channel-id=@t [session-id=@uv =identity] =request:http]
|
2018-11-21 04:06:04 +03:00
|
|
|
^- [(list move) server-state]
|
|
|
|
:: if there's no channel-id, we must 404
|
2022-11-28 20:30:04 +03:00
|
|
|
::TODO but arm description says otherwise?
|
2018-11-21 04:06:04 +03:00
|
|
|
::
|
|
|
|
?~ maybe-channel=(~(get by session.channel-state.state) channel-id)
|
|
|
|
%^ return-static-data-on-duct 404 'text/html'
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(error-page 404 | url.request ~)
|
|
|
|
:: find the channel creator's identity, make sure it matches
|
|
|
|
::
|
|
|
|
?. =(identity identity.u.maybe-channel)
|
|
|
|
%^ return-static-data-on-duct 403 'text/html'
|
|
|
|
(error-page 403 | url.request ~)
|
2022-11-28 20:30:04 +03:00
|
|
|
:: find the requested "mode" and make sure it doesn't conflict
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
::
|
2022-11-28 20:30:04 +03:00
|
|
|
=/ mode=?(%json %jam)
|
|
|
|
(find-channel-mode %'GET' header-list.request)
|
|
|
|
?. =(mode mode.u.maybe-channel)
|
|
|
|
%^ return-static-data-on-duct 406 'text/html'
|
|
|
|
=; msg=tape (error-page 406 %.y url.request msg)
|
|
|
|
"channel already established in {(trip mode.u.maybe-channel)} mode"
|
2018-11-21 04:06:04 +03:00
|
|
|
:: when opening an event-stream, we must cancel our timeout timer
|
2021-06-24 03:24:55 +03:00
|
|
|
:: if there's no duct already bound. Else, kill the old request
|
|
|
|
:: and replace it
|
|
|
|
::
|
|
|
|
=^ cancel-moves state
|
2021-06-25 01:28:06 +03:00
|
|
|
?. ?=([%| *] state.u.maybe-channel)
|
2021-06-24 03:24:55 +03:00
|
|
|
:_ state
|
|
|
|
(cancel-timeout-move channel-id p.state.u.maybe-channel)^~
|
2021-06-25 01:28:06 +03:00
|
|
|
=/ cancel-heartbeat
|
2021-06-24 03:24:55 +03:00
|
|
|
?~ heartbeat.u.maybe-channel ~
|
|
|
|
:_ ~
|
2021-06-25 01:28:06 +03:00
|
|
|
%+ cancel-heartbeat-move channel-id
|
2021-06-24 03:24:55 +03:00
|
|
|
[date duct]:u.heartbeat.u.maybe-channel
|
|
|
|
=- [(weld cancel-heartbeat -<) ->]
|
2021-06-25 01:28:06 +03:00
|
|
|
(handle-response(duct p.state.u.maybe-channel) [%cancel ~])
|
2019-02-09 00:16:42 +03:00
|
|
|
:: the request may include a 'Last-Event-Id' header
|
2018-11-21 04:06:04 +03:00
|
|
|
::
|
|
|
|
=/ maybe-last-event-id=(unit @ud)
|
2022-08-30 17:44:11 +03:00
|
|
|
?~ maybe-raw-header=(get-header:http 'last-event-id' header-list.request)
|
2018-11-21 04:06:04 +03:00
|
|
|
~
|
|
|
|
(rush u.maybe-raw-header dum:ag)
|
|
|
|
:: flush events older than the passed in 'Last-Event-ID'
|
|
|
|
::
|
|
|
|
=? state ?=(^ maybe-last-event-id)
|
|
|
|
(acknowledge-events channel-id u.maybe-last-event-id)
|
|
|
|
:: combine the remaining queued events to send to the client
|
|
|
|
::
|
|
|
|
=/ event-replay=wall
|
|
|
|
%- zing
|
|
|
|
%- flop
|
|
|
|
=/ queue events.u.maybe-channel
|
|
|
|
=| events=(list wall)
|
|
|
|
|-
|
|
|
|
^+ events
|
|
|
|
?: =(~ queue)
|
|
|
|
events
|
|
|
|
=^ head queue ~(get to queue)
|
2020-10-18 12:18:29 +03:00
|
|
|
=, p.head
|
2020-10-19 20:17:58 +03:00
|
|
|
::NOTE these will only fail if the mark and/or json types changed,
|
|
|
|
:: since conversion failure also gets caught during first receive.
|
|
|
|
:: we can't do anything about this, so consider it unsupported.
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
=/ said
|
2023-04-20 16:18:52 +03:00
|
|
|
(channel-event-to-tape u.maybe-channel request-id channel-event)
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
?~ said $
|
|
|
|
$(events [(event-tape-to-wall id +.u.said) events])
|
2018-11-21 04:06:04 +03:00
|
|
|
:: send the start event to the client
|
|
|
|
::
|
2019-01-11 03:35:09 +03:00
|
|
|
=^ http-moves state
|
|
|
|
%- handle-response
|
2019-02-09 00:16:42 +03:00
|
|
|
:* %start
|
|
|
|
:- 200
|
2018-11-21 04:06:04 +03:00
|
|
|
:~ ['content-type' 'text/event-stream']
|
|
|
|
['cache-control' 'no-cache']
|
|
|
|
['connection' 'keep-alive']
|
|
|
|
==
|
|
|
|
(wall-to-octs event-replay)
|
|
|
|
complete=%.n
|
|
|
|
==
|
2018-11-22 00:37:26 +03:00
|
|
|
:: associate this duct with this session key
|
|
|
|
::
|
|
|
|
=. duct-to-key.channel-state.state
|
|
|
|
(~(put by duct-to-key.channel-state.state) duct channel-id)
|
2020-06-04 23:06:13 +03:00
|
|
|
:: associate this channel with the session cookie
|
|
|
|
::
|
2023-05-19 12:31:01 +03:00
|
|
|
=. sessions.auth.state
|
|
|
|
%+ ~(jab by sessions.auth.state)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
session-id
|
2020-06-04 23:06:13 +03:00
|
|
|
|= =session
|
|
|
|
session(channels (~(put in channels.session) channel-id))
|
2019-10-07 02:26:03 +03:00
|
|
|
:: initialize sse heartbeat
|
|
|
|
::
|
|
|
|
=/ heartbeat-time=@da (add now ~s20)
|
|
|
|
=/ heartbeat (set-heartbeat-move channel-id heartbeat-time)
|
2023-04-20 16:18:52 +03:00
|
|
|
:: record the mode & duct for future output,
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
:: and record heartbeat-time for possible future cancel
|
2018-11-21 04:06:04 +03:00
|
|
|
::
|
|
|
|
=. session.channel-state.state
|
|
|
|
%+ ~(jab by session.channel-state.state) channel-id
|
|
|
|
|= =channel
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
%_ channel
|
|
|
|
mode mode
|
|
|
|
state [%| duct]
|
|
|
|
heartbeat (some [heartbeat-time duct])
|
|
|
|
==
|
2018-11-21 04:06:04 +03:00
|
|
|
::
|
2021-06-24 03:24:55 +03:00
|
|
|
[[heartbeat :(weld http-moves cancel-moves moves)] state]
|
2018-11-21 04:06:04 +03:00
|
|
|
:: +acknowledge-events: removes events before :last-event-id on :channel-id
|
|
|
|
::
|
|
|
|
++ acknowledge-events
|
|
|
|
|= [channel-id=@t last-event-id=@u]
|
|
|
|
^- server-state
|
|
|
|
%_ state
|
|
|
|
session.channel-state
|
|
|
|
%+ ~(jab by session.channel-state.state) channel-id
|
|
|
|
|= =channel
|
|
|
|
^+ channel
|
2020-10-19 16:56:05 +03:00
|
|
|
=^ acked events.channel
|
|
|
|
(prune-events events.channel last-event-id)
|
|
|
|
=. unacked.channel
|
|
|
|
(subtract-acked-events acked unacked.channel)
|
|
|
|
channel(last-ack now)
|
2018-11-21 04:06:04 +03:00
|
|
|
==
|
2018-11-15 21:27:10 +03:00
|
|
|
:: +on-put-request: handles a PUT request
|
|
|
|
::
|
2018-11-21 04:06:04 +03:00
|
|
|
:: PUT requests send commands from the client to the server. We receive
|
|
|
|
:: a set of commands in JSON format in the body of the message.
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
|
|
|
++ on-put-request
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
|= [channel-id=@t =identity =request:http]
|
2018-11-15 21:27:10 +03:00
|
|
|
^- [(list move) server-state]
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:: if the channel already exists, and is not of this identity, 403
|
|
|
|
::
|
|
|
|
:: the creation case happens in the +update-timeout-timer-for below
|
|
|
|
::
|
|
|
|
?: ?~ c=(~(get by session.channel-state.state) channel-id) |
|
|
|
|
!=(identity identity.u.c)
|
|
|
|
%^ return-static-data-on-duct 403 'text/html'
|
|
|
|
(error-page 403 | url.request ~)
|
2018-11-15 21:27:10 +03:00
|
|
|
:: error when there's no body
|
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
?~ body.request
|
2018-11-15 21:27:10 +03:00
|
|
|
%^ return-static-data-on-duct 400 'text/html'
|
2019-03-21 23:58:37 +03:00
|
|
|
(error-page 400 %.y url.request "no put body")
|
2022-11-28 20:30:04 +03:00
|
|
|
::
|
|
|
|
=/ mode=?(%json %jam)
|
|
|
|
(find-channel-mode %'PUT' header-list.request)
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
:: if we cannot parse requests from the body, give an error
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
=/ maybe-requests=(each (list channel-request) @t)
|
|
|
|
(parse-channel-request mode u.body.request)
|
|
|
|
?: ?=(%| -.maybe-requests)
|
2018-11-15 21:27:10 +03:00
|
|
|
%^ return-static-data-on-duct 400 'text/html'
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
(error-page 400 & url.request (trip p.maybe-requests))
|
2018-11-16 02:27:49 +03:00
|
|
|
:: while weird, the request list could be empty
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
?: =(~ p.maybe-requests)
|
2018-11-15 21:27:10 +03:00
|
|
|
%^ return-static-data-on-duct 400 'text/html'
|
2019-03-21 23:58:37 +03:00
|
|
|
(error-page 400 %.y url.request "empty list of actions")
|
2018-11-21 04:06:04 +03:00
|
|
|
:: check for the existence of the channel-id
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
|
|
|
:: if we have no session, create a new one set to expire in
|
2018-11-22 00:37:26 +03:00
|
|
|
:: :channel-timeout from now. if we have one which has a timer, update
|
|
|
|
:: that timer.
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=. ..on-put-request (update-timeout-timer-for mode identity channel-id)
|
2018-11-15 21:27:10 +03:00
|
|
|
:: for each request, execute the action passed in
|
|
|
|
::
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
=+ requests=p.maybe-requests
|
2018-11-20 01:59:58 +03:00
|
|
|
:: gall-moves: put moves here first so we can flop for ordering
|
2023-05-05 23:08:18 +03:00
|
|
|
:: errors: if we accumulate any, discard the gall-moves and revert
|
2018-11-20 01:59:58 +03:00
|
|
|
::
|
|
|
|
=| gall-moves=(list move)
|
2023-05-05 23:08:18 +03:00
|
|
|
=| errors=(map @ud @t)
|
|
|
|
=/ og-state state
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=/ from=ship
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
?+(-.identity who.identity %ours our)
|
2018-11-15 21:27:10 +03:00
|
|
|
|-
|
2018-11-17 01:30:23 +03:00
|
|
|
::
|
2018-11-15 21:27:10 +03:00
|
|
|
?~ requests
|
2023-05-05 23:08:18 +03:00
|
|
|
?: =(~ errors)
|
|
|
|
:: everything succeeded, mark the request as completed
|
|
|
|
::
|
|
|
|
=^ http-moves state
|
|
|
|
%- handle-response
|
|
|
|
:* %start
|
|
|
|
[status-code=204 headers=~]
|
|
|
|
data=~
|
|
|
|
complete=%.y
|
|
|
|
==
|
|
|
|
::
|
|
|
|
[:(weld (flop gall-moves) http-moves moves) state]
|
|
|
|
:: some things went wrong. revert all operations & give 400
|
2018-11-17 01:30:23 +03:00
|
|
|
::
|
2023-05-05 23:08:18 +03:00
|
|
|
%- (trace 1 |.("{<channel-id>} reverting due to errors"))
|
|
|
|
=. state og-state
|
2019-01-11 03:35:09 +03:00
|
|
|
=^ http-moves state
|
2023-05-05 23:08:18 +03:00
|
|
|
%^ return-static-data-on-duct 400 'text/html'
|
|
|
|
%- as-octs:mimes:html
|
|
|
|
%+ rap 3
|
|
|
|
%+ turn (sort ~(tap by errors) dor)
|
|
|
|
|= [id=@ud er=@t]
|
|
|
|
(rap 3 (crip (a-co:co id)) ': ' er '<br/>' ~)
|
|
|
|
[(weld http-moves moves) state]
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
|
|
|
?- -.i.requests
|
|
|
|
%ack
|
2019-01-12 01:15:17 +03:00
|
|
|
:: client acknowledges that they have received up to event-id
|
|
|
|
::
|
|
|
|
%_ $
|
|
|
|
state (acknowledge-events channel-id event-id.i.requests)
|
|
|
|
requests t.requests
|
|
|
|
==
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
?(%poke %poke-json)
|
2023-05-05 23:08:18 +03:00
|
|
|
=, i.requests
|
|
|
|
::
|
|
|
|
?. |(=(from our) =(ship our))
|
|
|
|
=+ [request-id 'non-local operation']
|
|
|
|
$(errors (~(put by errors) -), requests t.requests)
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
2018-11-20 01:59:58 +03:00
|
|
|
=. gall-moves
|
2023-05-22 16:12:09 +03:00
|
|
|
=/ =wire /channel/poke/[channel-id]/(scot %ud request-id.i.requests)
|
2018-11-20 01:59:58 +03:00
|
|
|
:_ gall-moves
|
2018-11-17 01:30:23 +03:00
|
|
|
^- move
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
%+ deal-as
|
|
|
|
/channel/poke/[channel-id]/(scot %ud request-id)
|
|
|
|
:^ from ship app
|
|
|
|
^- task:agent:gall
|
|
|
|
:+ %poke-as mark
|
|
|
|
?- -.i.requests
|
|
|
|
%poke [%noun !>(noun)]
|
|
|
|
%poke-json [%json !>(json)]
|
2019-11-05 10:42:59 +03:00
|
|
|
==
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
|
|
|
$(requests t.requests)
|
|
|
|
::
|
2019-11-14 06:38:13 +03:00
|
|
|
%subscribe
|
2020-08-27 14:47:18 +03:00
|
|
|
=, i.requests
|
2019-03-27 01:52:32 +03:00
|
|
|
::
|
2023-05-05 23:08:18 +03:00
|
|
|
?. |(=(from our) =(ship our))
|
|
|
|
=+ [request-id 'non-local operation']
|
|
|
|
$(errors (~(put by errors) -), requests t.requests)
|
|
|
|
::
|
|
|
|
::TODO could error if the subscription is a duplicate
|
2018-11-20 01:59:58 +03:00
|
|
|
=. gall-moves
|
|
|
|
:_ gall-moves
|
|
|
|
^- move
|
2023-02-09 20:55:08 +03:00
|
|
|
%- (trace 1 |.("subscribing to {<app>} on {<path>}"))
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
%+ deal-as
|
|
|
|
(subscription-wire channel-id request-id ship app)
|
|
|
|
[from ship app %watch path]
|
2018-11-20 01:59:58 +03:00
|
|
|
::
|
|
|
|
=. session.channel-state.state
|
2018-11-21 04:06:04 +03:00
|
|
|
%+ ~(jab by session.channel-state.state) channel-id
|
|
|
|
|= =channel
|
2020-10-19 01:48:18 +03:00
|
|
|
=- channel(subscriptions -)
|
|
|
|
%+ ~(put by subscriptions.channel)
|
|
|
|
request-id
|
|
|
|
[ship app path duct]
|
2018-11-20 01:59:58 +03:00
|
|
|
::
|
|
|
|
$(requests t.requests)
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
2019-11-14 06:38:13 +03:00
|
|
|
%unsubscribe
|
2020-10-19 01:48:18 +03:00
|
|
|
=, i.requests
|
2019-03-27 01:52:32 +03:00
|
|
|
::
|
2023-05-05 23:08:18 +03:00
|
|
|
?. |(=(from our) =(ship our))
|
|
|
|
=+ [request-id 'non-local operation']
|
|
|
|
$(errors (~(put by errors) -), requests t.requests)
|
|
|
|
::
|
2019-07-17 20:51:56 +03:00
|
|
|
=/ usession (~(get by session.channel-state.state) channel-id)
|
|
|
|
?~ usession
|
|
|
|
$(requests t.requests)
|
|
|
|
=/ subscriptions subscriptions:u.usession
|
2019-03-27 01:52:32 +03:00
|
|
|
::
|
2020-10-19 01:48:18 +03:00
|
|
|
?~ maybe-subscription=(~(get by subscriptions) subscription-id)
|
2019-03-27 01:52:32 +03:00
|
|
|
:: the client sent us a weird request referring to a subscription
|
|
|
|
:: which isn't active.
|
|
|
|
::
|
2023-02-09 01:03:02 +03:00
|
|
|
%. $(requests t.requests)
|
2023-02-09 22:51:34 +03:00
|
|
|
=* msg=tape "{(trip channel-id)} {<subscription-id>}"
|
2023-02-09 23:06:06 +03:00
|
|
|
(trace 0 |.("missing subscription in unsubscribe {msg}"))
|
2019-03-15 21:25:12 +03:00
|
|
|
::
|
|
|
|
=. gall-moves
|
|
|
|
:_ gall-moves
|
|
|
|
^- move
|
2019-03-27 01:52:32 +03:00
|
|
|
=, u.maybe-subscription
|
2023-02-09 22:22:50 +03:00
|
|
|
%- (trace 1 |.("leaving subscription to {<app>}"))
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
%+ deal-as
|
|
|
|
(subscription-wire channel-id subscription-id ship app)
|
|
|
|
[from ship app %leave ~]
|
2019-03-15 21:25:12 +03:00
|
|
|
::
|
|
|
|
=. session.channel-state.state
|
|
|
|
%+ ~(jab by session.channel-state.state) channel-id
|
|
|
|
|= =channel
|
2020-10-19 16:56:05 +03:00
|
|
|
%_ channel
|
|
|
|
subscriptions (~(del by subscriptions.channel) subscription-id)
|
|
|
|
unacked (~(del by unacked.channel) subscription-id)
|
|
|
|
==
|
2019-03-15 21:25:12 +03:00
|
|
|
::
|
|
|
|
$(requests t.requests)
|
2019-06-14 00:53:04 +03:00
|
|
|
::
|
|
|
|
%delete
|
2023-02-09 21:58:24 +03:00
|
|
|
%- (trace 1 |.("{<channel-id>} discarding due to %delete PUT"))
|
2020-06-04 18:12:35 +03:00
|
|
|
=^ moves state
|
|
|
|
(discard-channel channel-id |)
|
2019-06-14 00:53:04 +03:00
|
|
|
=. gall-moves
|
2020-06-04 18:12:35 +03:00
|
|
|
(weld gall-moves moves)
|
2019-06-14 00:53:04 +03:00
|
|
|
$(requests t.requests)
|
|
|
|
::
|
2018-11-15 21:27:10 +03:00
|
|
|
==
|
2020-10-18 12:18:29 +03:00
|
|
|
:: +on-gall-response: sanity-check a gall response, send as event
|
2018-11-21 04:06:04 +03:00
|
|
|
::
|
|
|
|
++ on-gall-response
|
2020-08-27 14:47:18 +03:00
|
|
|
|= [channel-id=@t request-id=@ud extra=wire =sign:agent:gall]
|
2018-11-21 04:06:04 +03:00
|
|
|
^- [(list move) server-state]
|
2020-08-27 14:47:18 +03:00
|
|
|
:: if the channel doesn't exist, we should clean up subscriptions
|
|
|
|
::
|
|
|
|
:: this is a band-aid solution. you really want eyre to have cleaned
|
|
|
|
:: these up on-channel-delete in the first place.
|
|
|
|
:: until the source of that bug is discovered though, we keep this
|
|
|
|
:: in place to ensure a slightly tidier home.
|
|
|
|
::
|
2020-10-18 12:18:29 +03:00
|
|
|
?. ?& !(~(has by session.channel-state.state) channel-id)
|
2020-08-27 14:47:18 +03:00
|
|
|
?=(?(%fact %watch-ack) -.sign)
|
|
|
|
?=([@ @ ~] extra)
|
|
|
|
==
|
2020-10-18 12:18:29 +03:00
|
|
|
(emit-event channel-id request-id sign)
|
|
|
|
=/ =ship (slav %p i.extra)
|
|
|
|
=* app=term i.t.extra
|
2023-02-09 22:22:50 +03:00
|
|
|
=* msg=tape "{(trip channel-id)} {(trip app)}"
|
2023-02-09 20:55:08 +03:00
|
|
|
%- (trace 0 |.("removing watch for non-existent channel {msg}"))
|
2020-10-18 12:18:29 +03:00
|
|
|
:_ state
|
|
|
|
:_ ~
|
|
|
|
^- move
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
%+ deal-as
|
2020-10-18 12:18:29 +03:00
|
|
|
(subscription-wire channel-id request-id ship app)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=+ id=identity:(~(got by session.channel-state.state) channel-id)
|
|
|
|
[id ship app %leave ~]
|
2018-11-21 04:06:04 +03:00
|
|
|
:: +emit-event: records an event occurred, possibly sending to client
|
|
|
|
::
|
|
|
|
:: When an event occurs, we need to record it, even if we immediately
|
|
|
|
:: send it to a connected browser so in case of disconnection, we can
|
|
|
|
:: resend it.
|
|
|
|
::
|
2020-10-19 16:56:05 +03:00
|
|
|
:: This function is responsible for taking the event sign and converting
|
|
|
|
:: it into a text/event-stream. The :sign then may get sent, and is
|
|
|
|
:: stored for later resending until acknowledged by the client.
|
2018-11-21 04:06:04 +03:00
|
|
|
::
|
|
|
|
++ emit-event
|
2020-10-18 12:18:29 +03:00
|
|
|
|= [channel-id=@t request-id=@ud =sign:agent:gall]
|
2018-11-21 04:06:04 +03:00
|
|
|
^- [(list move) server-state]
|
|
|
|
::
|
2019-03-29 20:44:37 +03:00
|
|
|
=/ channel=(unit channel)
|
|
|
|
(~(get by session.channel-state.state) channel-id)
|
|
|
|
?~ channel
|
2019-12-14 11:43:04 +03:00
|
|
|
:_ state :_ ~
|
|
|
|
[duct %pass /flog %d %flog %crud %eyre-no-channel >id=channel-id< ~]
|
2020-11-11 00:06:28 +03:00
|
|
|
:: it's possible that this is a sign emitted directly alongside a fact
|
2020-10-24 12:45:21 +03:00
|
|
|
:: that triggered a clog & closed the subscription. in that case, just
|
2020-11-11 00:06:28 +03:00
|
|
|
:: drop the sign.
|
|
|
|
:: poke-acks are not paired with subscriptions, so we can process them
|
|
|
|
:: regardless.
|
2020-10-24 12:45:21 +03:00
|
|
|
::
|
2020-11-11 00:06:28 +03:00
|
|
|
?: ?& !?=(%poke-ack -.sign)
|
2020-10-24 12:45:21 +03:00
|
|
|
!(~(has by subscriptions.u.channel) request-id)
|
|
|
|
==
|
|
|
|
[~ state]
|
2020-10-19 20:17:58 +03:00
|
|
|
:: attempt to convert the sign to json.
|
|
|
|
:: if conversion succeeds, we *can* send it. if the client is actually
|
|
|
|
:: connected, we *will* send it immediately.
|
2018-11-21 04:06:04 +03:00
|
|
|
::
|
2023-04-20 16:18:52 +03:00
|
|
|
=/ maybe-channel-event=(unit channel-event)
|
|
|
|
(sign-to-channel-event sign u.channel request-id)
|
|
|
|
?~ maybe-channel-event [~ state]
|
|
|
|
=/ =channel-event u.maybe-channel-event
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
=/ said=(unit (quip move tape))
|
2023-04-20 16:18:52 +03:00
|
|
|
(channel-event-to-tape u.channel request-id channel-event)
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
=? moves ?=(^ said)
|
|
|
|
(weld moves -.u.said)
|
|
|
|
=* sending &(?=([%| *] state.u.channel) ?=(^ said))
|
2020-10-19 16:56:05 +03:00
|
|
|
::
|
2020-10-19 20:17:58 +03:00
|
|
|
=/ next-id next-id.u.channel
|
|
|
|
:: if we can send it, store the event as unacked
|
|
|
|
::
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
=? events.u.channel ?=(^ said)
|
2020-10-19 16:56:05 +03:00
|
|
|
%- ~(put to events.u.channel)
|
2023-04-20 16:18:52 +03:00
|
|
|
[next-id request-id channel-event]
|
2020-10-19 20:17:58 +03:00
|
|
|
:: if it makes sense to do so, send the event to the client
|
2018-11-21 04:06:04 +03:00
|
|
|
::
|
2020-10-19 20:17:58 +03:00
|
|
|
=? moves sending
|
2019-02-09 00:16:42 +03:00
|
|
|
^- (list move)
|
2018-11-21 04:06:04 +03:00
|
|
|
:_ moves
|
2020-10-19 20:17:58 +03:00
|
|
|
::NOTE assertions in this block because =* is flimsy
|
|
|
|
?> ?=([%| *] state.u.channel)
|
2019-03-29 20:44:37 +03:00
|
|
|
:+ p.state.u.channel %give
|
2020-12-08 03:47:06 +03:00
|
|
|
^- gift
|
2019-02-06 01:05:06 +03:00
|
|
|
:* %response %continue
|
2018-11-21 04:06:04 +03:00
|
|
|
::
|
|
|
|
^= data
|
2020-10-18 12:18:29 +03:00
|
|
|
%- wall-to-octs
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
(event-tape-to-wall next-id +:(need said))
|
2018-11-21 04:06:04 +03:00
|
|
|
::
|
|
|
|
complete=%.n
|
|
|
|
==
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
=? next-id ?=(^ said) +(next-id)
|
2020-10-19 16:56:05 +03:00
|
|
|
:: update channel's unacked counts, find out if clogged
|
|
|
|
::
|
|
|
|
=^ clogged unacked.u.channel
|
2020-11-11 00:06:28 +03:00
|
|
|
:: only apply clog logic to facts.
|
2020-10-19 20:17:58 +03:00
|
|
|
:: and of course don't count events we can't send as unacked.
|
2020-10-19 16:56:05 +03:00
|
|
|
::
|
2020-11-11 00:06:28 +03:00
|
|
|
?: ?| !?=(%fact -.sign)
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
?=(~ said)
|
2020-10-19 20:17:58 +03:00
|
|
|
==
|
|
|
|
[| unacked.u.channel]
|
2020-10-19 16:56:05 +03:00
|
|
|
=/ num=@ud
|
|
|
|
(~(gut by unacked.u.channel) request-id 0)
|
|
|
|
:_ (~(put by unacked.u.channel) request-id +(num))
|
|
|
|
?& (gte num clog-threshold)
|
|
|
|
(lth (add last-ack.u.channel clog-timeout) now)
|
|
|
|
==
|
2020-10-19 20:17:58 +03:00
|
|
|
:: if we're clogged, or we ran into an event we can't serialize,
|
|
|
|
:: kill this gall subscription.
|
2020-10-19 16:56:05 +03:00
|
|
|
::
|
2023-04-20 16:18:52 +03:00
|
|
|
=* msg=tape "on {(trip channel-id)} for {(scow %ud request-id)}"
|
2023-02-08 21:47:43 +03:00
|
|
|
=/ kicking=?
|
|
|
|
?: clogged
|
2023-02-09 23:06:06 +03:00
|
|
|
((trace 0 |.("clogged {msg}")) &)
|
2023-04-11 22:54:43 +03:00
|
|
|
?. ?=(~ said) |
|
2023-02-16 18:02:34 +03:00
|
|
|
((trace 0 |.("can't serialize event, kicking {msg}")) &)
|
2020-10-19 20:17:58 +03:00
|
|
|
=? moves kicking
|
2020-10-19 16:56:05 +03:00
|
|
|
:_ moves
|
2020-11-11 00:06:28 +03:00
|
|
|
::NOTE this shouldn't crash because we
|
|
|
|
:: - never fail to serialize subscriptionless signs (%poke-ack),
|
|
|
|
:: - only clog on %facts, which have a subscription associated,
|
|
|
|
:: - and already checked whether we still have that subscription.
|
2020-10-19 16:56:05 +03:00
|
|
|
=+ (~(got by subscriptions.u.channel) request-id)
|
2023-02-09 22:22:50 +03:00
|
|
|
%- (trace 1 |.("leaving subscription to {<app>}"))
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
%+ deal-as
|
2020-10-19 16:56:05 +03:00
|
|
|
(subscription-wire channel-id request-id ship app)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
[identity.u.channel ship app %leave ~]
|
2020-10-19 20:17:58 +03:00
|
|
|
:: update channel state to reflect the %kick
|
|
|
|
::
|
|
|
|
=? u.channel kicking
|
2020-10-19 16:56:05 +03:00
|
|
|
%_ u.channel
|
|
|
|
subscriptions (~(del by subscriptions.u.channel) request-id)
|
|
|
|
unacked (~(del by unacked.u.channel) request-id)
|
|
|
|
events %- ~(put to events.u.channel)
|
2023-04-20 16:18:52 +03:00
|
|
|
:+ next-id
|
|
|
|
request-id
|
|
|
|
(need (sign-to-channel-event [%kick ~] u.channel request-id))
|
2020-10-19 16:56:05 +03:00
|
|
|
==
|
|
|
|
:: if a client is connected, send the kick event to them
|
|
|
|
::
|
2020-10-19 20:17:58 +03:00
|
|
|
=? moves &(kicking ?=([%| *] state.u.channel))
|
2020-10-19 16:56:05 +03:00
|
|
|
:_ moves
|
|
|
|
:+ p.state.u.channel %give
|
2020-12-08 03:47:06 +03:00
|
|
|
^- gift
|
2020-10-19 16:56:05 +03:00
|
|
|
:* %response %continue
|
|
|
|
::
|
|
|
|
^= data
|
|
|
|
%- wall-to-octs
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
%+ event-tape-to-wall next-id
|
2023-04-20 16:18:52 +03:00
|
|
|
+:(need (channel-event-to-tape u.channel request-id %kick ~))
|
2020-10-19 16:56:05 +03:00
|
|
|
::
|
|
|
|
complete=%.n
|
|
|
|
==
|
2020-10-19 20:17:58 +03:00
|
|
|
=? next-id kicking +(next-id)
|
2018-11-21 04:06:04 +03:00
|
|
|
::
|
2020-10-24 02:48:51 +03:00
|
|
|
:- (flop moves)
|
2018-11-21 04:06:04 +03:00
|
|
|
%_ state
|
2018-11-22 00:37:26 +03:00
|
|
|
session.channel-state
|
2020-10-19 16:56:05 +03:00
|
|
|
%+ ~(put by session.channel-state.state) channel-id
|
2020-10-19 20:17:58 +03:00
|
|
|
u.channel(next-id next-id)
|
2020-10-18 12:18:29 +03:00
|
|
|
==
|
2020-10-19 16:56:05 +03:00
|
|
|
:: +sign-to-channel-event: strip the vase from a sign:agent:gall
|
|
|
|
::
|
|
|
|
++ sign-to-channel-event
|
2023-04-20 16:18:52 +03:00
|
|
|
|= [=sign:agent:gall =channel request-id=@ud]
|
|
|
|
^- (unit channel-event)
|
|
|
|
?. ?=(%fact -.sign) `sign
|
|
|
|
?~ desk=(app-to-desk channel request-id) ~
|
|
|
|
:- ~
|
|
|
|
[%fact u.desk [p q.q]:cage.sign]
|
2021-06-19 05:13:55 +03:00
|
|
|
:: +app-to-desk
|
|
|
|
::
|
|
|
|
++ app-to-desk
|
|
|
|
|= [=channel request-id=@ud]
|
|
|
|
^- (unit desk)
|
|
|
|
=/ sub (~(get by subscriptions.channel) request-id)
|
|
|
|
?~ sub
|
2023-04-20 16:18:52 +03:00
|
|
|
((trace 0 |.("no subscription for request-id {(scow %ud request-id)}")) ~)
|
2021-06-19 05:13:55 +03:00
|
|
|
=/ des=(unit (unit cage))
|
2023-05-22 16:12:09 +03:00
|
|
|
(rof ~ /eyre %gd [our app.u.sub da+now] /$)
|
2021-06-19 05:13:55 +03:00
|
|
|
?. ?=([~ ~ *] des)
|
2023-02-09 22:51:34 +03:00
|
|
|
((trace 0 |.("no desk for app {<app.u.sub>}")) ~)
|
2021-06-19 05:13:55 +03:00
|
|
|
`!<(=desk q.u.u.des)
|
2023-04-20 16:18:52 +03:00
|
|
|
:: +channel-event-to-tape: render channel-event from request-id in specified mode
|
2020-10-18 12:18:29 +03:00
|
|
|
::
|
2023-04-20 16:18:52 +03:00
|
|
|
++ channel-event-to-tape
|
|
|
|
|= [=channel request-id=@ud =channel-event]
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
^- (unit (quip move tape))
|
|
|
|
?- mode.channel
|
2023-04-20 16:18:52 +03:00
|
|
|
%json %+ bind (channel-event-to-json channel request-id channel-event)
|
2023-06-30 22:25:19 +03:00
|
|
|
|=((quip move json) [+<- (trip (en:json:html +<+))])
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
%jam =- `[~ (scow %uw (jam -))]
|
2023-04-20 16:18:52 +03:00
|
|
|
[request-id channel-event]
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
==
|
2023-04-20 16:18:52 +03:00
|
|
|
:: +channel-event-to-json: render channel event as json channel event
|
2020-10-18 12:18:29 +03:00
|
|
|
::
|
2023-04-20 16:18:52 +03:00
|
|
|
++ channel-event-to-json
|
|
|
|
~% %eyre-channel-event-to-json ..part ~
|
|
|
|
|= [=channel request-id=@ud event=channel-event]
|
2021-05-20 22:31:28 +03:00
|
|
|
^- (unit (quip move json))
|
2020-10-18 17:31:35 +03:00
|
|
|
:: for facts, we try to convert the result to json
|
|
|
|
::
|
2021-06-19 05:13:55 +03:00
|
|
|
=/ [from=(unit [=desk =mark]) jsyn=(unit sign:agent:gall)]
|
2023-04-20 16:18:52 +03:00
|
|
|
?. ?=(%fact -.event) [~ `event]
|
|
|
|
?: ?=(%json mark.event)
|
|
|
|
?~ jsin=((soft json) noun.event)
|
|
|
|
%. [~ ~]
|
|
|
|
(slog leaf+"eyre: dropping fake json for {(scow %ud request-id)}" ~)
|
|
|
|
[~ `[%fact %json !>(u.jsin)]]
|
2020-10-18 17:31:35 +03:00
|
|
|
:: find and use tube from fact mark to json
|
|
|
|
::
|
2021-06-19 05:13:55 +03:00
|
|
|
::
|
2023-04-20 16:18:52 +03:00
|
|
|
=* have=mark mark.event
|
2021-05-20 21:03:04 +03:00
|
|
|
=/ convert=(unit vase)
|
2021-05-20 20:11:45 +03:00
|
|
|
=/ cag=(unit (unit cage))
|
2023-05-22 16:12:09 +03:00
|
|
|
(rof ~ /eyre %cf [our desk.event da+now] /[have]/json)
|
2021-05-20 20:11:45 +03:00
|
|
|
?. ?=([~ ~ *] cag) ~
|
2021-05-20 21:03:04 +03:00
|
|
|
`q.u.u.cag
|
2021-05-20 20:11:45 +03:00
|
|
|
?~ convert
|
2023-02-09 22:56:50 +03:00
|
|
|
((trace 0 |.("no convert from {(trip have)} to json")) [~ ~])
|
|
|
|
~| "conversion failed from {(trip have)} to json"
|
2023-04-20 16:18:52 +03:00
|
|
|
[`[desk.event have] `[%fact %json (slym u.convert noun.event)]]
|
2021-05-20 22:31:28 +03:00
|
|
|
?~ jsyn ~
|
2020-10-18 17:31:35 +03:00
|
|
|
%- some
|
2021-05-20 22:31:28 +03:00
|
|
|
:- ?~ from ~
|
2021-05-19 23:40:32 +03:00
|
|
|
:_ ~
|
2021-06-19 05:13:55 +03:00
|
|
|
:^ duct %pass /conversion-cache/[mark.u.from]
|
|
|
|
[%c %warp our desk.u.from `[%sing %f da+now /[mark.u.from]/json]]
|
2021-05-20 22:31:28 +03:00
|
|
|
=* sign u.jsyn
|
2020-10-18 12:18:29 +03:00
|
|
|
=, enjs:format
|
|
|
|
%- pairs
|
|
|
|
^- (list [@t json])
|
|
|
|
:- ['id' (numb request-id)]
|
|
|
|
?- -.sign
|
|
|
|
%poke-ack
|
|
|
|
:~ ['response' [%s 'poke']]
|
|
|
|
::
|
|
|
|
?~ p.sign
|
|
|
|
['ok' [%s 'ok']]
|
|
|
|
['err' (wall (render-tang-to-wall 100 u.p.sign))]
|
|
|
|
==
|
|
|
|
::
|
|
|
|
%fact
|
2021-12-02 01:48:57 +03:00
|
|
|
:+ ['response' [%s 'diff']]
|
|
|
|
:- 'json'
|
|
|
|
~| [%unexpected-fact-mark p.cage.sign]
|
|
|
|
?> =(%json p.cage.sign)
|
|
|
|
!<(json q.cage.sign)
|
|
|
|
::
|
|
|
|
?~ from ~
|
2021-12-02 17:06:42 +03:00
|
|
|
['mark' [%s mark.u.from]]~
|
2020-10-18 12:18:29 +03:00
|
|
|
::
|
|
|
|
%kick
|
|
|
|
['response' [%s 'quit']]~
|
|
|
|
::
|
|
|
|
%watch-ack
|
|
|
|
:~ ['response' [%s 'subscribe']]
|
|
|
|
::
|
|
|
|
?~ p.sign
|
|
|
|
['ok' [%s 'ok']]
|
|
|
|
['err' (wall (render-tang-to-wall 100 u.p.sign))]
|
2018-11-21 04:06:04 +03:00
|
|
|
==
|
|
|
|
==
|
2019-10-07 02:26:03 +03:00
|
|
|
::
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
++ event-tape-to-wall
|
|
|
|
~% %eyre-tape-to-wall ..part ~
|
|
|
|
|= [event-id=@ud =tape]
|
2020-10-18 12:18:29 +03:00
|
|
|
^- wall
|
|
|
|
:~ (weld "id: " (format-ud-as-integer event-id))
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
(weld "data: " tape)
|
2020-10-18 12:18:29 +03:00
|
|
|
""
|
|
|
|
==
|
|
|
|
::
|
2019-10-07 02:26:03 +03:00
|
|
|
++ on-channel-heartbeat
|
|
|
|
|= channel-id=@t
|
|
|
|
^- [(list move) server-state]
|
|
|
|
::
|
|
|
|
=/ res
|
|
|
|
%- handle-response
|
|
|
|
:* %continue
|
2021-06-30 04:45:50 +03:00
|
|
|
data=(some (as-octs:mimes:html ':\0a'))
|
2019-10-07 02:26:03 +03:00
|
|
|
complete=%.n
|
|
|
|
==
|
|
|
|
=/ http-moves -.res
|
|
|
|
=/ new-state +.res
|
|
|
|
=/ heartbeat-time=@da (add now ~s20)
|
|
|
|
:_ %_ new-state
|
|
|
|
session.channel-state
|
|
|
|
%+ ~(jab by session.channel-state.state) channel-id
|
|
|
|
|= =channel
|
|
|
|
channel(heartbeat (some [heartbeat-time duct]))
|
|
|
|
==
|
|
|
|
(snoc http-moves (set-heartbeat-move channel-id heartbeat-time))
|
2020-06-04 18:12:35 +03:00
|
|
|
:: +discard-channel: remove a channel from state
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
2020-06-04 18:12:35 +03:00
|
|
|
:: cleans up state, timers, and gall subscriptions of the channel
|
|
|
|
::
|
|
|
|
++ discard-channel
|
|
|
|
|= [channel-id=@t expired=?]
|
2018-11-15 21:27:10 +03:00
|
|
|
^- [(list move) server-state]
|
|
|
|
::
|
2019-07-17 20:51:56 +03:00
|
|
|
=/ usession=(unit channel)
|
|
|
|
(~(get by session.channel-state.state) channel-id)
|
|
|
|
?~ usession
|
|
|
|
[~ state]
|
|
|
|
=/ session=channel u.usession
|
2018-11-15 21:27:10 +03:00
|
|
|
::
|
2018-11-16 02:27:49 +03:00
|
|
|
:_ %_ state
|
|
|
|
session.channel-state
|
2018-11-21 04:06:04 +03:00
|
|
|
(~(del by session.channel-state.state) channel-id)
|
2020-06-04 18:12:35 +03:00
|
|
|
::
|
|
|
|
duct-to-key.channel-state
|
|
|
|
?. ?=(%| -.state.session) duct-to-key.channel-state.state
|
|
|
|
(~(del by duct-to-key.channel-state.state) p.state.session)
|
2018-11-16 02:27:49 +03:00
|
|
|
==
|
2019-10-10 14:33:11 +03:00
|
|
|
=/ heartbeat-cancel=(list move)
|
|
|
|
?~ heartbeat.session ~
|
|
|
|
:~ %^ cancel-heartbeat-move
|
|
|
|
channel-id
|
|
|
|
date.u.heartbeat.session
|
|
|
|
duct.u.heartbeat.session
|
|
|
|
==
|
2020-06-04 18:12:35 +03:00
|
|
|
=/ expire-cancel=(list move)
|
|
|
|
?: expired ~
|
|
|
|
?. ?=(%& -.state.session) ~
|
|
|
|
=, p.state.session
|
|
|
|
[(cancel-timeout-move channel-id date duct)]~
|
2019-10-10 14:33:11 +03:00
|
|
|
%+ weld heartbeat-cancel
|
2020-06-04 18:12:35 +03:00
|
|
|
%+ weld expire-cancel
|
2018-11-15 21:27:10 +03:00
|
|
|
:: produce a list of moves which cancels every gall subscription
|
|
|
|
::
|
2019-03-27 01:52:32 +03:00
|
|
|
%+ turn ~(tap by subscriptions.session)
|
2020-10-19 01:48:18 +03:00
|
|
|
|= [request-id=@ud ship=@p app=term =path duc=^duct]
|
2018-11-16 02:27:49 +03:00
|
|
|
^- move
|
2023-02-09 22:22:50 +03:00
|
|
|
%- (trace 1 |.("{<channel-id>} leaving subscription to {<app>}"))
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
%+ deal-as
|
2020-10-19 01:48:18 +03:00
|
|
|
(subscription-wire channel-id request-id ship app)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
[identity.session ship app %leave ~]
|
2018-11-15 21:27:10 +03:00
|
|
|
--
|
2019-03-19 23:38:18 +03:00
|
|
|
:: +handle-gall-error: a call to +poke-http-response resulted in a %coup
|
|
|
|
::
|
|
|
|
++ handle-gall-error
|
|
|
|
|= =tang
|
|
|
|
^- [(list move) server-state]
|
|
|
|
::
|
2023-05-04 01:25:10 +03:00
|
|
|
?~ connection-state=(~(get by connections.state) duct)
|
|
|
|
%. `state
|
|
|
|
(trace 0 |.("{<duct>} error on invalid outstanding connection"))
|
|
|
|
=* connection u.connection-state
|
2019-11-13 12:38:18 +03:00
|
|
|
=/ moves-1=(list move)
|
2019-11-13 12:21:14 +03:00
|
|
|
?. ?=(%app -.action.connection)
|
|
|
|
~
|
|
|
|
:_ ~
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=, connection
|
|
|
|
%- (trace 1 |.("leaving subscription to {<app.action>}"))
|
|
|
|
(deal-as /watch-response/[eyre-id] identity our app.action %leave ~)
|
2019-03-19 23:38:18 +03:00
|
|
|
::
|
2019-11-13 12:21:14 +03:00
|
|
|
=^ moves-2 state
|
|
|
|
%^ return-static-data-on-duct 500 'text/html'
|
|
|
|
::
|
|
|
|
%- internal-server-error :*
|
|
|
|
authenticated.inbound-request.connection
|
|
|
|
url.request.inbound-request.connection
|
|
|
|
tang
|
|
|
|
==
|
2019-11-13 12:38:18 +03:00
|
|
|
[(weld moves-1 moves-2) state]
|
2018-10-10 21:51:52 +03:00
|
|
|
:: +handle-response: check a response for correctness and send to earth
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
2019-02-09 02:03:46 +03:00
|
|
|
:: All outbound responses including %http-server generated responses need to go
|
2019-01-12 01:15:17 +03:00
|
|
|
:: through this interface because we want to have one centralized place
|
|
|
|
:: where we perform logging and state cleanup for connections that we're
|
|
|
|
:: done with.
|
|
|
|
::
|
2018-09-24 21:48:19 +03:00
|
|
|
++ handle-response
|
2019-02-09 00:16:42 +03:00
|
|
|
|= =http-event:http
|
2018-09-24 21:48:19 +03:00
|
|
|
^- [(list move) server-state]
|
|
|
|
:: verify that this is a valid response on the duct
|
|
|
|
::
|
|
|
|
?~ connection-state=(~(get by connections.state) duct)
|
2023-02-09 22:56:50 +03:00
|
|
|
((trace 0 |.("{<duct>} invalid outstanding connection")) `state)
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
|
|
|
|^ ^- [(list move) server-state]
|
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
?- -.http-event
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
|
|
|
%start
|
2019-02-09 00:16:42 +03:00
|
|
|
?^ response-header.u.connection-state
|
2023-02-09 23:06:06 +03:00
|
|
|
((trace 0 |.("{<duct>} error multiple start")) error-connection)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:: extend the request's session's + cookie's life
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
2023-05-19 12:31:01 +03:00
|
|
|
=^ response-header sessions.auth.state
|
2020-05-30 03:29:20 +03:00
|
|
|
=, authentication
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=* session-id session-id.u.connection-state
|
2023-05-19 12:31:01 +03:00
|
|
|
=* sessions sessions.auth.state
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=* inbound inbound-request.u.connection-state
|
2020-05-30 03:29:20 +03:00
|
|
|
::
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
?. (~(has by sessions) session-id)
|
2020-05-30 03:29:20 +03:00
|
|
|
:: if the session has expired since the request was opened,
|
|
|
|
:: tough luck, we don't create/revive sessions here
|
|
|
|
::
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
[response-header.http-event sessions]
|
|
|
|
:_ %+ ~(jab by sessions) session-id
|
2020-06-04 23:06:13 +03:00
|
|
|
|= =session
|
|
|
|
session(expiry-time (add now session-timeout))
|
2020-05-30 03:29:20 +03:00
|
|
|
=- response-header.http-event(headers -)
|
|
|
|
%^ set-header:http 'set-cookie'
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
(session-cookie-string session-id &)
|
2020-05-30 03:29:20 +03:00
|
|
|
headers.response-header.http-event
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
2023-05-04 01:25:48 +03:00
|
|
|
=* connection u.connection-state
|
|
|
|
::
|
2020-09-30 16:07:27 +03:00
|
|
|
:: if the request was a simple cors request from an approved origin
|
|
|
|
:: append the necessary cors headers to the response
|
|
|
|
::
|
|
|
|
=/ origin=(unit origin)
|
|
|
|
%+ get-header:http 'origin'
|
|
|
|
header-list.request.inbound-request.connection
|
|
|
|
=? headers.response-header
|
|
|
|
?& ?=(^ origin)
|
|
|
|
(~(has in approved.cors-registry.state) u.origin)
|
|
|
|
==
|
|
|
|
%^ set-header:http 'Access-Control-Allow-Origin' u.origin
|
|
|
|
%^ set-header:http 'Access-Control-Allow-Credentials' 'true'
|
|
|
|
headers.response-header
|
|
|
|
::
|
2020-05-30 03:29:20 +03:00
|
|
|
=. response-header.http-event response-header
|
2018-09-24 21:48:19 +03:00
|
|
|
=. connections.state
|
2023-05-04 01:39:19 +03:00
|
|
|
?: complete.http-event
|
|
|
|
:: XX optimize by not requiring +put:by in +request
|
|
|
|
::
|
|
|
|
(~(del by connections.state) duct)
|
|
|
|
::
|
2023-02-09 20:55:08 +03:00
|
|
|
%- (trace 2 |.("{<duct>} start"))
|
2020-09-30 16:07:27 +03:00
|
|
|
%+ ~(put by connections.state) duct
|
2023-05-04 01:25:48 +03:00
|
|
|
%= connection
|
2020-05-30 03:29:20 +03:00
|
|
|
response-header `response-header
|
2019-02-09 00:16:42 +03:00
|
|
|
bytes-sent ?~(data.http-event 0 p.u.data.http-event)
|
2018-09-24 21:48:19 +03:00
|
|
|
==
|
|
|
|
::
|
|
|
|
pass-response
|
|
|
|
::
|
|
|
|
%continue
|
2019-02-09 00:16:42 +03:00
|
|
|
?~ response-header.u.connection-state
|
2023-02-09 01:03:02 +03:00
|
|
|
%. error-connection
|
2023-02-09 23:06:06 +03:00
|
|
|
(trace 0 |.("{<duct>} error continue without start"))
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
|
|
|
=. connections.state
|
2023-05-04 01:39:19 +03:00
|
|
|
?: complete.http-event
|
|
|
|
%- (trace 2 |.("{<duct>} completed"))
|
|
|
|
(~(del by connections.state) duct)
|
|
|
|
::
|
|
|
|
%- (trace 2 |.("{<duct>} continuing"))
|
|
|
|
?~ data.http-event
|
|
|
|
connections.state
|
|
|
|
::
|
|
|
|
%+ ~(put by connections.state) duct
|
|
|
|
=* size p.u.data.http-event
|
|
|
|
=* conn u.connection-state
|
|
|
|
conn(bytes-sent (add size bytes-sent.conn))
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
|
|
|
pass-response
|
|
|
|
::
|
|
|
|
%cancel
|
|
|
|
:: todo: log this differently from an ise.
|
|
|
|
::
|
2023-02-09 21:06:02 +03:00
|
|
|
((trace 1 |.("cancel http event")) error-connection)
|
2018-09-24 21:48:19 +03:00
|
|
|
==
|
|
|
|
::
|
|
|
|
++ pass-response
|
|
|
|
^- [(list move) server-state]
|
2019-02-09 00:16:42 +03:00
|
|
|
[[duct %give %response http-event]~ state]
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
|
|
|
++ error-connection
|
|
|
|
:: todo: log application error
|
|
|
|
::
|
|
|
|
:: remove all outstanding state for this connection
|
|
|
|
::
|
|
|
|
=. connections.state
|
|
|
|
(~(del by connections.state) duct)
|
|
|
|
:: respond to outside with %error
|
|
|
|
::
|
|
|
|
^- [(list move) server-state]
|
2019-11-13 12:21:14 +03:00
|
|
|
:_ state
|
|
|
|
:- [duct %give %response %cancel ~]
|
|
|
|
?. ?=(%app -.action.u.connection-state)
|
|
|
|
~
|
|
|
|
:_ ~
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=, u.connection-state
|
2023-02-09 22:22:50 +03:00
|
|
|
%- %+ trace 1
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
|.("leaving subscription to {<app.action>}")
|
|
|
|
(deal-as /watch-response/[eyre-id] identity our app.action %leave ~)
|
2018-09-24 21:48:19 +03:00
|
|
|
--
|
2023-03-25 07:18:25 +03:00
|
|
|
:: +set-response: remember (or update) a cache mapping
|
|
|
|
::
|
|
|
|
++ set-response
|
|
|
|
|= [url=@t entry=(unit cache-entry)]
|
|
|
|
^- [(list move) server-state]
|
|
|
|
=/ aeon ?^(prev=(~(get by cache.state) url) +(aeon.u.prev) 1)
|
|
|
|
=. cache.state (~(put by cache.state) url [aeon entry])
|
|
|
|
:_ state
|
|
|
|
[outgoing-duct.state %give %grow /cache/(scot %ud aeon)/(scot %t url)]~
|
2018-09-20 02:29:36 +03:00
|
|
|
:: +add-binding: conditionally add a pairing between binding and action
|
|
|
|
::
|
|
|
|
:: Adds =binding =action if there is no conflicting bindings.
|
|
|
|
::
|
|
|
|
++ add-binding
|
2023-03-03 02:00:27 +03:00
|
|
|
|= [=binding =action]
|
2018-09-20 02:29:36 +03:00
|
|
|
^- [(list move) server-state]
|
2020-06-03 02:40:32 +03:00
|
|
|
=^ success bindings.state
|
2020-10-06 17:50:49 +03:00
|
|
|
:: prevent binding in reserved namespaces
|
|
|
|
::
|
|
|
|
?: ?| ?=([%'~' *] path.binding) :: eyre
|
|
|
|
?=([%'~_~' *] path.binding) :: runtime
|
|
|
|
==
|
|
|
|
[| bindings.state]
|
2021-09-24 23:54:24 +03:00
|
|
|
[& (insert-binding [binding duct action] bindings.state)]
|
2020-06-03 02:40:32 +03:00
|
|
|
:_ state
|
2021-09-24 23:54:24 +03:00
|
|
|
[duct %give %bound & binding]~
|
2018-09-20 02:29:36 +03:00
|
|
|
:: +remove-binding: removes a binding if it exists and is owned by this duct
|
|
|
|
::
|
|
|
|
++ remove-binding
|
|
|
|
|= =binding
|
|
|
|
::
|
|
|
|
^- server-state
|
|
|
|
%_ state
|
|
|
|
bindings
|
|
|
|
%+ skip bindings.state
|
2023-03-03 02:00:27 +03:00
|
|
|
|= [item-binding=^binding item-duct=^duct =action]
|
2018-09-20 02:29:36 +03:00
|
|
|
^- ?
|
|
|
|
&(=(item-binding binding) =(item-duct duct))
|
|
|
|
==
|
|
|
|
:: +get-action-for-binding: finds an action for an incoming web request
|
|
|
|
::
|
|
|
|
++ get-action-for-binding
|
|
|
|
|= [raw-host=(unit @t) url=@t]
|
2023-03-03 02:00:27 +03:00
|
|
|
^- [=action suburl=@t]
|
2018-09-20 02:29:36 +03:00
|
|
|
:: process :raw-host
|
|
|
|
::
|
|
|
|
:: If we are missing a 'Host:' header, if that header is a raw IP
|
|
|
|
:: address, or if the 'Host:' header refers to [our].urbit.org, we want
|
2019-06-04 00:34:01 +03:00
|
|
|
:: to return ~ which means we're unidentified and will match against any
|
|
|
|
:: wildcard matching.
|
2018-09-20 02:29:36 +03:00
|
|
|
::
|
|
|
|
:: Otherwise, return the site given.
|
|
|
|
::
|
|
|
|
=/ host=(unit @t)
|
|
|
|
?~ raw-host
|
|
|
|
~
|
2018-10-03 21:36:45 +03:00
|
|
|
:: Parse the raw-host so that we can ignore ports, usernames, etc.
|
2018-09-20 02:29:36 +03:00
|
|
|
::
|
2018-10-04 00:05:36 +03:00
|
|
|
=+ parsed=(rush u.raw-host simplified-url-parser)
|
|
|
|
?~ parsed
|
2018-09-20 02:29:36 +03:00
|
|
|
~
|
2018-10-03 21:36:45 +03:00
|
|
|
:: if the url is a raw IP, assume default site.
|
|
|
|
::
|
2018-10-04 00:05:36 +03:00
|
|
|
?: ?=([%ip *] -.u.parsed)
|
|
|
|
~
|
|
|
|
:: if the url is "localhost", assume default site.
|
|
|
|
::
|
|
|
|
?: =([%site 'localhost'] -.u.parsed)
|
|
|
|
~
|
|
|
|
:: render our as a tape, and cut off the sig in front.
|
|
|
|
::
|
|
|
|
=/ with-sig=tape (scow %p our)
|
|
|
|
?> ?=(^ with-sig)
|
|
|
|
?: =(u.raw-host (crip t.with-sig))
|
|
|
|
:: [our].urbit.org is the default site
|
|
|
|
::
|
|
|
|
~
|
2018-09-20 02:29:36 +03:00
|
|
|
::
|
|
|
|
raw-host
|
|
|
|
:: url is the raw thing passed over the 'Request-Line'.
|
|
|
|
::
|
2018-09-27 02:18:40 +03:00
|
|
|
:: todo: this is really input validation, and we should return a 500 to
|
|
|
|
:: the client.
|
|
|
|
::
|
|
|
|
=/ request-line (parse-request-line url)
|
|
|
|
=/ parsed-url=(list @t) site.request-line
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
=? parsed-url ?=([%'~' %channel-jam *] parsed-url)
|
|
|
|
parsed-url(i.t %channel)
|
2018-09-20 02:29:36 +03:00
|
|
|
::
|
|
|
|
=/ bindings bindings.state
|
|
|
|
|-
|
|
|
|
::
|
|
|
|
?~ bindings
|
2020-06-11 02:42:21 +03:00
|
|
|
[[%four-oh-four ~] url]
|
|
|
|
::
|
|
|
|
?. (host-matches site.binding.i.bindings raw-host)
|
|
|
|
$(bindings t.bindings)
|
|
|
|
?~ suffix=(find-suffix path.binding.i.bindings parsed-url)
|
|
|
|
$(bindings t.bindings)
|
|
|
|
::
|
|
|
|
:- action.i.bindings
|
|
|
|
%^ cat 3
|
|
|
|
%+ roll
|
|
|
|
^- (list @t)
|
|
|
|
(join '/' (flop ['' u.suffix]))
|
|
|
|
(cury cat 3)
|
|
|
|
?~ ext.request-line ''
|
|
|
|
(cat 3 '.' u.ext.request-line)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:: +give-session-tokens: send valid local session tokens to unix
|
2022-08-24 01:34:08 +03:00
|
|
|
::
|
|
|
|
++ give-session-tokens
|
|
|
|
^- move
|
|
|
|
:- outgoing-duct.state
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:+ %give %sessions
|
|
|
|
%- sy
|
2023-05-19 12:31:01 +03:00
|
|
|
%+ murn ~(tap by sessions.auth.state)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
|= [sid=@uv session]
|
|
|
|
?. ?=(%ours -.identity) ~
|
|
|
|
(some (scot %uv sid))
|
|
|
|
:: +new-session-key
|
|
|
|
::
|
|
|
|
++ new-session-key
|
|
|
|
|- ^- @uv
|
|
|
|
=/ candidate=@uv (~(raw og (shas %session-key eny)) 128)
|
2023-05-19 12:31:01 +03:00
|
|
|
?. (~(has by sessions.auth.state) candidate)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
candidate
|
|
|
|
$(eny (shas %try-again candidate))
|
|
|
|
::
|
|
|
|
++ deal-as
|
|
|
|
|= [=wire identity=$@(@p identity) =ship =dude:gall =task:agent:gall]
|
|
|
|
^- move
|
|
|
|
=/ from=@p
|
|
|
|
?@ identity identity
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
?+(-.identity who.identity %ours our)
|
2023-06-07 11:38:05 +03:00
|
|
|
[duct %pass wire %g %deal [from ship /eyre] dude task]
|
2023-02-08 22:43:13 +03:00
|
|
|
::
|
|
|
|
++ trace
|
|
|
|
|= [pri=@ print=(trap tape)]
|
2023-02-08 23:19:14 +03:00
|
|
|
?: (lth verb.state pri) same
|
2023-02-08 22:43:13 +03:00
|
|
|
(slog leaf+"eyre: {(print)}" ~)
|
2018-09-20 02:29:36 +03:00
|
|
|
--
|
2019-06-04 00:34:01 +03:00
|
|
|
::
|
2020-10-29 16:24:24 +03:00
|
|
|
++ forwarded-params
|
2020-05-31 18:43:35 +03:00
|
|
|
|= =header-list:http
|
2020-10-29 16:24:24 +03:00
|
|
|
^- (unit (list (map @t @t)))
|
|
|
|
%+ biff
|
2020-05-31 18:43:35 +03:00
|
|
|
(get-header:http 'forwarded' header-list)
|
2020-10-29 16:24:24 +03:00
|
|
|
unpack-header:http
|
|
|
|
::
|
|
|
|
++ forwarded-for
|
|
|
|
|= forwards=(list (map @t @t))
|
|
|
|
^- (unit address)
|
|
|
|
?. ?=(^ forwards) ~
|
|
|
|
=* forward i.forwards
|
|
|
|
?~ for=(~(get by forward) 'for') ~
|
|
|
|
::NOTE per rfc7239, non-ip values are also valid. they're not useful
|
|
|
|
:: for the general case, so we ignore them here. if needed,
|
|
|
|
:: request handlers are free to inspect the headers themselves.
|
2020-05-31 18:43:35 +03:00
|
|
|
::
|
2020-10-29 16:24:24 +03:00
|
|
|
%+ rush u.for
|
|
|
|
;~ sfix
|
2020-11-15 08:08:52 +03:00
|
|
|
;~(pose (stag %ipv4 ip4) (stag %ipv6 (ifix [sel ser] ip6)))
|
2020-10-29 16:24:24 +03:00
|
|
|
;~(pose ;~(pfix col dim:ag) (easy ~))
|
|
|
|
==
|
|
|
|
::
|
|
|
|
++ forwarded-secure
|
|
|
|
|= forwards=(list (map @t @t))
|
|
|
|
^- (unit ?)
|
|
|
|
?. ?=(^ forwards) ~
|
|
|
|
=* forward i.forwards
|
|
|
|
?~ proto=(~(get by forward) 'proto') ~
|
|
|
|
?+ u.proto ~
|
|
|
|
%http `|
|
|
|
|
%https `&
|
|
|
|
==
|
2019-06-04 00:34:01 +03:00
|
|
|
::
|
|
|
|
++ parse-request-line
|
|
|
|
|= url=@t
|
|
|
|
^- [[ext=(unit @ta) site=(list @t)] args=(list [key=@t value=@t])]
|
|
|
|
(fall (rush url ;~(plug apat:de-purl:html yque:de-purl:html)) [[~ ~] ~])
|
2021-09-24 23:54:24 +03:00
|
|
|
:: +insert-binding: add a new binding, replacing any existing at its path
|
2020-06-03 02:40:32 +03:00
|
|
|
::
|
|
|
|
++ insert-binding
|
2023-03-03 02:00:27 +03:00
|
|
|
|= $: new=[=binding =duct =action]
|
|
|
|
bindings=(list [=binding =duct =action])
|
2021-09-24 23:54:24 +03:00
|
|
|
==
|
|
|
|
^+ bindings
|
|
|
|
?~ bindings [new]~
|
|
|
|
=* bid binding.i.bindings
|
|
|
|
:: replace already bound paths
|
2020-06-03 02:40:32 +03:00
|
|
|
::
|
2021-09-24 23:54:24 +03:00
|
|
|
?: =([site path]:bid [site path]:binding.new)
|
|
|
|
~> %slog.[0 leaf+"eyre: replacing existing binding at {<`path`path.bid>}"]
|
|
|
|
[new t.bindings]
|
|
|
|
:: if new comes before bid, prepend it.
|
|
|
|
:: otherwise, continue our search.
|
2020-06-03 02:40:32 +03:00
|
|
|
::
|
2021-09-24 23:54:24 +03:00
|
|
|
=; new-before-bid=?
|
|
|
|
?: new-before-bid [new bindings]
|
|
|
|
[i.bindings $(bindings t.bindings)]
|
|
|
|
?: =(site.binding.new site.bid)
|
2021-09-25 16:44:31 +03:00
|
|
|
(aor path.bid path.binding.new)
|
|
|
|
(aor (fall site.bid '') (fall site.binding.new ''))
|
2020-08-27 14:47:18 +03:00
|
|
|
::
|
|
|
|
++ channel-wire
|
|
|
|
|= [channel-id=@t request-id=@ud]
|
|
|
|
^- wire
|
|
|
|
/channel/subscription/[channel-id]/(scot %ud request-id)
|
|
|
|
::
|
|
|
|
++ subscription-wire
|
|
|
|
|= [channel-id=@t request-id=@ud =ship app=term]
|
|
|
|
^- wire
|
|
|
|
(weld (channel-wire channel-id request-id) /(scot %p ship)/[app])
|
2018-09-20 02:29:36 +03:00
|
|
|
--
|
|
|
|
:: end the =~
|
|
|
|
::
|
|
|
|
. ==
|
|
|
|
:: begin with a default +axle as a blank slate
|
|
|
|
::
|
|
|
|
=| ax=axle
|
|
|
|
:: a vane is activated with current date, entropy, and a namespace function
|
|
|
|
::
|
2020-12-06 11:38:37 +03:00
|
|
|
|= [now=@da eny=@uvJ rof=roof]
|
2018-09-20 02:29:36 +03:00
|
|
|
:: allow jets to be registered within this core
|
|
|
|
::
|
2020-12-05 07:32:17 +03:00
|
|
|
~% %http-server ..part ~
|
2018-09-20 02:29:36 +03:00
|
|
|
|%
|
|
|
|
++ call
|
2021-03-28 10:47:37 +03:00
|
|
|
~/ %eyre-call
|
2020-12-08 03:47:06 +03:00
|
|
|
|= [=duct dud=(unit goof) wrapped-task=(hobo task)]
|
2019-02-09 02:03:46 +03:00
|
|
|
^- [(list move) _http-server-gate]
|
2018-09-20 02:29:36 +03:00
|
|
|
::
|
2020-12-08 03:47:06 +03:00
|
|
|
=/ task=task ((harden task) wrapped-task)
|
2020-02-24 22:09:37 +03:00
|
|
|
::
|
2023-05-04 18:33:37 +03:00
|
|
|
:: XX handle more error notifications
|
2020-02-24 22:09:37 +03:00
|
|
|
::
|
2020-12-08 05:01:48 +03:00
|
|
|
?^ dud
|
2023-05-04 18:33:37 +03:00
|
|
|
:_ http-server-gate
|
|
|
|
:: always print the error trace
|
|
|
|
::
|
|
|
|
:- [duct %slip %d %flog %crud [-.task tang.u.dud]]
|
|
|
|
^- (list move)
|
|
|
|
:: if a request caused the crash, respond with a 500
|
|
|
|
::
|
|
|
|
?. ?=(?(%request %request-local) -.task) ~
|
|
|
|
^~
|
|
|
|
=/ data (as-octs:mimes:html 'crud!')
|
|
|
|
=/ head
|
|
|
|
:~ ['content-type' 'text/html']
|
|
|
|
['content-length' (crip (a-co:co p.data))]
|
|
|
|
==
|
|
|
|
[duct %give %response %start 500^head `data &]~
|
2019-02-09 00:16:42 +03:00
|
|
|
:: %init: tells us what our ship name is
|
2018-09-20 02:29:36 +03:00
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
?: ?=(%init -.task)
|
2018-09-27 02:18:40 +03:00
|
|
|
:: initial value for the login handler
|
|
|
|
::
|
|
|
|
=. bindings.server-state.ax
|
2021-09-25 16:44:31 +03:00
|
|
|
=- (roll - insert-binding)
|
2023-03-03 02:00:27 +03:00
|
|
|
^- (list [binding ^duct action])
|
2018-11-15 21:27:10 +03:00
|
|
|
:~ [[~ /~/login] duct [%authentication ~]]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
[[~ /~/eauth] duct [%eauth ~]]
|
2020-06-03 02:40:32 +03:00
|
|
|
[[~ /~/logout] duct [%logout ~]]
|
2018-11-15 21:27:10 +03:00
|
|
|
[[~ /~/channel] duct [%channel ~]]
|
2020-06-11 02:45:05 +03:00
|
|
|
[[~ /~/scry] duct [%scry ~]]
|
2022-08-01 01:50:36 +03:00
|
|
|
[[~ /~/name] duct [%name ~]]
|
2023-05-06 00:38:40 +03:00
|
|
|
[[~ /~/host] duct [%host ~]]
|
2018-09-27 02:18:40 +03:00
|
|
|
==
|
2019-02-09 02:03:46 +03:00
|
|
|
[~ http-server-gate]
|
2019-09-27 23:00:37 +03:00
|
|
|
:: %trim: in response to memory pressure
|
|
|
|
::
|
2019-10-01 21:34:22 +03:00
|
|
|
:: Cancel all inactive channels
|
|
|
|
:: XX cancel active too if =(0 trim-priority) ?
|
|
|
|
::
|
2019-09-27 23:00:37 +03:00
|
|
|
?: ?=(%trim -.task)
|
2022-07-09 03:10:41 +03:00
|
|
|
=* event-args [[eny duct now rof] server-state.ax]
|
2019-10-01 21:34:22 +03:00
|
|
|
=* by-channel by-channel:(per-server-event event-args)
|
|
|
|
=* channel-state channel-state.server-state.ax
|
|
|
|
::
|
|
|
|
=/ inactive=(list @t)
|
|
|
|
=/ full=(set @t) ~(key by session.channel-state)
|
|
|
|
=/ live=(set @t)
|
|
|
|
(~(gas in *(set @t)) ~(val by duct-to-key.channel-state))
|
|
|
|
~(tap in (~(dif in full) live))
|
|
|
|
::
|
|
|
|
?: =(~ inactive)
|
|
|
|
[~ http-server-gate]
|
|
|
|
::
|
|
|
|
=/ len=tape (scow %ud (lent inactive))
|
|
|
|
~> %slog.[0 leaf+"eyre: trim: closing {len} inactive channels"]
|
|
|
|
::
|
|
|
|
=| moves=(list (list move))
|
|
|
|
|- ^- [(list move) _http-server-gate]
|
|
|
|
=* channel-id i.inactive
|
|
|
|
?~ inactive
|
|
|
|
[(zing (flop moves)) http-server-gate]
|
|
|
|
:: discard channel state, and cancel any active gall subscriptions
|
|
|
|
::
|
2020-06-04 18:12:35 +03:00
|
|
|
=^ mov server-state.ax (discard-channel:by-channel channel-id |)
|
2019-10-01 21:34:22 +03:00
|
|
|
$(moves [mov moves], inactive t.inactive)
|
|
|
|
::
|
2019-03-13 23:35:14 +03:00
|
|
|
:: %vega: notifies us of a completed kernel upgrade
|
2019-02-12 01:41:50 +03:00
|
|
|
::
|
|
|
|
?: ?=(%vega -.task)
|
|
|
|
[~ http-server-gate]
|
2019-02-09 00:16:42 +03:00
|
|
|
:: %born: new unix process
|
2019-03-13 23:35:14 +03:00
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
?: ?=(%born -.task)
|
2018-10-24 21:25:55 +03:00
|
|
|
:: close previously open connections
|
2018-09-28 21:24:41 +03:00
|
|
|
::
|
2018-10-24 21:25:55 +03:00
|
|
|
:: When we have a new unix process, every outstanding open connection is
|
|
|
|
:: dead. For every duct, send an implicit close connection.
|
|
|
|
::
|
|
|
|
=^ closed-connections=(list move) server-state.ax
|
|
|
|
=/ connections=(list [=^duct *])
|
|
|
|
~(tap by connections.server-state.ax)
|
|
|
|
::
|
|
|
|
=| closed-connections=(list move)
|
|
|
|
|-
|
|
|
|
?~ connections
|
|
|
|
[closed-connections server-state.ax]
|
|
|
|
::
|
|
|
|
=/ event-args
|
2020-12-06 13:55:19 +03:00
|
|
|
[[eny duct.i.connections now rof] server-state.ax]
|
2018-10-24 21:25:55 +03:00
|
|
|
=/ cancel-request cancel-request:(per-server-event event-args)
|
|
|
|
=^ moves server-state.ax cancel-request
|
|
|
|
::
|
|
|
|
$(closed-connections (weld moves closed-connections), connections t.connections)
|
2019-04-10 00:03:21 +03:00
|
|
|
:: save duct for future %give to unix
|
|
|
|
::
|
|
|
|
=. outgoing-duct.server-state.ax duct
|
2023-03-25 07:18:25 +03:00
|
|
|
:: send all cache mappings to runtime
|
|
|
|
::
|
|
|
|
=/ cache-moves=(list move)
|
|
|
|
%+ turn ~(tap by cache.server-state.ax)
|
|
|
|
|= [url=@t cache-val=[aeon=@ud val=(unit cache-entry)]]
|
|
|
|
[duct %give %grow /cache/(scot %u aeon.cache-val)/(scot %t url)]
|
2018-10-24 21:25:55 +03:00
|
|
|
::
|
2019-02-09 02:03:46 +03:00
|
|
|
:_ http-server-gate
|
2022-08-24 01:34:08 +03:00
|
|
|
:* :: hand back default configuration for now
|
|
|
|
::
|
|
|
|
[duct %give %set-config http-config.server-state.ax]
|
|
|
|
:: provide a list of valid auth tokens
|
|
|
|
::
|
|
|
|
=< give-session-tokens
|
|
|
|
(per-server-event [eny duct now rof] server-state.ax)
|
2018-10-24 21:25:55 +03:00
|
|
|
::
|
2023-03-25 07:18:25 +03:00
|
|
|
(zing ~[closed-connections cache-moves])
|
2018-10-24 21:25:55 +03:00
|
|
|
==
|
2020-07-29 19:14:18 +03:00
|
|
|
::
|
|
|
|
?: ?=(%code-changed -.task)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
~> %slog.[0 leaf+"eyre: code-changed: throwing away local sessions"]
|
|
|
|
=* event-args [[eny duct now rof] server-state.ax]
|
|
|
|
:: find all the %ours sessions, we must close them
|
2020-07-29 19:14:18 +03:00
|
|
|
::
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
=/ siz=(list @uv)
|
2023-05-19 12:31:01 +03:00
|
|
|
%+ murn ~(tap by sessions.auth.server-state.ax)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
|= [sid=@uv session]
|
|
|
|
?:(?=(%ours -.identity) (some sid) ~)
|
2020-07-29 19:14:18 +03:00
|
|
|
=| moves=(list (list move))
|
|
|
|
|- ^- [(list move) _http-server-gate]
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
?~ siz
|
2020-07-29 19:14:18 +03:00
|
|
|
[(zing (flop moves)) http-server-gate]
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
:: discard the session, clean up its channels
|
2020-07-29 19:14:18 +03:00
|
|
|
::
|
2023-05-19 12:31:01 +03:00
|
|
|
=^ mov server-state.ax
|
|
|
|
(close-session:authentication:(per-server-event event-args) i.siz |)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
$(moves [mov moves], siz t.siz)
|
2020-07-29 19:14:18 +03:00
|
|
|
::
|
2023-05-22 22:08:11 +03:00
|
|
|
?: ?=(%eauth-host -.task)
|
|
|
|
=. user.endpoint.auth.server-state.ax host.task
|
2023-06-09 16:46:04 +03:00
|
|
|
=. time.endpoint.auth.server-state.ax now
|
2023-05-22 22:08:11 +03:00
|
|
|
[~ http-server-gate]
|
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
:: all other commands operate on a per-server-event
|
2018-09-28 21:24:41 +03:00
|
|
|
::
|
2020-12-06 13:55:19 +03:00
|
|
|
=/ event-args [[eny duct now rof] server-state.ax]
|
2019-02-09 00:16:42 +03:00
|
|
|
=/ server (per-server-event event-args)
|
2018-10-26 02:32:54 +03:00
|
|
|
::
|
2019-03-21 08:28:32 +03:00
|
|
|
?- -.task
|
|
|
|
:: %live: notifies us of the ports of our live http servers
|
2018-10-26 02:32:54 +03:00
|
|
|
::
|
2019-02-09 00:16:42 +03:00
|
|
|
%live
|
2019-03-21 08:28:32 +03:00
|
|
|
=. ports.server-state.ax +.task
|
2022-09-03 17:58:09 +03:00
|
|
|
:: enable http redirects if https port live and cert set
|
|
|
|
::
|
|
|
|
=. redirect.http-config.server-state.ax
|
|
|
|
&(?=(^ secure.task) ?=(^ secure.http-config.server-state.ax))
|
2019-02-09 02:03:46 +03:00
|
|
|
[~ http-server-gate]
|
2019-03-21 08:28:32 +03:00
|
|
|
:: %rule: updates our http configuration
|
|
|
|
::
|
|
|
|
%rule
|
|
|
|
?- -.http-rule.task
|
|
|
|
:: %cert: install tls certificate
|
|
|
|
::
|
|
|
|
%cert
|
|
|
|
=* config http-config.server-state.ax
|
|
|
|
?: =(secure.config cert.http-rule.task)
|
|
|
|
[~ http-server-gate]
|
|
|
|
=. secure.config cert.http-rule.task
|
2022-09-03 17:58:09 +03:00
|
|
|
=. redirect.config
|
2022-09-29 03:32:32 +03:00
|
|
|
?& ?=(^ secure.ports.server-state.ax)
|
|
|
|
?=(^ cert.http-rule.task)
|
|
|
|
==
|
2019-03-21 08:28:32 +03:00
|
|
|
:_ http-server-gate
|
2019-04-10 00:03:21 +03:00
|
|
|
=* out-duct outgoing-duct.server-state.ax
|
|
|
|
?~ out-duct ~
|
|
|
|
[out-duct %give %set-config config]~
|
2019-03-21 08:28:32 +03:00
|
|
|
:: %turf: add or remove domain name
|
|
|
|
::
|
|
|
|
%turf
|
|
|
|
=* domains domains.server-state.ax
|
2020-11-25 23:22:55 +03:00
|
|
|
=/ mod=(set turf)
|
2019-03-21 08:28:32 +03:00
|
|
|
?: ?=(%put action.http-rule.task)
|
|
|
|
(~(put in domains) turf.http-rule.task)
|
|
|
|
(~(del in domains) turf.http-rule.task)
|
|
|
|
?: =(domains mod)
|
|
|
|
[~ http-server-gate]
|
|
|
|
=. domains mod
|
|
|
|
:_ http-server-gate
|
|
|
|
=/ cmd
|
|
|
|
[%acme %poke `cage`[%acme-order !>(mod)]]
|
2023-05-22 16:12:09 +03:00
|
|
|
[duct %pass /acme/order %g %deal [our our /eyre] cmd]~
|
2019-03-21 08:28:32 +03:00
|
|
|
==
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
::
|
|
|
|
%plea
|
|
|
|
~| path.plea.task
|
|
|
|
?> ?=([%eauth %'0' ~] path.plea.task)
|
|
|
|
=+ plea=;;(eauth-plea payload.plea.task)
|
|
|
|
=^ moves server-state.ax
|
2023-06-09 16:46:04 +03:00
|
|
|
(on-plea:server:eauth:authentication:server ship.task plea)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
[moves http-server-gate]
|
2019-02-09 00:16:42 +03:00
|
|
|
::
|
2019-11-14 06:38:13 +03:00
|
|
|
%request
|
2019-02-09 00:16:42 +03:00
|
|
|
=^ moves server-state.ax (request:server +.task)
|
2019-02-09 02:03:46 +03:00
|
|
|
[moves http-server-gate]
|
2019-04-30 23:38:40 +03:00
|
|
|
::
|
|
|
|
%request-local
|
|
|
|
=^ moves server-state.ax (request-local:server +.task)
|
|
|
|
[moves http-server-gate]
|
2019-02-09 00:16:42 +03:00
|
|
|
::
|
|
|
|
%cancel-request
|
|
|
|
=^ moves server-state.ax cancel-request:server
|
2019-02-09 02:03:46 +03:00
|
|
|
[moves http-server-gate]
|
2019-02-09 00:16:42 +03:00
|
|
|
::
|
|
|
|
%connect
|
|
|
|
=^ moves server-state.ax
|
|
|
|
%+ add-binding:server binding.task
|
|
|
|
[%app app.task]
|
2019-02-09 02:03:46 +03:00
|
|
|
[moves http-server-gate]
|
2019-02-09 00:16:42 +03:00
|
|
|
::
|
|
|
|
%serve
|
|
|
|
=^ moves server-state.ax
|
|
|
|
%+ add-binding:server binding.task
|
|
|
|
[%gen generator.task]
|
2019-02-09 02:03:46 +03:00
|
|
|
[moves http-server-gate]
|
2019-02-09 00:16:42 +03:00
|
|
|
::
|
|
|
|
%disconnect
|
|
|
|
=. server-state.ax (remove-binding:server binding.task)
|
2019-02-09 02:03:46 +03:00
|
|
|
[~ http-server-gate]
|
2020-09-30 16:07:27 +03:00
|
|
|
::
|
|
|
|
%approve-origin
|
|
|
|
=. cors-registry.server-state.ax
|
|
|
|
=, cors-registry.server-state.ax
|
|
|
|
:+ (~(del in requests) origin.task)
|
|
|
|
(~(put in approved) origin.task)
|
|
|
|
(~(del in rejected) origin.task)
|
|
|
|
[~ http-server-gate]
|
|
|
|
::
|
|
|
|
%reject-origin
|
|
|
|
=. cors-registry.server-state.ax
|
|
|
|
=, cors-registry.server-state.ax
|
|
|
|
:+ (~(del in requests) origin.task)
|
|
|
|
(~(del in approved) origin.task)
|
|
|
|
(~(put in rejected) origin.task)
|
|
|
|
[~ http-server-gate]
|
2023-02-08 23:20:07 +03:00
|
|
|
::
|
|
|
|
%spew
|
|
|
|
=. verb.server-state.ax veb.task
|
|
|
|
`http-server-gate
|
2023-03-25 07:18:25 +03:00
|
|
|
::
|
|
|
|
%set-response
|
|
|
|
=^ moves server-state.ax (set-response:server +.task)
|
|
|
|
[moves http-server-gate]
|
2018-09-20 02:29:36 +03:00
|
|
|
==
|
|
|
|
::
|
2018-09-24 21:48:19 +03:00
|
|
|
++ take
|
2021-03-28 10:47:37 +03:00
|
|
|
~/ %eyre-take
|
2020-12-06 11:38:37 +03:00
|
|
|
|= [=wire =duct dud=(unit goof) =sign]
|
2019-02-09 02:03:46 +03:00
|
|
|
^- [(list move) _http-server-gate]
|
2019-11-05 10:42:59 +03:00
|
|
|
=> %= .
|
|
|
|
sign
|
2020-12-08 03:22:26 +03:00
|
|
|
?: ?=(%gall -.sign)
|
2019-11-05 10:42:59 +03:00
|
|
|
?> ?=(%unto +<.sign)
|
|
|
|
sign
|
|
|
|
sign
|
|
|
|
==
|
2018-09-24 21:48:19 +03:00
|
|
|
:: :wire must at least contain two parts, the type and the build
|
|
|
|
::
|
2018-10-11 01:26:51 +03:00
|
|
|
?> ?=([@ *] wire)
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
2019-02-09 02:03:46 +03:00
|
|
|
|^ ^- [(list move) _http-server-gate]
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
2023-05-23 23:29:08 +03:00
|
|
|
?: ?=(%eauth i.wire)
|
|
|
|
eauth
|
|
|
|
?^ dud
|
|
|
|
~|(%eyre-take-dud (mean tang.u.dud))
|
2021-05-26 20:22:54 +03:00
|
|
|
?+ i.wire
|
|
|
|
~|([%bad-take-wire wire] !!)
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
2021-05-26 20:22:54 +03:00
|
|
|
%run-app-request run-app-request
|
|
|
|
%watch-response watch-response
|
|
|
|
%sessions sessions
|
|
|
|
%channel channel
|
|
|
|
%acme acme-ack
|
|
|
|
%conversion-cache `http-server-gate
|
2018-10-10 21:51:52 +03:00
|
|
|
==
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
2019-07-26 00:12:44 +03:00
|
|
|
++ run-app-request
|
2018-10-03 21:36:45 +03:00
|
|
|
::
|
2020-12-08 03:22:26 +03:00
|
|
|
?> ?=([%gall %unto *] sign)
|
2019-03-19 23:38:18 +03:00
|
|
|
::
|
|
|
|
::
|
2019-11-09 10:31:11 +03:00
|
|
|
?> ?=([%poke-ack *] p.sign)
|
2019-11-13 12:21:14 +03:00
|
|
|
?> ?=([@ *] t.wire)
|
2019-11-09 10:31:11 +03:00
|
|
|
?~ p.p.sign
|
|
|
|
:: received a positive acknowledgment: take no action
|
|
|
|
::
|
|
|
|
[~ http-server-gate]
|
|
|
|
:: we have an error; propagate it to the client
|
|
|
|
::
|
2020-12-06 13:55:19 +03:00
|
|
|
=/ event-args [[eny duct now rof] server-state.ax]
|
2019-11-09 10:31:11 +03:00
|
|
|
=/ handle-gall-error
|
|
|
|
handle-gall-error:(per-server-event event-args)
|
|
|
|
=^ moves server-state.ax
|
|
|
|
(handle-gall-error u.p.p.sign)
|
|
|
|
[moves http-server-gate]
|
|
|
|
::
|
|
|
|
++ watch-response
|
|
|
|
::
|
2020-12-06 13:55:19 +03:00
|
|
|
=/ event-args [[eny duct now rof] server-state.ax]
|
2019-11-09 10:31:11 +03:00
|
|
|
::
|
2019-11-13 12:21:14 +03:00
|
|
|
?> ?=([@ *] t.wire)
|
2020-12-08 03:22:26 +03:00
|
|
|
?: ?=([%gall %unto %watch-ack *] sign)
|
2019-03-19 23:38:18 +03:00
|
|
|
?~ p.p.sign
|
|
|
|
:: received a positive acknowledgment: take no action
|
|
|
|
::
|
|
|
|
[~ http-server-gate]
|
|
|
|
:: we have an error; propagate it to the client
|
2018-10-03 21:36:45 +03:00
|
|
|
::
|
2019-03-19 23:38:18 +03:00
|
|
|
=/ handle-gall-error
|
|
|
|
handle-gall-error:(per-server-event event-args)
|
|
|
|
=^ moves server-state.ax (handle-gall-error u.p.p.sign)
|
|
|
|
[moves http-server-gate]
|
|
|
|
::
|
2020-12-08 03:22:26 +03:00
|
|
|
?: ?=([%gall %unto %kick ~] sign)
|
2019-11-09 10:31:11 +03:00
|
|
|
=/ handle-response handle-response:(per-server-event event-args)
|
|
|
|
=^ moves server-state.ax
|
|
|
|
(handle-response %continue ~ &)
|
|
|
|
[moves http-server-gate]
|
2018-09-24 21:48:19 +03:00
|
|
|
::
|
2020-12-08 03:22:26 +03:00
|
|
|
?> ?=([%gall %unto %fact *] sign)
|
2019-11-09 10:31:11 +03:00
|
|
|
=/ =mark p.cage.p.sign
|
|
|
|
=/ =vase q.cage.p.sign
|
|
|
|
?. ?= ?(%http-response-header %http-response-data %http-response-cancel)
|
|
|
|
mark
|
|
|
|
=/ handle-gall-error
|
|
|
|
handle-gall-error:(per-server-event event-args)
|
|
|
|
=^ moves server-state.ax
|
2020-11-04 03:02:11 +03:00
|
|
|
(handle-gall-error leaf+"eyre bad mark {(trip mark)}" ~)
|
2019-11-09 10:31:11 +03:00
|
|
|
[moves http-server-gate]
|
|
|
|
::
|
|
|
|
=/ =http-event:http
|
|
|
|
?- mark
|
|
|
|
%http-response-header [%start !<(response-header:http vase) ~ |]
|
|
|
|
%http-response-data [%continue !<((unit octs) vase) |]
|
|
|
|
%http-response-cancel [%cancel ~]
|
|
|
|
==
|
2018-09-24 21:48:19 +03:00
|
|
|
=/ handle-response handle-response:(per-server-event event-args)
|
2019-11-09 10:31:11 +03:00
|
|
|
=^ moves server-state.ax
|
|
|
|
(handle-response http-event)
|
2019-02-09 02:03:46 +03:00
|
|
|
[moves http-server-gate]
|
2018-10-10 21:51:52 +03:00
|
|
|
::
|
2018-11-20 01:59:58 +03:00
|
|
|
++ channel
|
|
|
|
::
|
2020-12-06 13:55:19 +03:00
|
|
|
=/ event-args [[eny duct now rof] server-state.ax]
|
2018-11-20 01:59:58 +03:00
|
|
|
:: channel callback wires are triples.
|
|
|
|
::
|
|
|
|
?> ?=([@ @ @t *] wire)
|
|
|
|
::
|
|
|
|
?+ i.t.wire
|
|
|
|
~|([%bad-channel-wire wire] !!)
|
|
|
|
::
|
|
|
|
%timeout
|
2020-12-08 03:22:26 +03:00
|
|
|
?> ?=([%behn %wake *] sign)
|
2019-06-28 02:33:16 +03:00
|
|
|
?^ error.sign
|
|
|
|
[[duct %slip %d %flog %crud %wake u.error.sign]~ http-server-gate]
|
2023-02-16 18:02:34 +03:00
|
|
|
=* id i.t.t.wire
|
|
|
|
%- %+ trace:(per-server-event event-args) 1
|
|
|
|
|.("{(trip id)} cancelling channel due to timeout")
|
2018-11-20 01:59:58 +03:00
|
|
|
=^ moves server-state.ax
|
2023-02-09 22:11:35 +03:00
|
|
|
(discard-channel:by-channel:(per-server-event event-args) id &)
|
2019-02-09 02:03:46 +03:00
|
|
|
[moves http-server-gate]
|
2019-10-07 02:26:03 +03:00
|
|
|
::
|
|
|
|
%heartbeat
|
|
|
|
=/ on-channel-heartbeat
|
|
|
|
on-channel-heartbeat:by-channel:(per-server-event event-args)
|
|
|
|
=^ moves server-state.ax
|
|
|
|
(on-channel-heartbeat i.t.t.wire)
|
|
|
|
[moves http-server-gate]
|
2018-11-20 01:59:58 +03:00
|
|
|
::
|
2018-11-21 04:06:04 +03:00
|
|
|
?(%poke %subscription)
|
2020-12-08 03:22:26 +03:00
|
|
|
?> ?=([%gall %unto *] sign)
|
2021-06-19 05:13:55 +03:00
|
|
|
~| eyre-sub=wire
|
2018-11-21 04:06:04 +03:00
|
|
|
?> ?=([@ @ @t @ *] wire)
|
2021-06-19 05:13:55 +03:00
|
|
|
?< ?=(%raw-fact -.p.sign)
|
2020-08-27 14:47:18 +03:00
|
|
|
=* channel-id i.t.t.wire
|
|
|
|
=* request-id i.t.t.t.wire
|
|
|
|
=* extra-wire t.t.t.t.wire
|
2018-11-21 04:06:04 +03:00
|
|
|
=/ on-gall-response
|
|
|
|
on-gall-response:by-channel:(per-server-event event-args)
|
2019-01-11 03:35:09 +03:00
|
|
|
:: ~& [%gall-response sign]
|
2018-11-21 04:06:04 +03:00
|
|
|
=^ moves server-state.ax
|
2020-08-27 14:47:18 +03:00
|
|
|
%- on-gall-response
|
|
|
|
[channel-id (slav %ud request-id) extra-wire p.sign]
|
2019-02-09 02:03:46 +03:00
|
|
|
[moves http-server-gate]
|
2018-11-20 01:59:58 +03:00
|
|
|
==
|
2019-04-08 23:17:19 +03:00
|
|
|
::
|
2020-05-29 16:28:13 +03:00
|
|
|
++ sessions
|
|
|
|
::
|
2020-12-08 03:22:26 +03:00
|
|
|
?> ?=([%behn %wake *] sign)
|
2020-05-29 16:28:13 +03:00
|
|
|
::
|
|
|
|
?^ error.sign
|
|
|
|
[[duct %slip %d %flog %crud %wake u.error.sign]~ http-server-gate]
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
::NOTE we are not concerned with expiring channels that are still in
|
|
|
|
:: use. we require acks for messages, which bump their session's
|
|
|
|
:: timer. channels have their own expiry timer, too.
|
2020-05-29 16:28:13 +03:00
|
|
|
:: remove cookies that have expired
|
|
|
|
::
|
2023-05-19 12:31:01 +03:00
|
|
|
=* sessions sessions.auth.server-state.ax
|
|
|
|
=. sessions.auth.server-state.ax
|
2020-05-29 16:28:13 +03:00
|
|
|
%- ~(gas by *(map @uv session))
|
2020-06-04 23:06:13 +03:00
|
|
|
%+ skip ~(tap in sessions)
|
2020-05-29 16:28:13 +03:00
|
|
|
|= [cookie=@uv session]
|
2020-06-04 23:06:13 +03:00
|
|
|
(lth expiry-time now)
|
2020-05-29 16:28:13 +03:00
|
|
|
:: if there's any cookies left, set a timer for the next expected expiry
|
|
|
|
::
|
|
|
|
^- [(list move) _http-server-gate]
|
|
|
|
:_ http-server-gate
|
2022-08-24 01:34:08 +03:00
|
|
|
:- =< give-session-tokens
|
|
|
|
(per-server-event [eny duct now rof] server-state.ax)
|
2020-05-29 16:28:13 +03:00
|
|
|
?: =(~ sessions) ~
|
|
|
|
=; next-expiry=@da
|
|
|
|
[duct %pass /sessions/expire %b %wait next-expiry]~
|
|
|
|
%+ roll ~(tap by sessions)
|
|
|
|
|= [[@uv session] next=@da]
|
|
|
|
?: =(*@da next) expiry-time
|
|
|
|
(min next expiry-time)
|
|
|
|
::
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
++ eauth
|
2023-05-19 12:31:01 +03:00
|
|
|
=* auth auth.server-state.ax
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
=* args [[eny duct now rof] server-state.ax]
|
|
|
|
^- [(list move) _http-server-gate]
|
|
|
|
~| [wire +<.sign]
|
|
|
|
?+ t.wire !!
|
2023-06-09 16:46:04 +03:00
|
|
|
[%plea @ ~]
|
|
|
|
=/ =ship (slav %p i.t.t.wire)
|
2023-05-23 23:29:08 +03:00
|
|
|
::
|
|
|
|
?: |(?=(^ dud) ?=([%ames %lost *] sign))
|
2023-05-23 23:39:48 +03:00
|
|
|
%- %+ trace:(per-server-event args) 0
|
2023-05-23 23:29:08 +03:00
|
|
|
?~ dud |.("eauth: lost boon from {(scow %p ship)}")
|
|
|
|
|.("eauth: crashed on %{(trip +<.sign)} from {(scow %p ship)}")
|
2023-06-09 16:46:04 +03:00
|
|
|
::NOTE when failing on pending attempts, we just wait for the timer
|
|
|
|
:: to clean up. when failing on live sessions, well, we should
|
|
|
|
:: just be careful not to crash when receiving %shut boons.
|
|
|
|
:: (we do not want to have the nonce in the wire, so this is the
|
|
|
|
:: best handling we can do. the alternative is tracking)
|
|
|
|
[~ http-server-gate]
|
2023-05-23 23:29:08 +03:00
|
|
|
::
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
?: ?=([%ames %done *] sign)
|
2023-06-27 23:58:22 +03:00
|
|
|
=^ moz server-state.ax
|
|
|
|
%. [ship ?=(~ error.sign)]
|
|
|
|
on-done:client:eauth:authentication:(per-server-event args)
|
|
|
|
[moz http-server-gate]
|
2023-06-09 16:46:04 +03:00
|
|
|
::
|
|
|
|
?> ?=([%ames %boon *] sign)
|
|
|
|
=/ boon ;;(eauth-boon payload.sign)
|
|
|
|
=^ moz server-state.ax
|
|
|
|
%. [ship boon]
|
|
|
|
on-boon:client:eauth:authentication:(per-server-event args)
|
|
|
|
[moz http-server-gate]
|
|
|
|
::
|
|
|
|
[%keen @ @ ~]
|
|
|
|
=/ client=@p (slav %p i.t.t.wire)
|
|
|
|
=/ nonce=@uv (slav %uv i.t.t.t.wire)
|
|
|
|
::
|
|
|
|
?^ dud
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
=^ moz server-state.ax
|
2023-06-09 16:46:04 +03:00
|
|
|
%. [client nonce]
|
2023-05-23 23:29:08 +03:00
|
|
|
on-fail:server:eauth:authentication:(per-server-event args)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
[moz http-server-gate]
|
2023-05-23 23:29:08 +03:00
|
|
|
::
|
2023-06-09 16:46:04 +03:00
|
|
|
?> ?=([%ames %tune *] sign)
|
|
|
|
?> =(client ship.sign)
|
|
|
|
=/ url=(unit @t)
|
|
|
|
?~ roar.sign ~
|
|
|
|
?~ q.dat.u.roar.sign ~
|
|
|
|
;;((unit @t) q.u.q.dat.u.roar.sign)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
=^ moz server-state.ax
|
2023-06-09 16:46:04 +03:00
|
|
|
?~ url
|
|
|
|
%. [client nonce]
|
|
|
|
on-fail:server:eauth:authentication:(per-server-event args)
|
|
|
|
%. [client nonce u.url]
|
|
|
|
on-tune:server:eauth:authentication:(per-server-event args)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
[moz http-server-gate]
|
|
|
|
::
|
|
|
|
[%expire %visiting @ @ ~]
|
|
|
|
?> ?=([%behn %wake *] sign)
|
|
|
|
=/ server=@p (slav %p i.t.t.t.wire)
|
|
|
|
=/ nonce=@uv (slav %uv i.t.t.t.t.wire)
|
2023-05-23 23:37:05 +03:00
|
|
|
=^ moz server-state.ax
|
|
|
|
%. [server nonce]
|
|
|
|
expire:client:eauth:authentication:(per-server-event args)
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
[~ http-server-gate]
|
|
|
|
::
|
|
|
|
[%expire %visitors @ ~]
|
|
|
|
=/ nonce=@uv (slav %uv i.t.t.t.wire)
|
|
|
|
=^ moz server-state.ax
|
|
|
|
(expire:server:eauth:authentication:(per-server-event args) nonce)
|
|
|
|
[moz http-server-gate]
|
|
|
|
==
|
|
|
|
::
|
2019-04-08 23:17:19 +03:00
|
|
|
++ acme-ack
|
2020-12-08 03:22:26 +03:00
|
|
|
?> ?=([%gall %unto *] sign)
|
2019-04-08 23:17:19 +03:00
|
|
|
::
|
2019-11-05 10:42:59 +03:00
|
|
|
?> ?=([%poke-ack *] p.sign)
|
2019-04-08 23:17:19 +03:00
|
|
|
?~ p.p.sign
|
|
|
|
:: received a positive acknowledgment: take no action
|
|
|
|
::
|
|
|
|
[~ http-server-gate]
|
|
|
|
:: received a negative acknowledgment: XX do something
|
|
|
|
::
|
|
|
|
[((slog u.p.p.sign) ~) http-server-gate]
|
2018-09-24 21:48:19 +03:00
|
|
|
--
|
|
|
|
::
|
2019-02-09 02:03:46 +03:00
|
|
|
++ http-server-gate ..$
|
2018-09-28 21:24:41 +03:00
|
|
|
:: +load: migrate old state to new state (called on vane reload)
|
|
|
|
::
|
|
|
|
++ load
|
2023-02-08 23:10:16 +03:00
|
|
|
=> |%
|
|
|
|
+$ axle-any
|
2023-04-12 19:53:00 +03:00
|
|
|
$% [date=%~2020.10.18 server-state=server-state-0]
|
|
|
|
[date=%~2022.7.26 server-state=server-state-0]
|
|
|
|
[date=%~2023.2.17 server-state=server-state-1]
|
|
|
|
[date=%~2023.3.16 server-state=server-state-2]
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
[date=%~2023.4.11 server-state-3]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
[date=%~2023.5.15 server-state]
|
2023-02-08 23:10:16 +03:00
|
|
|
==
|
2023-04-11 22:54:43 +03:00
|
|
|
::
|
2023-02-08 23:10:16 +03:00
|
|
|
+$ server-state-0
|
|
|
|
$: bindings=(list [=binding =duct =action])
|
|
|
|
=cors-registry
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
connections=(map duct outstanding-connection-3)
|
2023-05-19 12:31:01 +03:00
|
|
|
auth=authentication-state-3
|
2023-04-11 22:54:43 +03:00
|
|
|
channel-state=channel-state-2
|
2023-02-08 23:10:16 +03:00
|
|
|
domains=(set turf)
|
|
|
|
=http-config
|
|
|
|
ports=[insecure=@ud secure=(unit @ud)]
|
|
|
|
outgoing-duct=duct
|
|
|
|
==
|
2023-04-11 22:54:43 +03:00
|
|
|
::
|
2023-03-25 07:18:25 +03:00
|
|
|
+$ server-state-1
|
|
|
|
$: bindings=(list [=binding =duct =action])
|
|
|
|
=cors-registry
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
connections=(map duct outstanding-connection-3)
|
2023-05-19 12:31:01 +03:00
|
|
|
auth=authentication-state-3
|
2023-04-11 22:54:43 +03:00
|
|
|
channel-state=channel-state-2
|
|
|
|
domains=(set turf)
|
|
|
|
=http-config
|
|
|
|
ports=[insecure=@ud secure=(unit @ud)]
|
|
|
|
outgoing-duct=duct
|
2023-04-12 19:53:00 +03:00
|
|
|
verb=@ :: <- new
|
2023-04-11 22:54:43 +03:00
|
|
|
==
|
|
|
|
::
|
|
|
|
+$ server-state-2
|
|
|
|
$: bindings=(list [=binding =duct =action])
|
2023-04-12 19:53:00 +03:00
|
|
|
cache=(map url=@t [aeon=@ud val=(unit cache-entry)]) :: <- new
|
2023-04-11 22:54:43 +03:00
|
|
|
=cors-registry
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
connections=(map duct outstanding-connection-3)
|
2023-05-19 12:31:01 +03:00
|
|
|
auth=authentication-state-3
|
2023-04-11 22:54:43 +03:00
|
|
|
channel-state=channel-state-2
|
2023-03-25 07:18:25 +03:00
|
|
|
domains=(set turf)
|
|
|
|
=http-config
|
|
|
|
ports=[insecure=@ud secure=(unit @ud)]
|
|
|
|
outgoing-duct=duct
|
|
|
|
verb=@
|
|
|
|
==
|
2023-04-11 22:54:43 +03:00
|
|
|
+$ channel-state-2
|
|
|
|
$: session=(map @t channel-2)
|
|
|
|
duct-to-key=(map duct @t)
|
|
|
|
==
|
|
|
|
+$ channel-2
|
|
|
|
$: state=(each timer duct)
|
|
|
|
next-id=@ud
|
|
|
|
last-ack=@da
|
2023-04-24 18:54:22 +03:00
|
|
|
events=(qeu [id=@ud request-id=@ud channel-event=channel-event-2])
|
2023-04-11 22:54:43 +03:00
|
|
|
unacked=(map @ud @ud)
|
|
|
|
subscriptions=(map @ud [ship=@p app=term =path duc=duct])
|
|
|
|
heartbeat=(unit timer)
|
|
|
|
==
|
2023-04-24 18:54:22 +03:00
|
|
|
+$ channel-event-2
|
2023-04-20 16:18:52 +03:00
|
|
|
$% $>(%poke-ack sign:agent:gall)
|
|
|
|
$>(%watch-ack sign:agent:gall)
|
|
|
|
$>(%kick sign:agent:gall)
|
|
|
|
[%fact =mark =noun]
|
|
|
|
==
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
::
|
|
|
|
+$ server-state-3
|
|
|
|
$: bindings=(list [=binding =duct =action])
|
|
|
|
cache=(map url=@t [aeon=@ud val=(unit cache-entry)])
|
|
|
|
=cors-registry
|
|
|
|
connections=(map duct outstanding-connection-3)
|
2023-05-19 12:31:01 +03:00
|
|
|
auth=authentication-state-3
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
channel-state=channel-state-3
|
|
|
|
domains=(set turf)
|
|
|
|
=http-config
|
|
|
|
ports=[insecure=@ud secure=(unit @ud)]
|
|
|
|
outgoing-duct=duct
|
|
|
|
verb=@
|
|
|
|
==
|
|
|
|
+$ outstanding-connection-3
|
|
|
|
$: =action
|
|
|
|
=inbound-request
|
|
|
|
response-header=(unit response-header:http)
|
|
|
|
bytes-sent=@ud
|
|
|
|
==
|
|
|
|
+$ authentication-state-3 sessions=(map @uv session-3)
|
|
|
|
+$ session-3
|
|
|
|
$: expiry-time=@da
|
|
|
|
channels=(set @t)
|
|
|
|
==
|
|
|
|
+$ channel-state-3
|
|
|
|
$: session=(map @t channel-3)
|
|
|
|
duct-to-key=(map duct @t)
|
|
|
|
==
|
|
|
|
+$ channel-3
|
|
|
|
$: mode=?(%json %jam)
|
|
|
|
state=(each timer duct)
|
|
|
|
next-id=@ud
|
|
|
|
last-ack=@da
|
|
|
|
events=(qeu [id=@ud request-id=@ud =channel-event])
|
|
|
|
unacked=(map @ud @ud)
|
|
|
|
subscriptions=(map @ud [ship=@p app=term =path duc=duct])
|
|
|
|
heartbeat=(unit timer)
|
|
|
|
==
|
2023-02-08 23:10:16 +03:00
|
|
|
--
|
|
|
|
|= old=axle-any
|
2023-04-12 19:53:00 +03:00
|
|
|
^+ http-server-gate
|
2022-08-01 01:50:36 +03:00
|
|
|
?- -.old
|
2023-04-12 19:53:00 +03:00
|
|
|
::
|
|
|
|
:: adds /~/name
|
|
|
|
::
|
2022-08-01 01:50:36 +03:00
|
|
|
%~2020.10.18
|
2022-08-11 19:32:49 +03:00
|
|
|
%= $
|
2023-04-12 19:53:00 +03:00
|
|
|
date.old %~2022.7.26
|
|
|
|
::
|
|
|
|
bindings.server-state.old
|
|
|
|
%+ insert-binding
|
|
|
|
[[~ /~/name] outgoing-duct.server-state.old [%name ~]]
|
|
|
|
bindings.server-state.old
|
|
|
|
==
|
|
|
|
::
|
|
|
|
:: enables https redirects if certificate configured
|
|
|
|
:: inits .verb
|
2022-08-01 01:50:36 +03:00
|
|
|
::
|
|
|
|
%~2022.7.26
|
2023-04-12 19:53:00 +03:00
|
|
|
=. redirect.http-config.server-state.old
|
|
|
|
?& ?=(^ secure.ports.server-state.old)
|
|
|
|
?=(^ secure.http-config.server-state.old)
|
|
|
|
==
|
|
|
|
$(old [%~2023.2.17 server-state.old(|8 [|8 verb=0]:server-state.old)])
|
|
|
|
::
|
|
|
|
:: inits .cache
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
::
|
2023-02-17 19:15:27 +03:00
|
|
|
%~2023.2.17
|
2023-04-12 19:53:00 +03:00
|
|
|
$(old [%~2023.3.16 [bindings ~ +]:server-state.old])
|
|
|
|
::
|
2023-04-24 18:54:22 +03:00
|
|
|
:: inits channel mode and desks in unacked events
|
eyre: add support for noun-based channels
Adds a "mode" to channels, which can be set to either %json (current
behavior) or %jam. For %jam channels, aside from the SSE framing, all
communication happens through @uw-encoded jammed nouns. This applies to
both outgoing channel events, as well as incoming channel requests.
We choose @uw-style encoding because raw bytestreams are fragile and
cannot work inside the SSE stream context.
Currently, a separate endpoint (/~/channel-jam/etc) is used to indicate
%jam as the desired mode for a channel. We will probably want to make
this a bit cleaner, not least because it's not currently implemented as
a formal standalone endpoint, but also to give it stronger aesthetic
equivalence with the existing channel endpoint. Putting the mode in the
file extension is a tempting option here, but semantically not quite
right.
Connecting to the same channel across multiple modes is currently
supported, but it's untested, and unclear whether this is desirable or
not.
2022-07-04 18:05:13 +03:00
|
|
|
::
|
2023-03-25 07:18:25 +03:00
|
|
|
%~2023.3.16
|
2023-04-20 16:18:52 +03:00
|
|
|
::
|
|
|
|
:: Prior to this desks were not part of events.channel.
|
|
|
|
:: When serializing we used to rely on the desk stored in
|
|
|
|
:: subscriptions.channel, but this state is deleted when we clog.
|
|
|
|
:: This migration adds the desk to events.channel, but we can not
|
|
|
|
:: scry in +load to populate the desks in the old events,
|
|
|
|
:: so we just kick all subscriptions on all channels.
|
2023-04-24 18:54:22 +03:00
|
|
|
%= $
|
|
|
|
date.old %~2023.4.11
|
|
|
|
::
|
|
|
|
server-state.old
|
|
|
|
%= server-state.old
|
|
|
|
session.channel-state
|
|
|
|
%- ~(run by session.channel-state.server-state.old)
|
|
|
|
|= c=channel-2
|
|
|
|
=; new-events
|
|
|
|
:- %json
|
|
|
|
c(events new-events, unacked ~, subscriptions ~)
|
|
|
|
=| events=(qeu [id=@ud request-id=@ud =channel-event])
|
|
|
|
=/ l ~(tap in ~(key by subscriptions.c))
|
|
|
|
|-
|
|
|
|
?~ l events
|
|
|
|
%= $
|
|
|
|
l t.l
|
|
|
|
next-id.c +(next-id.c)
|
|
|
|
events (~(put to events) [next-id.c i.l %kick ~])
|
|
|
|
==
|
2023-04-20 16:18:52 +03:00
|
|
|
==
|
|
|
|
==
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
::
|
|
|
|
:: guarantees & stores a session for each request, and a @p identity for
|
|
|
|
:: each session and channel
|
2023-04-20 16:18:52 +03:00
|
|
|
::
|
2023-04-24 18:54:22 +03:00
|
|
|
%~2023.4.11
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
%= $
|
2023-06-28 00:06:32 +03:00
|
|
|
date.old %~2023.5.15
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
::
|
|
|
|
connections.old
|
|
|
|
%- ~(run by connections.old)
|
|
|
|
|= outstanding-connection-3
|
|
|
|
^- outstanding-connection
|
|
|
|
[action inbound-request [*@uv [%ours ~]] response-header bytes-sent]
|
|
|
|
::
|
2023-06-28 00:06:32 +03:00
|
|
|
auth.old
|
|
|
|
:_ [~ ~ [~ ~ now]]
|
2023-05-19 12:31:01 +03:00
|
|
|
%- ~(run by sessions.auth.old)
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
|= s=session-3
|
|
|
|
^- session
|
|
|
|
[[%ours ~] s]
|
|
|
|
::
|
|
|
|
session.channel-state.old
|
|
|
|
%- ~(run by session.channel-state.old)
|
|
|
|
|= c=channel-3
|
|
|
|
^- channel
|
|
|
|
[-.c [%ours ~] +.c]
|
2023-05-06 00:38:40 +03:00
|
|
|
::
|
|
|
|
bindings.old
|
2023-06-28 00:06:32 +03:00
|
|
|
%+ insert-binding [[~ /~/host] outgoing-duct.old [%host ~]]
|
|
|
|
%+ insert-binding [[~ /~/eauth] outgoing-duct.old [%eauth ~]]
|
eyre: eauth, cross-ship authentication
aka "mirage" aka "eyre oauth"
With Eyre now supporting both local identity authentication, and fake
guest identities, the logical next step is to support authentication
with real non-local identities. Here, we implement that, building on top
of the groundwork laid by #6561.
The primary change is adding a %real case to Eyre's $identity type, and
implementing an http<->ames<->ames handshaking protocol into Eyre for
negotiating approval of login attempts made by unauthenticated HTTP
clients.
The authentication flow, where a "visitor" logs into a "~host" as their
own "~client" identity can be described in brief as follows:
1) Visitor makes an HTTP request saying they are ~client.
2) ~host tells ~client, over Ames, about its own public-facing hostname.
3) ~client responds with its own public-facing hostname.
4) ~host forwards the visitor to ~client's eauth page.
5) Visitor, there already logged in as ~client, approves the login
attempt.
6) ~client shares a secret with ~host over Ames, and forwards the
visitor to ~host's eauth page, including the secret in the request.
7) ~host sees that the secrets received over Ames and HTTP match, and
gives the visitor a new session token, identifying them as ~client.
The negotiating of hostnames/URLs via Ames is crucial to keeping this
handshake sequence secure.
Discovering a ship's public-facing hostname happens when successful
local logins are made by reading out the Host header from the request.
Users may hard-code a value to override this.
Each eauth login attempt comes with a unique nonce. Both the host and
client track the lifetime of these. The corresponding Ames flow (which
goes from ~host -> ~client) is corked when the login attempt gets
aborted, or its associated session expires.
The logout functionality has been updated to let clients ask to be
logged out of sessions on other ships.
2023-05-18 22:40:58 +03:00
|
|
|
bindings.old
|
|
|
|
==
|
|
|
|
::
|
|
|
|
%~2023.5.15
|
2023-04-12 19:53:00 +03:00
|
|
|
http-server-gate(ax old)
|
2023-02-08 23:10:16 +03:00
|
|
|
==
|
2018-09-28 21:24:41 +03:00
|
|
|
:: +stay: produce current state
|
|
|
|
::
|
|
|
|
++ stay `axle`ax
|
|
|
|
:: +scry: request a path in the urbit namespace
|
|
|
|
::
|
|
|
|
++ scry
|
2021-03-28 10:47:37 +03:00
|
|
|
~/ %eyre-scry
|
2020-12-08 00:52:12 +03:00
|
|
|
^- roon
|
2023-05-22 16:12:09 +03:00
|
|
|
|= [lyc=gang pov=path car=term bem=beam]
|
2019-03-21 09:01:38 +03:00
|
|
|
^- (unit (unit cage))
|
2020-12-08 00:52:12 +03:00
|
|
|
=* ren car
|
2020-11-24 00:06:50 +03:00
|
|
|
=* why=shop &/p.bem
|
|
|
|
=* syd q.bem
|
|
|
|
=/ lot=coin $/r.bem
|
|
|
|
=* tyl s.bem
|
|
|
|
::
|
2019-03-21 09:01:38 +03:00
|
|
|
?. ?=(%& -.why)
|
|
|
|
~
|
|
|
|
=* who p.why
|
2023-04-24 23:01:00 +03:00
|
|
|
::
|
2019-03-21 09:01:38 +03:00
|
|
|
?. ?=(%$ -.lot)
|
|
|
|
[~ ~]
|
|
|
|
?. =(our who)
|
|
|
|
?. =([%da now] p.lot)
|
|
|
|
[~ ~]
|
|
|
|
~& [%r %scry-foreign-host who]
|
|
|
|
~
|
2023-04-24 23:01:00 +03:00
|
|
|
?: &(?=(%x ren) ?=(%$ syd))
|
2020-09-30 16:07:27 +03:00
|
|
|
=, server-state.ax
|
|
|
|
?+ tyl [~ ~]
|
2023-04-24 23:01:00 +03:00
|
|
|
[%$ %whey ~] =- ``mass+!>(`(list mass)`-)
|
|
|
|
:~ bindings+&+bindings.server-state.ax
|
2023-05-19 12:31:01 +03:00
|
|
|
auth+&+auth.server-state.ax
|
2023-04-24 23:01:00 +03:00
|
|
|
connections+&+connections.server-state.ax
|
|
|
|
channels+&+channel-state.server-state.ax
|
|
|
|
axle+&+ax
|
|
|
|
==
|
|
|
|
::
|
2020-09-30 16:07:27 +03:00
|
|
|
[%cors ~] ``noun+!>(cors-registry)
|
|
|
|
[%cors %requests ~] ``noun+!>(requests.cors-registry)
|
|
|
|
[%cors %approved ~] ``noun+!>(approved.cors-registry)
|
|
|
|
[%cors %rejected ~] ``noun+!>(rejected.cors-registry)
|
|
|
|
::
|
|
|
|
[%cors ?(%approved %rejected) @ ~]
|
|
|
|
=* kind i.t.tyl
|
|
|
|
=* orig i.t.t.tyl
|
|
|
|
?~ origin=(slaw %t orig) [~ ~]
|
|
|
|
?- kind
|
|
|
|
%approved ``noun+!>((~(has in approved.cors-registry) u.origin))
|
|
|
|
%rejected ``noun+!>((~(has in rejected.cors-registry) u.origin))
|
|
|
|
==
|
2023-06-09 16:46:04 +03:00
|
|
|
::
|
|
|
|
[%eauth %url ~]
|
|
|
|
=* endpoint endpoint.auth.server-state.ax
|
|
|
|
?. ?=(%da -.p.lot) [~ ~]
|
|
|
|
:: we cannot answer for something prior to the last set time,
|
|
|
|
:: or something beyond the present moment.
|
|
|
|
::
|
|
|
|
?: ?| (lth q.p.lot time.endpoint)
|
|
|
|
(gth q.p.lot now)
|
|
|
|
==
|
|
|
|
~
|
|
|
|
:^ ~ ~ %noun
|
|
|
|
!> ^- (unit @t)
|
|
|
|
=< eauth-url:eauth:authentication
|
|
|
|
(per-server-event [eny *duct now rof] server-state.ax)
|
2020-10-01 20:55:16 +03:00
|
|
|
::
|
|
|
|
[%authenticated %cookie @ ~]
|
|
|
|
?~ cookies=(slaw %t i.t.t.tyl) [~ ~]
|
|
|
|
:^ ~ ~ %noun
|
|
|
|
!> ^- ?
|
eyre: guest ids for unauthenticated requests
aka "the open eyre" aka "universal basic identity"
Urbit already supports presence on the clearnet, but fails to expose any
of its interactive affordances to unauthenticated users. Here, we
improve this situation by granting "guest identity" @ps to every
unauthenticated HTTP request, and extending the channels functionality
to them.
Sessions no longer represent only the local identity. Instead, each
session has either the local identity, or a fake guest identity
associated with it.
Every request that does not provide a session key/cookie gets assigned
a fresh one with a guest identity on the spot. As a result, every
single request has an identity associated with it.
The identity of a request gets propagated into userspace, if the request
ends up there.
For normal HTTP requests, this means the src.bowl gets set to that
identity for both the watch and poke of the request. For backwards
compatibility, the authenticated flag on the request noun gets set at
normal: only true if the request came from the local identity.
For channel requests, this means the src.bowl gets set to that identity
for any pokes and watches it sends, and it can only send those to agents
running on the local ship.
The scry endpoint remains unchanged in its behavior: only available to
the local identity.
Notable implementation detail changes in this diff include:
- Factored all gall interactions out into +deal-as.
- Sessions no longer represent exclusively the local identity. This
matters a lot to +give-session-tokens, %code-changed, and logout
handling.
- Session management got factored out into explicit +start-session and
+close-session arms.
2023-05-05 22:59:17 +03:00
|
|
|
%- =< request-is-authenticated:authentication
|
2020-12-06 13:55:19 +03:00
|
|
|
(per-server-event [eny *duct now rof] server-state.ax)
|
2020-10-01 20:55:16 +03:00
|
|
|
%*(. *request:http header-list ['cookie' u.cookies]~)
|
2023-03-25 07:18:25 +03:00
|
|
|
::
|
|
|
|
[%cache @ @ ~]
|
|
|
|
?~ aeon=(slaw %ud i.t.tyl) [~ ~]
|
|
|
|
?~ url=(slaw %t i.t.t.tyl) [~ ~]
|
|
|
|
?~ entry=(~(get by cache) u.url) [~ ~]
|
|
|
|
?. =(u.aeon aeon.u.entry) [~ ~]
|
|
|
|
?~ val=val.u.entry [~ ~]
|
|
|
|
``noun+!>(u.val)
|
2020-09-30 16:07:27 +03:00
|
|
|
==
|
|
|
|
?. ?=(%$ ren)
|
|
|
|
[~ ~]
|
2020-05-23 00:55:17 +03:00
|
|
|
?+ syd [~ ~]
|
2023-03-03 02:00:27 +03:00
|
|
|
%bindings ``noun+!>(bindings.server-state.ax)
|
|
|
|
%connections ``noun+!>(connections.server-state.ax)
|
2023-05-19 12:31:01 +03:00
|
|
|
%authentication-state ``noun+!>(auth.server-state.ax)
|
2020-05-23 00:55:17 +03:00
|
|
|
%channel-state ``noun+!>(channel-state.server-state.ax)
|
2019-03-21 09:01:38 +03:00
|
|
|
::
|
2020-05-23 00:55:17 +03:00
|
|
|
%host
|
|
|
|
%- (lift (lift |=(a=hart:eyre [%hart !>(a)])))
|
|
|
|
^- (unit (unit hart:eyre))
|
|
|
|
=. p.lot ?.(=([%da now] p.lot) p.lot [%tas %real])
|
|
|
|
?+ p.lot
|
|
|
|
[~ ~]
|
|
|
|
::
|
|
|
|
[%tas %fake]
|
|
|
|
``[& [~ 8.443] %& /localhost]
|
|
|
|
::
|
|
|
|
[%tas %real]
|
|
|
|
=* domains domains.server-state.ax
|
|
|
|
=* ports ports.server-state.ax
|
|
|
|
=/ =host:eyre [%& ?^(domains n.domains /localhost)]
|
|
|
|
=/ port=(unit @ud)
|
2022-12-01 04:17:23 +03:00
|
|
|
?. ?=(^ secure.ports)
|
2020-05-23 00:55:17 +03:00
|
|
|
?:(=(80 insecure.ports) ~ `insecure.ports)
|
|
|
|
?:(=(443 u.secure.ports) ~ secure.ports)
|
2023-01-27 16:16:45 +03:00
|
|
|
``[?=(^ secure.ports) port host]
|
2020-05-23 00:55:17 +03:00
|
|
|
==
|
2019-03-21 09:01:38 +03:00
|
|
|
==
|
2018-09-20 02:29:36 +03:00
|
|
|
--
|