+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 {
···
76
77
}
77
78
78
79
func (o *OAuth) callback(w http.ResponseWriter, r *http.Request) {
79
-
l := o.Logger.With("handler", "callback")
80
80
ctx := r.Context()
81
+
l := o.Logger.With("handler", "callback").With("query", r.URL.Query())
81
82
82
83
sessData, err := o.ClientApp.ProcessCallback(ctx, r.URL.Query())
83
84
if err != nil {
84
-
o.Logger.Error("failed to process callback", "err", err)
85
-
http.Error(w, err.Error(), http.StatusInternalServerError)
85
+
var callbackErr *oauth.AuthRequestCallbackError
86
+
if errors.As(err, &callbackErr) {
87
+
l.Debug("callback error", "err", callbackErr)
88
+
http.Redirect(w, r, fmt.Sprintf("/login?error=%s", callbackErr.ErrorCode), http.StatusFound)
89
+
return
90
+
}
91
+
l.Error("failed to process callback", "err", err)
92
+
http.Redirect(w, r, "/login?error=oauth", http.StatusFound)
86
93
return
87
94
}
88
95
89
96
if err := o.SaveSession(w, r, sessData); err != nil {
90
97
l.Error("failed to save session", "err", err)
91
-
http.Error(w, err.Error(), http.StatusInternalServerError)
98
+
http.Redirect(w, r, "/login?error=session", http.StatusFound)
92
99
return
93
100
}
94
101
···
96
103
resolved, err := o.IdResolver.ResolveIdent(context.Background(), did)
97
104
if err != nil {
98
105
l.Error("failed to resolve handle", "handle", resolved.Handle.String(), "err", err)
99
-
htmx.HxError(w, http.StatusBadRequest, fmt.Sprintf("'%s' is an invalid handle", resolved.Handle.String()))
106
+
http.Redirect(w, r, "/login?error=handle", http.StatusFound)
100
107
return
101
108
}
102
109
103
110
client, err := o.AuthorizedClient(r)
104
111
if err != nil {
105
112
l.Error("failed to get authorized client", "err", err)
106
-
http.Error(w, err.Error(), http.StatusInternalServerError)
113
+
http.Redirect(w, r, "/login?error=client", http.StatusFound)
107
114
return
108
115
}
109
116
···
133
140
})
134
141
if err != nil {
135
142
l.Error("failed to create profile record", "err", err)
136
-
htmx.HxError(w, http.StatusInternalServerError, "Failed to announce profile creation, try again later")
143
+
http.Redirect(w, r, "/login?error=profile-creation", http.StatusFound)
137
144
return
138
145
}
139
146
+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>