+13
-2
appview/oauth/handler.go
+13
-2
appview/oauth/handler.go
···
4
4
"bytes"
5
5
"context"
6
6
"encoding/json"
7
+
"errors"
7
8
"fmt"
8
9
"net/http"
9
10
"slices"
10
11
"time"
11
12
13
+
"github.com/bluesky-social/indigo/atproto/auth/oauth"
12
14
"github.com/go-chi/chi/v5"
13
15
"github.com/lestrrat-go/jwx/v2/jwk"
14
16
"github.com/posthog/posthog-go"
···
58
60
59
61
func (o *OAuth) callback(w http.ResponseWriter, r *http.Request) {
60
62
ctx := r.Context()
63
+
l := o.Logger.With("query", r.URL.Query())
61
64
62
65
sessData, err := o.ClientApp.ProcessCallback(ctx, r.URL.Query())
63
66
if err != nil {
64
-
http.Error(w, err.Error(), http.StatusInternalServerError)
67
+
var callbackErr *oauth.AuthRequestCallbackError
68
+
if errors.As(err, &callbackErr) {
69
+
l.Debug("callback error", "err", callbackErr)
70
+
http.Redirect(w, r, fmt.Sprintf("/login?error=%s", callbackErr.ErrorCode), http.StatusFound)
71
+
return
72
+
}
73
+
l.Error("failed to process callback", "err", err)
74
+
http.Redirect(w, r, "/login?error=oauth", http.StatusFound)
65
75
return
66
76
}
67
77
68
78
if err := o.SaveSession(w, r, sessData); err != nil {
69
-
http.Error(w, err.Error(), http.StatusInternalServerError)
79
+
l.Error("failed to save session", "data", sessData, "err", err)
80
+
http.Redirect(w, r, "/login?error=session", http.StatusFound)
70
81
return
71
82
}
72
83
+2
-1
appview/pages/pages.go
+2
-1
appview/pages/pages.go
+19
-2
appview/pages/templates/user/login.html
+19
-2
appview/pages/templates/user/login.html
···
13
13
<title>login · tangled</title>
14
14
</head>
15
15
<body class="flex items-center justify-center min-h-screen">
16
-
<main class="max-w-md px-6 -mt-4">
16
+
<main class="max-w-md px-7 mt-4">
17
17
<h1 class="flex place-content-center text-3xl font-semibold italic dark:text-white" >
18
18
{{ template "fragments/logotype" }}
19
19
</h1>
···
21
21
tightly-knit social coding.
22
22
</h2>
23
23
<form
24
-
class="mt-4 max-w-sm mx-auto"
24
+
class="mt-4"
25
25
hx-post="/login"
26
26
hx-swap="none"
27
27
hx-disabled-elt="#login-button"
···
56
56
<span>login</span>
57
57
</button>
58
58
</form>
59
+
{{ if .ErrorCode }}
60
+
<div class="flex gap-2 my-2 bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-3 py-2 text-red-500 dark:text-red-300">
61
+
<span class="py-1">{{ i "circle-alert" "w-4 h-4" }}</span>
62
+
<div>
63
+
<h5 class="font-medium">Login error</h5>
64
+
<p class="text-sm">
65
+
{{ if eq .ErrorCode "access_denied" }}
66
+
You have not authorized the app. Please try again
67
+
{{ else if eq .ErrorCode "session" }}
68
+
Server failed to create user session. Please try again
69
+
{{ else }}
70
+
Internal Server error. Please try again
71
+
</p>
72
+
{{ end }}
73
+
</div>
74
+
</div>
75
+
{{ end }}
59
76
<p class="text-sm text-gray-500">
60
77
Don't have an account? <a href="/signup" class="underline">Create an account</a> on Tangled now!
61
78
</p>
+2
appview/state/login.go
+2
appview/state/login.go
···
14
14
switch r.Method {
15
15
case http.MethodGet:
16
16
returnURL := r.URL.Query().Get("return_url")
17
+
errorCode := r.URL.Query().Get("error")
17
18
s.pages.Login(w, pages.LoginParams{
18
19
ReturnUrl: returnURL,
20
+
ErrorCode: errorCode,
19
21
})
20
22
case http.MethodPost:
21
23
handle := r.FormValue("handle")