tangled
alpha
login
or
join now
lewis.moe
/
tangled-core
0
fork
atom
Monorepo for Tangled
0
fork
atom
overview
issues
1
pulls
pipelines
oauth: integrate multi-account into session management
lewis.moe
1 month ago
d10ddce1
44342ca2
+80
-6
2 changed files
expand all
collapse all
unified
split
appview
oauth
handler.go
oauth.go
+14
-2
appview/oauth/handler.go
···
55
55
ctx := r.Context()
56
56
l := o.Logger.With("query", r.URL.Query())
57
57
58
58
+
authReturn := o.GetAuthReturn(r)
59
59
+
_ = o.ClearAuthReturn(w, r)
60
60
+
58
61
sessData, err := o.ClientApp.ProcessCallback(ctx, r.URL.Query())
59
62
if err != nil {
60
63
var callbackErr *oauth.AuthRequestCallbackError
···
70
73
71
74
if err := o.SaveSession(w, r, sessData); err != nil {
72
75
l.Error("failed to save session", "data", sessData, "err", err)
73
73
-
http.Redirect(w, r, "/login?error=session", http.StatusFound)
76
76
+
errorCode := "session"
77
77
+
if errors.Is(err, ErrMaxAccountsReached) {
78
78
+
errorCode = "max_accounts"
79
79
+
}
80
80
+
http.Redirect(w, r, fmt.Sprintf("/login?error=%s", errorCode), http.StatusFound)
74
81
return
75
82
}
76
83
···
88
95
}
89
96
}
90
97
91
91
-
http.Redirect(w, r, "/", http.StatusFound)
98
98
+
redirectURL := "/"
99
99
+
if authReturn.ReturnURL != "" {
100
100
+
redirectURL = authReturn.ReturnURL
101
101
+
}
102
102
+
103
103
+
http.Redirect(w, r, redirectURL, http.StatusFound)
92
104
}
93
105
94
106
func (o *OAuth) addToDefaultSpindle(did string) {
+66
-4
appview/oauth/oauth.go
···
98
98
}
99
99
100
100
func (o *OAuth) SaveSession(w http.ResponseWriter, r *http.Request, sessData *oauth.ClientSessionData) error {
101
101
-
// first we save the did in the user session
102
101
userSession, err := o.SessStore.Get(r, SessionName)
103
102
if err != nil {
104
103
return err
···
108
107
userSession.Values[SessionPds] = sessData.HostURL
109
108
userSession.Values[SessionId] = sessData.SessionID
110
109
userSession.Values[SessionAuthenticated] = true
111
111
-
return userSession.Save(r, w)
110
110
+
111
111
+
if err := userSession.Save(r, w); err != nil {
112
112
+
return err
113
113
+
}
114
114
+
115
115
+
handle := ""
116
116
+
resolved, err := o.IdResolver.ResolveIdent(r.Context(), sessData.AccountDID.String())
117
117
+
if err == nil && resolved.Handle.String() != "" {
118
118
+
handle = resolved.Handle.String()
119
119
+
}
120
120
+
121
121
+
registry := o.GetAccounts(r)
122
122
+
if err := registry.AddAccount(sessData.AccountDID.String(), handle, sessData.SessionID); err != nil {
123
123
+
return err
124
124
+
}
125
125
+
return o.SaveAccounts(w, r, registry)
112
126
}
113
127
114
128
func (o *OAuth) ResumeSession(r *http.Request) (*oauth.ClientSession, error) {
···
163
177
return errors.Join(err1, err2)
164
178
}
165
179
180
180
+
func (o *OAuth) SwitchAccount(w http.ResponseWriter, r *http.Request, targetDid string) error {
181
181
+
registry := o.GetAccounts(r)
182
182
+
account := registry.FindAccount(targetDid)
183
183
+
if account == nil {
184
184
+
return fmt.Errorf("account not found in registry: %s", targetDid)
185
185
+
}
186
186
+
187
187
+
did, err := syntax.ParseDID(targetDid)
188
188
+
if err != nil {
189
189
+
return fmt.Errorf("invalid DID: %w", err)
190
190
+
}
191
191
+
192
192
+
sess, err := o.ClientApp.ResumeSession(r.Context(), did, account.SessionId)
193
193
+
if err != nil {
194
194
+
registry.RemoveAccount(targetDid)
195
195
+
_ = o.SaveAccounts(w, r, registry)
196
196
+
return fmt.Errorf("session expired for account: %w", err)
197
197
+
}
198
198
+
199
199
+
userSession, err := o.SessStore.Get(r, SessionName)
200
200
+
if err != nil {
201
201
+
return err
202
202
+
}
203
203
+
204
204
+
userSession.Values[SessionDid] = sess.Data.AccountDID.String()
205
205
+
userSession.Values[SessionPds] = sess.Data.HostURL
206
206
+
userSession.Values[SessionId] = sess.Data.SessionID
207
207
+
userSession.Values[SessionAuthenticated] = true
208
208
+
209
209
+
return userSession.Save(r, w)
210
210
+
}
211
211
+
212
212
+
func (o *OAuth) RemoveAccount(w http.ResponseWriter, r *http.Request, targetDid string) error {
213
213
+
registry := o.GetAccounts(r)
214
214
+
account := registry.FindAccount(targetDid)
215
215
+
if account == nil {
216
216
+
return nil
217
217
+
}
218
218
+
219
219
+
did, err := syntax.ParseDID(targetDid)
220
220
+
if err == nil {
221
221
+
_ = o.ClientApp.Logout(r.Context(), did, account.SessionId)
222
222
+
}
223
223
+
224
224
+
registry.RemoveAccount(targetDid)
225
225
+
return o.SaveAccounts(w, r, registry)
226
226
+
}
227
227
+
166
228
type User struct {
167
229
Did string
168
230
Pds string
···
181
243
}
182
244
183
245
func (o *OAuth) GetDid(r *http.Request) string {
184
184
-
if u := o.GetUser(r); u != nil {
185
185
-
return u.Did
246
246
+
if u := o.GetMultiAccountUser(r); u != nil {
247
247
+
return u.Did()
186
248
}
187
249
188
250
return ""