oauth: automatically clean up expired oauth state in db
This commit is contained in:
@@ -8,6 +8,9 @@
|
||||
- [x] move auth state stuff to database (out of cache)
|
||||
- [x] only generate a sign up link IF they click the link on the accounts page
|
||||
- [ ] get api key approved
|
||||
- [ ] automatically clean up access tokens and state when expired
|
||||
- [ ] access tokens
|
||||
- [ ] state
|
||||
- [?] Get new access token using refresh token flow
|
||||
- [ ] make a FK between the etsy_store_events table and etsy_users table (store_id columns don't match types)
|
||||
- [ ] Auth0
|
||||
@@ -15,9 +18,9 @@
|
||||
- [x] Get new access token using refresh token flow
|
||||
- [ ] test
|
||||
- [ ] Social connections login
|
||||
- [ ] automatically clean up access tokens and state when expired
|
||||
- [ ] access tokens
|
||||
- [ ] state
|
||||
- [x] automatically clean up access tokens and state when expired
|
||||
- [x] access tokens
|
||||
- [x] state
|
||||
- [ ] Complete this design document?
|
||||
- [ ] Complete defining this roadmap checklist
|
||||
- [ ] Website displaying an audit of store events
|
||||
|
||||
@@ -81,6 +81,24 @@ func New(ctx context.Context, db *pgxpool.Pool) (*Authenticator, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *Authenticator) RunBackgroundCleanup(ctx context.Context) error {
|
||||
for {
|
||||
if _, err := a.db.Exec(ctx, "DELETE FROM oauth_tokens WHERE expiry < NOW()"); err != nil {
|
||||
return fmt.Errorf("failed to delete all oauth_tokens rows that are expired: %w", err)
|
||||
}
|
||||
|
||||
if _, err := a.db.Exec(ctx, "DELETE FROM oauth_login_states WHERE expiration < NOW()"); err != nil {
|
||||
return fmt.Errorf("failed to delete all oauth_login_states rows that are expired: %w", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case <-time.After(time.Minute):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Exchange exchanges an auth code for an access token.
|
||||
func (a *Authenticator) Exchange(ctx context.Context, state, code string) (accessToken string, expiration time.Time, err error) {
|
||||
// validate state
|
||||
|
||||
@@ -48,13 +48,17 @@ func runApp(ctx context.Context) error {
|
||||
return fmt.Errorf("failed to initialize database connection pool: %w", err)
|
||||
}
|
||||
|
||||
// start http server
|
||||
// start background processes
|
||||
|
||||
auth, err := authentication.New(ctx, connPool)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to construct authenticator: %w", err)
|
||||
}
|
||||
|
||||
authErrCh := runAuthProcesses(ctx, auth)
|
||||
|
||||
// start http server
|
||||
|
||||
srvErrCh := runServer(ctx, connPool, auth)
|
||||
|
||||
// wait for interrupt signal or unrecoverable failure, then shutdown
|
||||
@@ -62,13 +66,24 @@ func runApp(ctx context.Context) error {
|
||||
osSignalCh := make(chan os.Signal, 1)
|
||||
signal.Notify(osSignalCh, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
var serverAlreadyShutdown bool
|
||||
var (
|
||||
alreadyShutdown struct {
|
||||
server bool
|
||||
authProcesses bool
|
||||
}
|
||||
)
|
||||
select {
|
||||
case s := <-osSignalCh:
|
||||
fmt.Println("application received shutdown signal:", s)
|
||||
fmt.Println("shutting down")
|
||||
case err := <-authErrCh:
|
||||
alreadyShutdown.authProcesses = true
|
||||
fmt.Println("auth processes shutdown unexpectedly")
|
||||
if err != nil {
|
||||
fmt.Println("auth processes encountered error:", err)
|
||||
}
|
||||
case err := <-srvErrCh:
|
||||
serverAlreadyShutdown = true
|
||||
alreadyShutdown.server = true
|
||||
fmt.Println("server shutdown unexpectedly")
|
||||
if err != nil {
|
||||
fmt.Println("server encountered error:", err)
|
||||
@@ -81,7 +96,14 @@ func runApp(ctx context.Context) error {
|
||||
|
||||
var errs []error
|
||||
|
||||
if !serverAlreadyShutdown {
|
||||
if !alreadyShutdown.authProcesses {
|
||||
if err := <-authErrCh; err != nil {
|
||||
errs = append(errs, fmt.Errorf("auth processes experienced an error: %w", err))
|
||||
}
|
||||
fmt.Println("auth processes shut down")
|
||||
}
|
||||
|
||||
if !alreadyShutdown.server {
|
||||
if err := <-srvErrCh; err != nil {
|
||||
errs = append(errs, fmt.Errorf("server experienced an error: %w", err))
|
||||
}
|
||||
@@ -91,6 +113,19 @@ func runApp(ctx context.Context) error {
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
func runAuthProcesses(ctx context.Context, auth *authentication.Authenticator) <-chan error {
|
||||
errCh := make(chan error, 1)
|
||||
go func() {
|
||||
defer close(errCh)
|
||||
|
||||
if err := auth.RunBackgroundCleanup(ctx); err != nil {
|
||||
errCh <- err
|
||||
}
|
||||
}()
|
||||
|
||||
return errCh
|
||||
}
|
||||
|
||||
func runServer(ctx context.Context, connPool *pgxpool.Pool, auth *authentication.Authenticator) <-chan error {
|
||||
srv := &http.Server{
|
||||
Addr: ":8082", // local
|
||||
|
||||
Reference in New Issue
Block a user