Signed-off-by: brookjeynes me@brookjeynes.dev
+2
internal/server/handlers/login.go
+2
internal/server/handlers/login.go
···
19
19
switch r.Method {
20
20
case http.MethodGet:
21
21
returnURL := r.URL.Query().Get("return_url")
22
+
errorCode := r.URL.Query().Get("error")
22
23
views.LoginPage(views.LoginPageParams{
23
24
ReturnUrl: returnURL,
25
+
ErrorCode: errorCode,
24
26
}).Render(r.Context(), w)
25
27
case http.MethodPost:
26
28
handle := r.FormValue("handle")
+15
-8
internal/server/oauth/handler.go
+15
-8
internal/server/oauth/handler.go
···
3
3
import (
4
4
"context"
5
5
"encoding/json"
6
+
"errors"
6
7
"fmt"
7
8
"net/http"
8
9
"time"
9
10
10
11
comatproto "github.com/bluesky-social/indigo/api/atproto"
12
+
"github.com/bluesky-social/indigo/atproto/auth/oauth"
11
13
lexutil "github.com/bluesky-social/indigo/lex/util"
12
14
"github.com/go-chi/chi/v5"
13
15
"github.com/lestrrat-go/jwx/v2/jwk"
···
16
18
"yoten.app/api/yoten"
17
19
ph "yoten.app/internal/clients/posthog"
18
20
"yoten.app/internal/db"
19
-
"yoten.app/internal/server/htmx"
20
21
)
21
22
22
23
func (o *OAuth) Router() http.Handler {
···
71
72
}
72
73
73
74
func (o *OAuth) callback(w http.ResponseWriter, r *http.Request) {
74
-
l := o.Logger.With("handler", "callback")
75
75
ctx := r.Context()
76
+
l := o.Logger.With("handler", "callback").With("query", r.URL.Query())
76
77
77
78
sessData, err := o.ClientApp.ProcessCallback(ctx, r.URL.Query())
78
79
if err != nil {
79
-
o.Logger.Error("failed to process callback", "err", err)
80
-
http.Error(w, err.Error(), http.StatusInternalServerError)
80
+
var callbackErr *oauth.AuthRequestCallbackError
81
+
if errors.As(err, &callbackErr) {
82
+
l.Debug("callback error", "err", callbackErr)
83
+
http.Redirect(w, r, fmt.Sprintf("/login?error=%s", callbackErr.ErrorCode), http.StatusFound)
84
+
return
85
+
}
86
+
l.Error("failed to process callback", "err", err)
87
+
http.Redirect(w, r, "/login?error=oauth", http.StatusFound)
81
88
return
82
89
}
83
90
84
91
if err := o.SaveSession(w, r, sessData); err != nil {
85
92
l.Error("failed to save session", "err", err)
86
-
http.Error(w, err.Error(), http.StatusInternalServerError)
93
+
http.Redirect(w, r, "/login?error=session", http.StatusFound)
87
94
return
88
95
}
89
96
···
91
98
resolved, err := o.IdResolver.ResolveIdent(context.Background(), did)
92
99
if err != nil {
93
100
l.Error("failed to resolve handle", "handle", resolved.Handle.String(), "err", err)
94
-
htmx.HxError(w, http.StatusBadRequest, fmt.Sprintf("'%s' is an invalid handle", resolved.Handle.String()))
101
+
http.Redirect(w, r, "/login?error=handle", http.StatusFound)
95
102
return
96
103
}
97
104
98
105
client, err := o.AuthorizedClient(r)
99
106
if err != nil {
100
107
l.Error("failed to get authorized client", "err", err)
101
-
http.Error(w, err.Error(), http.StatusInternalServerError)
108
+
http.Redirect(w, r, "/login?error=client", http.StatusFound)
102
109
return
103
110
}
104
111
···
128
135
})
129
136
if err != nil {
130
137
l.Error("failed to create profile record", "err", err)
131
-
htmx.HxError(w, http.StatusInternalServerError, "Failed to announce profile creation, try again later")
138
+
http.Redirect(w, r, "/login?error=profile-creation", http.StatusFound)
132
139
return
133
140
}
134
141
+23
internal/server/views/login.templ
+23
internal/server/views/login.templ
···
44
44
<i class="w-4 h-4" data-lucide="arrow-right"></i>
45
45
</button>
46
46
</form>
47
+
if params.ErrorCode != "" {
48
+
<div class="flex flex-col my-4 p-4 bg-red-50 border border-red-500 rounded-lg text-red-500">
49
+
<div class="flex items-center gap-1">
50
+
<i class="w-4 h-4" data-lucide="circle-alert"></i>
51
+
<h5 class="font-medium">Login error</h5>
52
+
</div>
53
+
<div>
54
+
<p class="text-sm">
55
+
switch (params.ErrorCode) {
56
+
case "access_denied":
57
+
You have not authorized the app.
58
+
case "session":
59
+
Server failed to create user session.
60
+
case "handle":
61
+
Server failed to validate your handle.
62
+
default:
63
+
Internal Server error.
64
+
}
65
+
Please try again.
66
+
</p>
67
+
</div>
68
+
</div>
69
+
}
47
70
<div class="mt-6 pt-6 border-t border-bg-dark">
48
71
<div class="text-center">
49
72
<p class="text-sm text-text-muted mb-3">New to the AT Protocol?</p>