oficina / home Public

Clone
git clone https://amadan.net/oficina/home

Plain git — no account needed to clone.

Download

Download this file

1// Package connect adapts the Home handoff to an application's existing identity.
2// It grants no membership and never creates local accounts or sample content.
3package connect
4
5import (
6 "context"
7 "database/sql"
8 "net/http"
9 "time"
10
11 "amadan.net/oficina/home/connect/linkstore"
12)
13
14const HomeMethod = "home-assertion"
15
16// Session times must come from the verified stored session, never request or last-seen time.
17// AuthTime is the method verification time; At is immutable session creation time.
18type Session struct {
19 Subject, Method string
20 AuthTime, At time.Time
21}
22
23// Person.Label is the canonical verified local address, never a display name.
24// Local IDs must never be reused, including for a new account with the same address.
25type Person struct {
26 ID int64
27 Label string
28}
29
30type Config struct {
31 DB *sql.DB
32 Origin, Issuer, ConsumerID, Namespace, SessionCookie string
33 Keys map[string][]byte
34 DEK []byte
35 // ReadSession must resolve the actual verified session, never a supplied subject.
36 ReadSession func(*http.Request) (*Session, error)
37 MintHomeSession func(http.ResponseWriter, *http.Request, Session) error
38 // Both lookup hooks must read current existing, admitted local accounts.
39 // They never create accounts or infer a Home link from an email address.
40 LookupLocalSession func(context.Context, Session) (Person, error)
41 LookupPerson linkstore.LookupPerson
42 Render func(http.ResponseWriter, *http.Request, string, string, int)
43 ReturnPath func(*http.Request) string
44 Now func() time.Time
45}
46
47func (b *Bridge) Resolve(ctx context.Context, subject string) (Person, error) {
48 id, label, err := b.links.Resolve(ctx, b.issuer, subject)
49 return Person{ID: id, Label: label}, err
50}
51func (b *Bridge) ResolveSession(r *http.Request) (Person, error) {
52 session, err := b.actualSession(r)
53 if err != nil || session == nil {
54 return Person{}, errIdentityRefused
55 }
56 return b.existingPerson(r, *session)
57}
58
59// FreshLocal accepts only independent local verification. A Keymail session
60// without auth_time cannot borrow its local session creation time.
61func FreshLocal(s Session, now time.Time) (time.Time, bool) {
62 if s.Subject == "" || (s.Method != "magiclink" && s.Method != "keymail") {
63 return time.Time{}, false
64 }
65 at := s.AuthTime
66 if at.IsZero() && s.Method == "magiclink" {
67 at = s.At
68 }
69 if at.IsZero() || at.After(now) || now.Sub(at) > 5*time.Minute {
70 return time.Time{}, false
71 }
72 return at, true
73}
74