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