this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

wire up session data persist callback

+51 -11
+11 -2
atproto/auth/oauth/cmd/oauth-web-demo/main.go
··· 256 256 return 257 257 } 258 258 259 - if err := oauthSess.RefreshTokens(ctx); err != nil { 259 + _, err = oauthSess.RefreshTokens(ctx) 260 + if err != nil { 260 261 http.Error(w, err.Error(), http.StatusBadRequest) 261 262 return 262 263 } ··· 266 267 } 267 268 268 269 func (s *Server) OAuthLogout(w http.ResponseWriter, r *http.Request) { 269 - // XXX: delete session from auth store 270 + 271 + // delete session from auth store 272 + did := s.currentSessionDID(r) 273 + if did != nil { 274 + if err := s.OAuth.Store.DeleteSession(r.Context(), *did); err != nil { 275 + slog.Error("failed to delete session", "did", did, "err", err) 276 + } 277 + } 270 278 271 279 // wipe all secure cookie session data 272 280 sess, _ := s.CookieStore.Get(r, "oauth-demo") ··· 276 284 http.Error(w, err.Error(), http.StatusInternalServerError) 277 285 return 278 286 } 287 + 279 288 slog.Info("logged out") 280 289 http.Redirect(w, r, "/", http.StatusFound) 281 290 }
+12 -2
atproto/auth/oauth/oauth.go
··· 162 162 Config: app.Config, 163 163 Data: sd, 164 164 } 165 - // XXX: configure token refresh callback 166 165 167 - // XXX: refactor this in to store layer? 166 + // configure callback for updating session data 167 + if app.Store != nil { 168 + sess.PersistSessionCallback = func(ctx context.Context, data *ClientSessionData) { 169 + slog.Debug("storing updated session data", "did", data.AccountDID) 170 + err := app.Store.SaveSession(ctx, *data) 171 + if err != nil { 172 + slog.Error("failed to store updated session data", "did", data.AccountDID, "err", err) 173 + } 174 + } 175 + } 176 + 177 + // XXX: refactor this in to ClientAuthStore layer? 168 178 priv, err := crypto.ParsePrivateMultibase(sd.DpopPrivateKeyMultibase) 169 179 if err != nil { 170 180 return nil, err
+28 -7
atproto/auth/oauth/session.go
··· 70 70 71 71 // Requests new tokens from auth server, and returns the new access token on success. 72 72 // 73 - // Internally takes a lock on session data around the entire refresh process, including retries. Persists data using PersistSessionCallback if configured. 73 + // Internally takes a lock on session data around the entire refresh process, including retries. Persists data using [ClientSession.PersistSessionCallback] if configured. 74 74 func (sess *ClientSession) RefreshTokens(ctx context.Context) (string, error) { 75 75 sess.lk.Lock() 76 76 defer sess.lk.Unlock() ··· 170 170 // persist updated data (tokens and possibly nonce) 171 171 if sess.PersistSessionCallback != nil { 172 172 sess.PersistSessionCallback(ctx, sess.Data) 173 + } else { 174 + slog.Warn("not saving updated session data", "did", sess.Data.AccountDID) 173 175 } 174 176 175 177 return sess.Data.AccessToken, nil ··· 242 244 return strings.Contains(hdr, "error=\"invalid_token\"") 243 245 } 244 246 247 + func (sess *ClientSession) GetHostAccessData() (accessToken string, dpopHostNonce string) { 248 + sess.lk.RLock() 249 + defer sess.lk.RUnlock() 250 + 251 + return sess.Data.AccessToken, sess.Data.DpopHostNonce 252 + } 253 + 254 + func (sess *ClientSession) UpdateHostDPoPNonce(ctx context.Context, nonce string) { 255 + sess.lk.Lock() 256 + defer sess.lk.Unlock() 257 + 258 + sess.Data.DpopHostNonce = nonce 259 + 260 + if sess.PersistSessionCallback != nil { 261 + sess.PersistSessionCallback(ctx, sess.Data) 262 + } else { 263 + slog.Warn("not saving updated host DPoP nonce", "did", sess.Data.AccountDID) 264 + } 265 + } 266 + 245 267 // Sends API request to OAuth Resource Server (PDS), using access token and DPoP. 246 268 // 247 269 // Automatically handles DPoP nonce updates and token refresh as needed, based on the response status code and `WWW-Authenticate` header. ··· 249 271 250 272 durl := dpopURL(req.URL) 251 273 252 - //accessToken, dpopNonce := sess.GetHostData() 253 - // XXX: fetch with mutex lock 254 - accessToken := sess.Data.AccessToken 255 - dpopNonce := sess.Data.DpopHostNonce 274 + accessToken, dpopNonce := sess.GetHostAccessData() 256 275 257 276 // this method may need to retry twice, once for DPoP nonce update and once for token refresh 258 277 var resp *http.Response ··· 284 303 if dpopNonceHdr == dpopNonce { 285 304 return nil, fmt.Errorf("OAuth PDS DPoP nonce failure, but no new nonce supplied") 286 305 } 287 - // XXX: persist new nonce value via callback 288 - sess.Data.DpopHostNonce = dpopNonceHdr 306 + 307 + // persist new nonce value via callback 308 + sess.UpdateHostDPoPNonce(req.Context(), dpopNonceHdr) 289 309 dpopNonce = dpopNonceHdr 310 + 290 311 // retry request 291 312 retry := req.Clone(req.Context()) 292 313 if req.GetBody != nil {