───────────────────────── RefreshTokenStorage ─────────────────────────
(ctx context.Context, signature, accessSignature string, request fosite.Requester)
| 353 | // ───────────────────────── RefreshTokenStorage ───────────────────────── |
| 354 | |
| 355 | func (s *Storage) CreateRefreshTokenSession(ctx context.Context, signature, accessSignature string, request fosite.Requester) error { |
| 356 | // accessSignature is intentionally ignored — RotateRefreshToken |
| 357 | // cascades via request_id (the fosite-managed grouping ID) which |
| 358 | // is also what RevokeAccessToken keys on. Storing the paired |
| 359 | // signature would just duplicate that linkage with no benefit. |
| 360 | _ = accessSignature |
| 361 | |
| 362 | raw, err := marshalRequest(request) |
| 363 | if err != nil { |
| 364 | return err |
| 365 | } |
| 366 | sess, _ := request.GetSession().(*Session) |
| 367 | userID := "" |
| 368 | if sess != nil { |
| 369 | userID = sess.UserID |
| 370 | } |
| 371 | // fosite signals "no expiry" by leaving the session ExpiresAt at |
| 372 | // zero (the RefreshTokenLifespan=-1 config path). Persist NULL in |
| 373 | // that case so the retention reaper — which must skip NULLs — keeps |
| 374 | // the row forever as the operator asked. Otherwise use the session |
| 375 | // value, which already reflects the configured lifetime. |
| 376 | // |
| 377 | // On configured-lifetime deployments, fosite's refresh strategy |
| 378 | // always sets a non-zero session expiry before this method is |
| 379 | // called; a zero value here is unambiguous opt-in. |
| 380 | var expiresAt *time.Time |
| 381 | if sess != nil { |
| 382 | if t := sess.GetExpiresAt(fosite.RefreshToken); !t.IsZero() { |
| 383 | expiresAt = &t |
| 384 | } |
| 385 | } |
| 386 | _, err = s.db(ctx).Exec(ctx, ` |
| 387 | INSERT INTO oauth_refresh_tokens |
| 388 | (signature, request_id, client_id, user_id, |
| 389 | request, requested_at, expires_at, active) |
| 390 | VALUES ($1, $2, $3, $4, $5, $6, $7, TRUE) |
| 391 | `, signature, request.GetID(), request.GetClient().GetID(), userID, |
| 392 | raw, request.GetRequestedAt(), expiresAt, |
| 393 | ) |
| 394 | return err |
| 395 | } |
| 396 | |
| 397 | func (s *Storage) GetRefreshTokenSession(ctx context.Context, signature string, session fosite.Session) (fosite.Requester, error) { |
| 398 | var raw []byte |