tangled
alpha
login
or
join now
dzming.li
/
core
0
fork
atom
A vibe coded tangled fork which supports pijul.
0
fork
atom
overview
issues
pulls
pipelines
clean up auth code
Anirudh Oppiliappan
1 year ago
ce0709d2
b77baecf
+142
-68
5 changed files
expand all
collapse all
unified
split
legit
routes
auth
auth.go
types.go
auth.go
handler.go
routes.go
+6
-17
legit/routes/auth.go
···
7
7
8
8
comatproto "github.com/bluesky-social/indigo/api/atproto"
9
9
"github.com/bluesky-social/indigo/xrpc"
10
10
+
rauth "github.com/icyphox/bild/legit/routes/auth"
10
11
)
11
12
12
13
const (
···
19
20
auth, ok := session.Values["authenticated"].(bool)
20
21
21
22
if !ok || !auth {
22
22
-
http.Error(w, "Forbidden: You are not logged in", http.StatusForbidden)
23
23
+
http.Redirect(w, r, "/login", http.StatusTemporaryRedirect)
23
24
return
24
25
}
25
26
···
43
44
},
44
45
}
45
46
atSession, err := comatproto.ServerRefreshSession(r.Context(), &client)
46
46
-
47
47
if err != nil {
48
48
log.Println(err)
49
49
-
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
49
49
+
h.Write500(w)
50
50
return
51
51
}
52
52
53
53
-
clientSession, _ := h.s.Get(r, "bild-session")
54
54
-
clientSession.Values["handle"] = atSession.Handle
55
55
-
clientSession.Values["did"] = atSession.Did
56
56
-
clientSession.Values["accessJwt"] = atSession.AccessJwt
57
57
-
clientSession.Values["refreshJwt"] = atSession.RefreshJwt
58
58
-
clientSession.Values["expiry"] = time.Now().Add(time.Hour).String()
59
59
-
clientSession.Values["pds"] = pdsUrl
60
60
-
clientSession.Values["authenticated"] = true
61
61
-
62
62
-
err = clientSession.Save(r, w)
63
63
-
53
53
+
err = h.auth.StoreSession(r, w, nil, &rauth.AtSessionRefresh{ServerRefreshSession_Output: *atSession, PDSEndpoint: pdsUrl})
64
54
if err != nil {
65
65
-
log.Printf("failed to store session for did: %s\n", atSession.Did)
66
66
-
log.Println(err)
67
67
-
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
55
55
+
log.Printf("failed to store session for did: %s\n: %s", atSession.Did, err)
56
56
+
h.Write500(w)
68
57
return
69
58
}
70
59
+98
legit/routes/auth/auth.go
···
1
1
+
package auth
2
2
+
3
3
+
import (
4
4
+
"context"
5
5
+
"fmt"
6
6
+
"net/http"
7
7
+
"time"
8
8
+
9
9
+
comatproto "github.com/bluesky-social/indigo/api/atproto"
10
10
+
"github.com/bluesky-social/indigo/atproto/identity"
11
11
+
"github.com/bluesky-social/indigo/atproto/syntax"
12
12
+
"github.com/bluesky-social/indigo/xrpc"
13
13
+
"github.com/gorilla/sessions"
14
14
+
)
15
15
+
16
16
+
type Auth struct {
17
17
+
s sessions.Store
18
18
+
}
19
19
+
20
20
+
func NewAuth(store sessions.Store) *Auth {
21
21
+
return &Auth{store}
22
22
+
}
23
23
+
24
24
+
func resolveIdent(ctx context.Context, arg string) (*identity.Identity, error) {
25
25
+
id, err := syntax.ParseAtIdentifier(arg)
26
26
+
if err != nil {
27
27
+
return nil, err
28
28
+
}
29
29
+
30
30
+
dir := identity.DefaultDirectory()
31
31
+
return dir.Lookup(ctx, *id)
32
32
+
}
33
33
+
34
34
+
func (a *Auth) CreateInitialSession(w http.ResponseWriter, r *http.Request, username, appPassword string) (AtSessionCreate, error) {
35
35
+
ctx := r.Context()
36
36
+
resolved, err := resolveIdent(ctx, username)
37
37
+
if err != nil {
38
38
+
return AtSessionCreate{}, fmt.Errorf("invalid handle: %s", err)
39
39
+
}
40
40
+
41
41
+
pdsUrl := resolved.PDSEndpoint()
42
42
+
client := xrpc.Client{
43
43
+
Host: pdsUrl,
44
44
+
}
45
45
+
46
46
+
atSession, err := comatproto.ServerCreateSession(ctx, &client, &comatproto.ServerCreateSession_Input{
47
47
+
Identifier: resolved.DID.String(),
48
48
+
Password: appPassword,
49
49
+
})
50
50
+
if err != nil {
51
51
+
return AtSessionCreate{}, fmt.Errorf("invalid app password")
52
52
+
}
53
53
+
54
54
+
return AtSessionCreate{
55
55
+
ServerCreateSession_Output: *atSession,
56
56
+
PDSEndpoint: pdsUrl,
57
57
+
}, nil
58
58
+
}
59
59
+
60
60
+
func (a *Auth) StoreSession(r *http.Request, w http.ResponseWriter, atSessionCreate *AtSessionCreate, atSessionRefresh *AtSessionRefresh) error {
61
61
+
if atSessionCreate != nil {
62
62
+
atSession := atSessionCreate
63
63
+
64
64
+
clientSession, _ := a.s.Get(r, "bild-session")
65
65
+
clientSession.Values["handle"] = atSession.Handle
66
66
+
clientSession.Values["did"] = atSession.Did
67
67
+
clientSession.Values["accessJwt"] = atSession.AccessJwt
68
68
+
clientSession.Values["refreshJwt"] = atSession.RefreshJwt
69
69
+
clientSession.Values["expiry"] = time.Now().Add(time.Hour).String()
70
70
+
clientSession.Values["pds"] = atSession.PDSEndpoint
71
71
+
clientSession.Values["authenticated"] = true
72
72
+
73
73
+
return clientSession.Save(r, w)
74
74
+
} else {
75
75
+
atSession := atSessionRefresh
76
76
+
77
77
+
clientSession, _ := a.s.Get(r, "bild-session")
78
78
+
clientSession.Values["handle"] = atSession.Handle
79
79
+
clientSession.Values["did"] = atSession.Did
80
80
+
clientSession.Values["accessJwt"] = atSession.AccessJwt
81
81
+
clientSession.Values["refreshJwt"] = atSession.RefreshJwt
82
82
+
clientSession.Values["expiry"] = time.Now().Add(time.Hour).String()
83
83
+
clientSession.Values["pds"] = atSession.PDSEndpoint
84
84
+
clientSession.Values["authenticated"] = true
85
85
+
86
86
+
return clientSession.Save(r, w)
87
87
+
}
88
88
+
}
89
89
+
90
90
+
func (a *Auth) GetSessionUser(r *http.Request) (*identity.Identity, error) {
91
91
+
session, _ := a.s.Get(r, "bild-session")
92
92
+
did, ok := session.Values["did"].(string)
93
93
+
if !ok {
94
94
+
return nil, fmt.Errorf("user is not authenticated")
95
95
+
}
96
96
+
97
97
+
return resolveIdent(r.Context(), did)
98
98
+
}
+15
legit/routes/auth/types.go
···
1
1
+
package auth
2
2
+
3
3
+
import (
4
4
+
comatproto "github.com/bluesky-social/indigo/api/atproto"
5
5
+
)
6
6
+
7
7
+
type AtSessionCreate struct {
8
8
+
comatproto.ServerCreateSession_Output
9
9
+
PDSEndpoint string
10
10
+
}
11
11
+
12
12
+
type AtSessionRefresh struct {
13
13
+
comatproto.ServerRefreshSession_Output
14
14
+
PDSEndpoint string
15
15
+
}
+8
-4
legit/routes/handler.go
···
11
11
"github.com/gorilla/sessions"
12
12
"github.com/icyphox/bild/legit/config"
13
13
"github.com/icyphox/bild/legit/db"
14
14
+
"github.com/icyphox/bild/legit/routes/auth"
14
15
"github.com/icyphox/bild/legit/routes/tmpl"
15
16
)
16
17
···
44
45
return nil, fmt.Errorf("failed to load templates: %w", err)
45
46
}
46
47
48
48
+
auth := auth.NewAuth(s)
49
49
+
47
50
db, err := db.Setup(c.Server.DBPath)
48
51
if err != nil {
49
52
return nil, fmt.Errorf("failed to setup db: %w", err)
50
53
}
51
54
52
55
h := Handle{
53
53
-
c: c,
54
54
-
t: t,
55
55
-
s: s,
56
56
-
db: db,
56
56
+
c: c,
57
57
+
t: t,
58
58
+
s: s,
59
59
+
db: db,
60
60
+
auth: auth,
57
61
}
58
62
59
63
r.Get("/login", h.Login)
+15
-47
legit/routes/routes.go
···
2
2
3
3
import (
4
4
"compress/gzip"
5
5
-
"context"
6
5
"errors"
7
6
"fmt"
8
7
"html/template"
···
15
14
"strings"
16
15
"time"
17
16
18
18
-
comatproto "github.com/bluesky-social/indigo/api/atproto"
19
19
-
"github.com/bluesky-social/indigo/atproto/identity"
20
20
-
"github.com/bluesky-social/indigo/atproto/syntax"
21
21
-
"github.com/bluesky-social/indigo/xrpc"
22
17
"github.com/dustin/go-humanize"
23
18
"github.com/go-chi/chi/v5"
24
19
"github.com/go-git/go-git/v5/plumbing"
···
26
21
"github.com/icyphox/bild/legit/config"
27
22
"github.com/icyphox/bild/legit/db"
28
23
"github.com/icyphox/bild/legit/git"
24
24
+
"github.com/icyphox/bild/legit/routes/auth"
29
25
"github.com/russross/blackfriday/v2"
30
26
"golang.org/x/crypto/ssh"
31
27
)
32
28
33
29
type Handle struct {
34
34
-
c *config.Config
35
35
-
t *template.Template
36
36
-
s *sessions.CookieStore
37
37
-
db *db.DB
30
30
+
c *config.Config
31
31
+
t *template.Template
32
32
+
s *sessions.CookieStore
33
33
+
db *db.DB
34
34
+
auth *auth.Auth
38
35
}
39
36
40
37
func (h *Handle) Index(w http.ResponseWriter, r *http.Request) {
···
440
437
http.ServeFile(w, r, f)
441
438
}
442
439
443
443
-
func resolveIdent(ctx context.Context, arg string) (*identity.Identity, error) {
444
444
-
id, err := syntax.ParseAtIdentifier(arg)
445
445
-
if err != nil {
446
446
-
return nil, err
447
447
-
}
448
448
-
449
449
-
dir := identity.DefaultDirectory()
450
450
-
return dir.Lookup(ctx, *id)
451
451
-
}
452
452
-
453
440
func (h *Handle) Login(w http.ResponseWriter, r *http.Request) {
454
441
switch r.Method {
455
442
case http.MethodGet:
···
458
445
return
459
446
}
460
447
case http.MethodPost:
461
461
-
ctx := r.Context()
462
448
username := r.FormValue("username")
463
449
appPassword := r.FormValue("app_password")
464
450
465
465
-
resolved, err := resolveIdent(ctx, username)
451
451
+
atSession, err := h.auth.CreateInitialSession(w, r, username, appPassword)
466
452
if err != nil {
467
467
-
http.Error(w, "invalid `handle`", http.StatusBadRequest)
453
453
+
h.WriteOOBNotice(w, "login", "Invalid username or app password.")
454
454
+
log.Printf("creating initial session: %s", err)
468
455
return
469
456
}
470
457
471
471
-
pdsUrl := resolved.PDSEndpoint()
472
472
-
client := xrpc.Client{
473
473
-
Host: pdsUrl,
474
474
-
}
475
475
-
476
476
-
atSession, err := comatproto.ServerCreateSession(ctx, &client, &comatproto.ServerCreateSession_Input{
477
477
-
Identifier: resolved.DID.String(),
478
478
-
Password: appPassword,
479
479
-
})
480
480
-
481
481
-
clientSession, _ := h.s.Get(r, "bild-session")
482
482
-
clientSession.Values["handle"] = atSession.Handle
483
483
-
clientSession.Values["did"] = atSession.Did
484
484
-
clientSession.Values["accessJwt"] = atSession.AccessJwt
485
485
-
clientSession.Values["refreshJwt"] = atSession.RefreshJwt
486
486
-
clientSession.Values["expiry"] = time.Now().Add(time.Hour).String()
487
487
-
clientSession.Values["pds"] = pdsUrl
488
488
-
clientSession.Values["authenticated"] = true
489
489
-
490
490
-
err = clientSession.Save(r, w)
491
491
-
458
458
+
err = h.auth.StoreSession(r, w, &atSession, nil)
492
459
if err != nil {
493
493
-
log.Printf("failed to store session for did: %s\n", atSession.Did)
494
494
-
log.Println(err)
460
460
+
h.WriteOOBNotice(w, "login", "Failed to store session.")
461
461
+
log.Printf("storing session: %s", err)
495
462
return
496
463
}
497
464
498
465
log.Printf("successfully saved session for %s (%s)", atSession.Handle, atSession.Did)
499
499
-
http.Redirect(w, r, "/@"+atSession.Handle, 302)
466
466
+
w.Header().Set("HX-Redirect", "/")
467
467
+
w.WriteHeader(http.StatusOK)
500
468
}
501
469
}
502
470
···
508
476
case http.MethodGet:
509
477
keys, err := h.db.GetPublicKeys(did)
510
478
if err != nil {
479
479
+
h.WriteOOBNotice(w, "keys", "Failed to list keys. Try again later.")
511
480
log.Println(err)
512
512
-
http.Error(w, "invalid `did`", http.StatusBadRequest)
513
481
return
514
482
}
515
483