Repository: dexidp/dex
Pull request #3303 (2024-01-25 13:22:54)

feat: add TLS versions configuration
#### Overview

Add configuration options for TLSMinVersion and TLSMaxVersion.

This enables configuring specific TLS versions to accept. That allows use-cases such as setting TLS 1.3 as minimum version (disables TLS 1.2), or enforcing TLS 1.2 only (disables TLS 1.3) for easier debugging of secure connections.

Default functionality of Go TLS is to allow TLS 1.2 and TLS 1.3 and have client and server negotiate. (Except in Dex 2.37.0 where TLS 1.0 to TLS 1.3 were always enabled).

`serve.go` doesn't have any unit tests, so didn't add any. Unit tests are added for `config.go`.

#### Special notes for your reviewer

This can be tested with `sslyze` for example:

1. Generate certs `cd examples/k8s; ./gencert.sh`
2. `cp config.dev.yaml config.yaml`
3. Add following under `web:`
```yaml
  https: 127.0.0.1:5554
  tlsCert: examples/k8s/ssl/cert.pem
  tlsKey: examples/k8s/ssl/key.pem
  tlsMinVersion: 1.3
  tlsMaxVersion: 1.3
```
4. Run dex
```bash
gh pr checkout <PR number>
rm -f bin/dex; make; bin/dex serve config.yaml
``` 
5. `pip3 install sslyze` (use virtualenv etc as needed)
6. `sslyze 127.0.0.1:5554`  or use `openssl`  if you like
7. Check the report and see TLS 1.3 is the only one enabled, TLS 1.2 is refused



Patch:
diff --git a/cmd/dex/config.go b/cmd/dex/config.go
index dd91bf1e..9c5c1039 100644
--- a/cmd/dex/config.go
+++ b/cmd/dex/config.go
@@ -64,10 +64,16 @@ func (c Config) Validate() error {
 		{c.Web.HTTP == "" && c.Web.HTTPS == "", "must supply a HTTP/HTTPS  address to listen on"},
 		{c.Web.HTTPS != "" && c.Web.TLSCert == "", "no cert specified for HTTPS"},
 		{c.Web.HTTPS != "" && c.Web.TLSKey == "", "no private key specified for HTTPS"},
+		{c.Web.TLSMinVersion != "" && c.Web.TLSMinVersion != "1.2" && c.Web.TLSMinVersion != "1.3", "supported TLS versions are: 1.2, 1.3"},
+		{c.Web.TLSMaxVersion != "" && c.Web.TLSMaxVersion != "1.2" && c.Web.TLSMaxVersion != "1.3", "supported TLS versions are: 1.2, 1.3"},
+		{c.Web.TLSMaxVersion != "" && c.Web.TLSMinVersion != "" && c.Web.TLSMinVersion > c.Web.TLSMaxVersion, "TLSMinVersion greater than TLSMaxVersion"},
 		{c.GRPC.TLSCert != "" && c.GRPC.Addr == "", "no address specified for gRPC"},
 		{c.GRPC.TLSKey != "" && c.GRPC.Addr == "", "no address specified for gRPC"},
 		{(c.GRPC.TLSCert == "") != (c.GRPC.TLSKey == ""), "must specific both a gRPC TLS cert and key"},
 		{c.GRPC.TLSCert == "" && c.GRPC.TLSClientCA != "", "cannot specify gRPC TLS client CA without a gRPC TLS cert"},
+		{c.GRPC.TLSMinVersion != "" && c.GRPC.TLSMinVersion != "1.2" && c.GRPC.TLSMinVersion != "1.3", "supported TLS versions are: 1.2, 1.3"},
+		{c.GRPC.TLSMaxVersion != "" && c.GRPC.TLSMaxVersion != "1.2" && c.GRPC.TLSMaxVersion != "1.3", "supported TLS versions are: 1.2, 1.3"},
+		{c.GRPC.TLSMaxVersion != "" && c.GRPC.TLSMinVersion != "" && c.GRPC.TLSMinVersion > c.GRPC.TLSMaxVersion, "TLSMinVersion greater than TLSMaxVersion"},
 	}
 
 	var checkErrors []string
@@ -149,6 +155,8 @@ type Web struct {
 	HTTPS          string   `json:"https"`
 	TLSCert        string   `json:"tlsCert"`
 	TLSKey         string   `json:"tlsKey"`
+	TLSMinVersion  string   `json:"tlsMinVersion"`
+	TLSMaxVersion  string   `json:"tlsMaxVersion"`
 	AllowedOrigins []string `json:"allowedOrigins"`
 	AllowedHeaders []string `json:"allowedHeaders"`
 }
@@ -163,11 +171,13 @@ type Telemetry struct {
 // GRPC is the config for the gRPC API.
 type GRPC struct {
 	// The port to listen on.
-	Addr        string `json:"addr"`
-	TLSCert     string `json:"tlsCert"`
-	TLSKey      string `json:"tlsKey"`
-	TLSClientCA string `json:"tlsClientCA"`
-	Reflection  bool   `json:"reflection"`
+	Addr          string `json:"addr"`
+	TLSCert       string `json:"tlsCert"`
+	TLSKey        string `json:"tlsKey"`
+	TLSClientCA   string `json:"tlsClientCA"`
+	TLSMinVersion string `json:"tlsMinVersion"`
+	TLSMaxVersion string `json:"tlsMaxVersion"`
+	Reflection    bool   `json:"reflection"`
 }
 
 // Storage holds app's storage configuration.
diff --git a/cmd/dex/serve.go b/cmd/dex/serve.go
index 54767494..3494443e 100644
--- a/cmd/dex/serve.go
+++ b/cmd/dex/serve.go
@@ -145,9 +145,23 @@ func runServe(options serveOptions) error {
 		tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
 	}
 
+	allowedTLSVersions := map[string]int{
+		"1.2": tls.VersionTLS12,
+		"1.3": tls.VersionTLS13,
+	}
+
 	if c.GRPC.TLSCert != "" {
+		tlsMinVersion := tls.VersionTLS12
+		if c.GRPC.TLSMinVersion != "" {
+			tlsMinVersion = allowedTLSVersions[c.GRPC.TLSMinVersion]
+		}
+		tlsMaxVersion := 0 // default for max is whatever Go defaults to
+		if c.GRPC.TLSMaxVersion != "" {
+			tlsMaxVersion = allowedTLSVersions[c.GRPC.TLSMaxVersion]
+		}
 		baseTLSConfig := &tls.Config{
-			MinVersion:               tls.VersionTLS12,
+			MinVersion:               uint16(tlsMinVersion),
+			MaxVersion:               uint16(tlsMaxVersion),
 			CipherSuites:             allowedTLSCiphers,
 			PreferServerCipherSuites: true,
 		}
@@ -422,8 +436,18 @@ func runServe(options serveOptions) error {
 			return fmt.Errorf("listening (%s) on %s: %v", name, c.Web.HTTPS, err)
 		}
 
+		tlsMinVersion := tls.VersionTLS12
+		if c.Web.TLSMinVersion != "" {
+			tlsMinVersion = allowedTLSVersions[c.Web.TLSMinVersion]
+		}
+		tlsMaxVersion := 0 // default for max is whatever Go defaults to
+		if c.Web.TLSMaxVersion != "" {
+			tlsMaxVersion = allowedTLSVersions[c.Web.TLSMaxVersion]
+		}
+
 		baseTLSConfig := &tls.Config{
-			MinVersion:               tls.VersionTLS12,
+			MinVersion:               uint16(tlsMinVersion),
+			MaxVersion:               uint16(tlsMaxVersion),
 			CipherSuites:             allowedTLSCiphers,
 			PreferServerCipherSuites: true,
 		}
diff --git a/config.yaml.dist b/config.yaml.dist
index 12d9b927..b7e1410f 100644
--- a/config.yaml.dist
+++ b/config.yaml.dist
@@ -55,6 +55,8 @@ web:
   # https: 127.0.0.1:5554
   # tlsCert: /etc/dex/tls.crt
   # tlsKey: /etc/dex/tls.key
+  # tlsMinVersion: 1.2
+  # tlsMaxVersion: 1.3
 
 # Dex UI configuration
 # frontend:
diff --git a/server/api.go b/server/api.go
index c0eacb8f..d8ca1831 100644
--- a/server/api.go
+++ b/server/api.go
@@ -85,7 +85,7 @@ func (d dexAPI) CreateClient(ctx context.Context, req *api.CreateClientReq) (*ap
 		Name:         req.Client.Name,
 		LogoURL:      req.Client.LogoUrl,
 	}
-	if err := d.s.CreateClient(ctx, c); err != nil {
+	if err := d.s.CreateClient(c); err != nil {
 		if err == storage.ErrAlreadyExists {
 			return &api.CreateClientResp{AlreadyExists: true}, nil
 		}
@@ -177,7 +177,7 @@ func (d dexAPI) CreatePassword(ctx context.Context, req *api.CreatePasswordReq)
 		Username: req.Password.Username,
 		UserID:   req.Password.UserId,
 	}
-	if err := d.s.CreatePassword(ctx, p); err != nil {
+	if err := d.s.CreatePassword(p); err != nil {
 		if err == storage.ErrAlreadyExists {
 			return &api.CreatePasswordResp{AlreadyExists: true}, nil
 		}
diff --git a/server/deviceflowhandlers.go b/server/deviceflowhandlers.go
index 5683e944..95fed3b3 100644
--- a/server/deviceflowhandlers.go
+++ b/server/deviceflowhandlers.go
@@ -58,7 +58,6 @@ func (s *Server) handleDeviceExchange(w http.ResponseWriter, r *http.Request) {
 }
 
 func (s *Server) handleDeviceCode(w http.ResponseWriter, r *http.Request) {
-	ctx := r.Context()
 	pollIntervalSeconds := 5
 
 	switch r.Method {
@@ -107,7 +106,7 @@ func (s *Server) handleDeviceCode(w http.ResponseWriter, r *http.Request) {
 			Expiry:       expireTime,
 		}
 
-		if err := s.storage.CreateDeviceRequest(ctx, deviceReq); err != nil {
+		if err := s.storage.CreateDeviceRequest(deviceReq); err != nil {
 			s.logger.Errorf("Failed to store device request; %v", err)
 			s.tokenErrHelper(w, errInvalidRequest, "", http.StatusInternalServerError)
 			return
@@ -126,7 +125,7 @@ func (s *Server) handleDeviceCode(w http.ResponseWriter, r *http.Request) {
 			},
 		}
 
-		if err := s.storage.CreateDeviceToken(ctx, deviceToken); err != nil {
+		if err := s.storage.CreateDeviceToken(deviceToken); err != nil {
 			s.logger.Errorf("Failed to store device token %v", err)
 			s.tokenErrHelper(w, errInvalidRequest, "", http.StatusInternalServerError)
 			return
@@ -281,7 +280,6 @@ func (s *Server) handleDeviceToken(w http.ResponseWriter, r *http.Request) {
 }
 
 func (s *Server) handleDeviceCallback(w http.ResponseWriter, r *http.Request) {
-	ctx := r.Context()
 	switch r.Method {
 	case http.MethodGet:
 		userCode := r.FormValue("state")
@@ -338,7 +336,7 @@ func (s *Server) handleDeviceCallback(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 
-		resp, err := s.exchangeAuthCode(ctx, w, authCode, client)
+		resp, err := s.exchangeAuthCode(w, authCode, client)
 		if err != nil {
 			s.logger.Errorf("Could not exchange auth code for client %q: %v", deviceReq.ClientID, err)
 			s.renderError(r, w, http.StatusInternalServerError, "Failed to exchange auth code.")
diff --git a/server/handlers.go b/server/handlers.go
index 58366a88..08a60d48 100644
--- a/server/handlers.go
+++ b/server/handlers.go
@@ -1,7 +1,6 @@
 package server
 
 import (
-	"context"
 	"crypto/hmac"
 	"crypto/sha256"
 	"crypto/subtle"
@@ -188,7 +187,6 @@ func (s *Server) handleAuthorization(w http.ResponseWriter, r *http.Request) {
 }
 
 func (s *Server) handleConnectorLogin(w http.ResponseWriter, r *http.Request) {
-	ctx := r.Context()
 	authReq, err := s.parseAuthorizationRequest(r)
 	if err != nil {
 		s.logger.Errorf("Failed to parse authorization request: %v", err)
@@ -231,7 +229,7 @@ func (s *Server) handleConnectorLogin(w http.ResponseWriter, r *http.Request) {
 
 	// Actually create the auth request
 	authReq.Expiry = s.now().Add(s.authRequestsValidFor)
-	if err := s.storage.CreateAuthRequest(ctx, *authReq); err != nil {
+	if err := s.storage.CreateAuthRequest(*authReq); err != nil {
 		s.logger.Errorf("Failed to create authorization request: %v", err)
 		s.renderError(r, w, http.StatusInternalServerError, "Failed to connect to the database.")
 		return
@@ -307,7 +305,6 @@ func (s *Server) handleConnectorLogin(w http.ResponseWriter, r *http.Request) {
 }
 
 func (s *Server) handlePasswordLogin(w http.ResponseWriter, r *http.Request) {
-	ctx := r.Context()
 	authID := r.URL.Query().Get("state")
 	if authID == "" {
 		s.renderError(r, w, http.StatusBadRequest, "User session error.")
@@ -363,7 +360,7 @@ func (s *Server) handlePasswordLogin(w http.ResponseWriter, r *http.Request) {
 		password := r.FormValue("password")
 		scopes := parseScopes(authReq.Scopes)
 
-		identity, ok, err := pwConn.Login(ctx, scopes, username, password)
+		identity, ok, err := pwConn.Login(r.Context(), scopes, username, password)
 		if err != nil {
 			s.logger.Errorf("Failed to login user: %v", err)
 			s.renderError(r, w, http.StatusInternalServerError, fmt.Sprintf("Login error: %v", err))
@@ -375,7 +372,7 @@ func (s *Server) handlePasswordLogin(w http.ResponseWriter, r *http.Request) {
 			}
 			return
 		}
-		redirectURL, canSkipApproval, err := s.finalizeLogin(ctx, identity, authReq, conn.Connector)
+		redirectURL, canSkipApproval, err := s.finalizeLogin(identity, authReq, conn.Connector)
 		if err != nil {
 			s.logger.Errorf("Failed to finalize login: %v", err)
 			s.renderError(r, w, http.StatusInternalServerError, "Login error.")
@@ -400,7 +397,6 @@ func (s *Server) handlePasswordLogin(w http.ResponseWriter, r *http.Request) {
 }
 
 func (s *Server) handleConnectorCallback(w http.ResponseWriter, r *http.Request) {
-	ctx := r.Context()
 	var authID string
 	switch r.Method {
 	case http.MethodGet: // OAuth2 callback
@@ -475,7 +471,7 @@ func (s *Server) handleConnectorCallback(w http.ResponseWriter, r *http.Request)
 		return
 	}
 
-	redirectURL, canSkipApproval, err := s.finalizeLogin(ctx, identity, authReq, conn.Connector)
+	redirectURL, canSkipApproval, err := s.finalizeLogin(identity, authReq, conn.Connector)
 	if err != nil {
 		s.logger.Errorf("Failed to finalize login: %v", err)
 		s.renderError(r, w, http.StatusInternalServerError, "Login error.")
@@ -498,7 +494,7 @@ func (s *Server) handleConnectorCallback(w http.ResponseWriter, r *http.Request)
 
 // finalizeLogin associates the user's identity with the current AuthRequest, then returns
 // the approval page's path.
-func (s *Server) finalizeLogin(ctx context.Context, identity connector.Identity, authReq storage.AuthRequest, conn connector.Connector) (string, bool, error) {
+func (s *Server) finalizeLogin(identity connector.Identity, authReq storage.AuthRequest, conn connector.Connector) (string, bool, error) {
 	claims := storage.Claims{
 		UserID:            identity.UserID,
 		Username:          identity.Username,
@@ -570,7 +566,7 @@ func (s *Server) finalizeLogin(ctx context.Context, identity connector.Identity,
 
 		// Create a new OfflineSession object for the user and add a reference object for
 		// the newly received refreshtoken.
-		if err := s.storage.CreateOfflineSessions(ctx, offlineSessions); err != nil {
+		if err := s.storage.CreateOfflineSessions(offlineSessions); err != nil {
 			s.logger.Errorf("failed to create offline session: %v", err)
 			return "", false, err
 		}
@@ -653,7 +649,6 @@ func (s *Server) handleApproval(w http.ResponseWriter, r *http.Request) {
 }
 
 func (s *Server) sendCodeResponse(w http.ResponseWriter, r *http.Request, authReq storage.AuthRequest) {
-	ctx := r.Context()
 	if s.now().After(authReq.Expiry) {
 		s.renderError(r, w, http.StatusBadRequest, "User session has expired.")
 		return
@@ -706,7 +701,7 @@ func (s *Server) sendCodeResponse(w http.ResponseWriter, r *http.Request, authRe
 				ConnectorData: authReq.ConnectorData,
 				PKCE:          authReq.PKCE,
 			}
-			if err := s.storage.CreateAuthCode(ctx, code); err != nil {
+			if err := s.storage.CreateAuthCode(code); err != nil {
 				s.logger.Errorf("Failed to create auth code: %v", err)
 				s.renderError(r, w, http.StatusInternalServerError, "Internal server error.")
 				return
@@ -881,7 +876,6 @@ func (s *Server) calculateCodeChallenge(codeVerifier, codeChallengeMethod string
 
 // handle an access token request https://tools.ietf.org/html/rfc6749#section-4.1.3
 func (s *Server) handleAuthCode(w http.ResponseWriter, r *http.Request, client storage.Client) {
-	ctx := r.Context()
 	code := r.PostFormValue("code")
 	redirectURI := r.PostFormValue("redirect_uri")
 
@@ -932,7 +926,7 @@ func (s *Server) handleAuthCode(w http.ResponseWriter, r *http.Request, client s
 		return
 	}
 
-	tokenResponse, err := s.exchangeAuthCode(ctx, w, authCode, client)
+	tokenResponse, err := s.exchangeAuthCode(w, authCode, client)
 	if err != nil {
 		s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
 		return
@@ -940,7 +934,7 @@ func (s *Server) handleAuthCode(w http.ResponseWriter, r *http.Request, client s
 	s.writeAccessToken(w, tokenResponse)
 }
 
-func (s *Server) exchangeAuthCode(ctx context.Context, w http.ResponseWriter, authCode storage.AuthCode, client storage.Client) (*accessTokenResponse, error) {
+func (s *Server) exchangeAuthCode(w http.ResponseWriter, authCode storage.AuthCode, client storage.Client) (*accessTokenResponse, error) {
 	accessToken, _, err := s.newAccessToken(client.ID, authCode.Claims, authCode.Scopes, authCode.Nonce, authCode.ConnectorID)
 	if err != nil {
 		s.logger.Errorf("failed to create new access token: %v", err)
@@ -1008,7 +1002,7 @@ func (s *Server) exchangeAuthCode(ctx context.Context, w http.ResponseWriter, au
 			return nil, err
 		}
 
-		if err := s.storage.CreateRefresh(ctx, refresh); err != nil {
+		if err := s.storage.CreateRefresh(refresh); err != nil {
 			s.logger.Errorf("failed to create refresh token: %v", err)
 			s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
 			return nil, err
@@ -1053,7 +1047,7 @@ func (s *Server) exchangeAuthCode(ctx context.Context, w http.ResponseWriter, au
 
 			// Create a new OfflineSession object for the user and add a reference object for
 			// the newly received refreshtoken.
-			if err := s.storage.CreateOfflineSessions(ctx, offlineSessions); err != nil {
+			if err := s.storage.CreateOfflineSessions(offlineSessions); err != nil {
 				s.logger.Errorf("failed to create offline session: %v", err)
 				s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
 				deleteToken = true
@@ -1086,7 +1080,6 @@ func (s *Server) exchangeAuthCode(ctx context.Context, w http.ResponseWriter, au
 }
 
 func (s *Server) handleUserInfo(w http.ResponseWriter, r *http.Request) {
-	ctx := r.Context()
 	const prefix = "Bearer "
 
 	auth := r.Header.Get("authorization")
@@ -1098,7 +1091,7 @@ func (s *Server) handleUserInfo(w http.ResponseWriter, r *http.Request) {
 	rawIDToken := auth[len(prefix):]
 
 	verifier := oidc.NewVerifier(s.issuerURL.String(), &storageKeySet{s.storage}, &oidc.Config{SkipClientIDCheck: true})
-	idToken, err := verifier.Verify(ctx, rawIDToken)
+	idToken, err := verifier.Verify(r.Context(), rawIDToken)
 	if err != nil {
 		s.tokenErrHelper(w, errAccessDenied, err.Error(), http.StatusForbidden)
 		return
@@ -1115,7 +1108,6 @@ func (s *Server) handleUserInfo(w http.ResponseWriter, r *http.Request) {
 }
 
 func (s *Server) handlePasswordGrant(w http.ResponseWriter, r *http.Request, client storage.Client) {
-	ctx := r.Context()
 	// Parse the fields
 	if err := r.ParseForm(); err != nil {
 		s.tokenErrHelper(w, errInvalidRequest, "Couldn't parse data", http.StatusBadRequest)
@@ -1185,7 +1177,7 @@ func (s *Server) handlePasswordGrant(w http.ResponseWriter, r *http.Request, cli
 	// Login
 	username := q.Get("username")
 	password := q.Get("password")
-	identity, ok, err := passwordConnector.Login(ctx, parseScopes(scopes), username, password)
+	identity, ok, err := passwordConnector.Login(r.Context(), parseScopes(scopes), username, password)
 	if err != nil {
 		s.logger.Errorf("Failed to login user: %v", err)
 		s.tokenErrHelper(w, errInvalidRequest, "Could not login user", http.StatusBadRequest)
@@ -1260,7 +1252,7 @@ func (s *Server) handlePasswordGrant(w http.ResponseWriter, r *http.Request, cli
 			return
 		}
 
-		if err := s.storage.CreateRefresh(ctx, refresh); err != nil {
+		if err := s.storage.CreateRefresh(refresh); err != nil {
 			s.logger.Errorf("failed to create refresh token: %v", err)
 			s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
 			return
@@ -1306,7 +1298,7 @@ func (s *Server) handlePasswordGrant(w http.ResponseWriter, r *http.Request, cli
 
 			// Create a new OfflineSession object for the user and add a reference object for
 			// the newly received refreshtoken.
-			if err := s.storage.CreateOfflineSessions(ctx, offlineSessions); err != nil {
+			if err := s.storage.CreateOfflineSessions(offlineSessions); err != nil {
 				s.logger.Errorf("failed to create offline session: %v", err)
 				s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
 				deleteToken = true
diff --git a/storage/conformance/conformance.go b/storage/conformance/conformance.go
index 6c2cb2e4..2f791cde 100644
--- a/storage/conformance/conformance.go
+++ b/storage/conformance/conformance.go
@@ -2,7 +2,6 @@
 package conformance
 
 import (
-	"context"
 	"reflect"
 	"sort"
 	"testing"
@@ -81,7 +80,6 @@ func mustBeErrAlreadyExists(t *testing.T, kind string, err error) {
 }
 
 func testAuthRequestCRUD(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	codeChallenge := storage.PKCE{
 		CodeChallenge:       "code_challenge_test",
 		CodeChallengeMethod: "plain",
@@ -113,12 +111,12 @@ func testAuthRequestCRUD(t *testing.T, s storage.Storage) {
 
 	identity := storage.Claims{Email: "foobar"}
 
-	if err := s.CreateAuthRequest(ctx, a1); err != nil {
+	if err := s.CreateAuthRequest(a1); err != nil {
 		t.Fatalf("failed creating auth request: %v", err)
 	}
 
 	// Attempt to create same AuthRequest twice.
-	err := s.CreateAuthRequest(ctx, a1)
+	err := s.CreateAuthRequest(a1)
 	mustBeErrAlreadyExists(t, "auth request", err)
 
 	a2 := storage.AuthRequest{
@@ -144,7 +142,7 @@ func testAuthRequestCRUD(t *testing.T, s storage.Storage) {
 		HMACKey: []byte("hmac_key"),
 	}
 
-	if err := s.CreateAuthRequest(ctx, a2); err != nil {
+	if err := s.CreateAuthRequest(a2); err != nil {
 		t.Fatalf("failed creating auth request: %v", err)
 	}
 
@@ -181,7 +179,6 @@ func testAuthRequestCRUD(t *testing.T, s storage.Storage) {
 }
 
 func testAuthCodeCRUD(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	a1 := storage.AuthCode{
 		ID:            storage.NewID(),
 		ClientID:      "client1",
@@ -204,7 +201,7 @@ func testAuthCodeCRUD(t *testing.T, s storage.Storage) {
 		},
 	}
 
-	if err := s.CreateAuthCode(ctx, a1); err != nil {
+	if err := s.CreateAuthCode(a1); err != nil {
 		t.Fatalf("failed creating auth code: %v", err)
 	}
 
@@ -227,10 +224,10 @@ func testAuthCodeCRUD(t *testing.T, s storage.Storage) {
 	}
 
 	// Attempt to create same AuthCode twice.
-	err := s.CreateAuthCode(ctx, a1)
+	err := s.CreateAuthCode(a1)
 	mustBeErrAlreadyExists(t, "auth code", err)
 
-	if err := s.CreateAuthCode(ctx, a2); err != nil {
+	if err := s.CreateAuthCode(a2); err != nil {
 		t.Fatalf("failed creating auth code: %v", err)
 	}
 
@@ -259,7 +256,6 @@ func testAuthCodeCRUD(t *testing.T, s storage.Storage) {
 }
 
 func testClientCRUD(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	id1 := storage.NewID()
 	c1 := storage.Client{
 		ID:           id1,
@@ -271,12 +267,12 @@ func testClientCRUD(t *testing.T, s storage.Storage) {
 	err := s.DeleteClient(id1)
 	mustBeErrNotFound(t, "client", err)
 
-	if err := s.CreateClient(ctx, c1); err != nil {
+	if err := s.CreateClient(c1); err != nil {
 		t.Fatalf("create client: %v", err)
 	}
 
 	// Attempt to create same Client twice.
-	err = s.CreateClient(ctx, c1)
+	err = s.CreateClient(c1)
 	mustBeErrAlreadyExists(t, "client", err)
 
 	id2 := storage.NewID()
@@ -288,7 +284,7 @@ func testClientCRUD(t *testing.T, s storage.Storage) {
 		LogoURL:      "https://goo.gl/JIyzIC",
 	}
 
-	if err := s.CreateClient(ctx, c2); err != nil {
+	if err := s.CreateClient(c2); err != nil {
 		t.Fatalf("create client: %v", err)
 	}
 
@@ -329,7 +325,6 @@ func testClientCRUD(t *testing.T, s storage.Storage) {
 }
 
 func testRefreshTokenCRUD(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	id := storage.NewID()
 	refresh := storage.RefreshToken{
 		ID:            id,
@@ -350,12 +345,12 @@ func testRefreshTokenCRUD(t *testing.T, s storage.Storage) {
 		},
 		ConnectorData: []byte(`{"some":"data"}`),
 	}
-	if err := s.CreateRefresh(ctx, refresh); err != nil {
+	if err := s.CreateRefresh(refresh); err != nil {
 		t.Fatalf("create refresh token: %v", err)
 	}
 
 	// Attempt to create same Refresh Token twice.
-	err := s.CreateRefresh(ctx, refresh)
+	err := s.CreateRefresh(refresh)
 	mustBeErrAlreadyExists(t, "refresh token", err)
 
 	getAndCompare := func(id string, want storage.RefreshToken) {
@@ -406,7 +401,7 @@ func testRefreshTokenCRUD(t *testing.T, s storage.Storage) {
 		ConnectorData: []byte(`{"some":"data"}`),
 	}
 
-	if err := s.CreateRefresh(ctx, refresh2); err != nil {
+	if err := s.CreateRefresh(refresh2); err != nil {
 		t.Fatalf("create second refresh token: %v", err)
 	}
 
@@ -448,7 +443,6 @@ func (n byEmail) Less(i, j int) bool { return n[i].Email < n[j].Email }
 func (n byEmail) Swap(i, j int)      { n[i], n[j] = n[j], n[i] }
 
 func testPasswordCRUD(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	// Use bcrypt.MinCost to keep the tests short.
 	passwordHash1, err := bcrypt.GenerateFromPassword([]byte("secret"), bcrypt.MinCost)
 	if err != nil {
@@ -461,12 +455,12 @@ func testPasswordCRUD(t *testing.T, s storage.Storage) {
 		Username: "jane",
 		UserID:   "foobar",
 	}
-	if err := s.CreatePassword(ctx, password1); err != nil {
+	if err := s.CreatePassword(password1); err != nil {
 		t.Fatalf("create password token: %v", err)
 	}
 
 	// Attempt to create same Password twice.
-	err = s.CreatePassword(ctx, password1)
+	err = s.CreatePassword(password1)
 	mustBeErrAlreadyExists(t, "password", err)
 
 	passwordHash2, err := bcrypt.GenerateFromPassword([]byte("password"), bcrypt.MinCost)
@@ -480,7 +474,7 @@ func testPasswordCRUD(t *testing.T, s storage.Storage) {
 		Username: "john",
 		UserID:   "barfoo",
 	}
-	if err := s.CreatePassword(ctx, password2); err != nil {
+	if err := s.CreatePassword(password2); err != nil {
 		t.Fatalf("create password token: %v", err)
 	}
 
@@ -539,7 +533,6 @@ func testPasswordCRUD(t *testing.T, s storage.Storage) {
 }
 
 func testOfflineSessionCRUD(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	userID1 := storage.NewID()
 	session1 := storage.OfflineSessions{
 		UserID:        userID1,
@@ -550,12 +543,12 @@ func testOfflineSessionCRUD(t *testing.T, s storage.Storage) {
 
 	// Creating an OfflineSession with an empty Refresh list to ensure that
 	// an empty map is translated as expected by the storage.
-	if err := s.CreateOfflineSessions(ctx, session1); err != nil {
+	if err := s.CreateOfflineSessions(session1); err != nil {
 		t.Fatalf("create offline session with UserID = %s: %v", session1.UserID, err)
 	}
 
 	// Attempt to create same OfflineSession twice.
-	err := s.CreateOfflineSessions(ctx, session1)
+	err := s.CreateOfflineSessions(session1)
 	mustBeErrAlreadyExists(t, "offline session", err)
 
 	userID2 := storage.NewID()
@@ -566,7 +559,7 @@ func testOfflineSessionCRUD(t *testing.T, s storage.Storage) {
 		ConnectorData: []byte(`{"some":"data"}`),
 	}
 
-	if err := s.CreateOfflineSessions(ctx, session2); err != nil {
+	if err := s.CreateOfflineSessions(session2); err != nil {
 		t.Fatalf("create offline session with UserID = %s: %v", session2.UserID, err)
 	}
 
@@ -614,7 +607,6 @@ func testOfflineSessionCRUD(t *testing.T, s storage.Storage) {
 }
 
 func testConnectorCRUD(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	id1 := storage.NewID()
 	config1 := []byte(`{"issuer": "https://accounts.google.com"}`)
 	c1 := storage.Connector{
@@ -624,12 +616,12 @@ func testConnectorCRUD(t *testing.T, s storage.Storage) {
 		Config: config1,
 	}
 
-	if err := s.CreateConnector(ctx, c1); err != nil {
+	if err := s.CreateConnector(c1); err != nil {
 		t.Fatalf("create connector with ID = %s: %v", c1.ID, err)
 	}
 
 	// Attempt to create same Connector twice.
-	err := s.CreateConnector(ctx, c1)
+	err := s.CreateConnector(c1)
 	mustBeErrAlreadyExists(t, "connector", err)
 
 	id2 := storage.NewID()
@@ -641,7 +633,7 @@ func testConnectorCRUD(t *testing.T, s storage.Storage) {
 		Config: config2,
 	}
 
-	if err := s.CreateConnector(ctx, c2); err != nil {
+	if err := s.CreateConnector(c2); err != nil {
 		t.Fatalf("create connector with ID = %s: %v", c2.ID, err)
 	}
 
@@ -752,7 +744,6 @@ func testKeysCRUD(t *testing.T, s storage.Storage) {
 }
 
 func testGC(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	est, err := time.LoadLocation("America/New_York")
 	if err != nil {
 		t.Fatal(err)
@@ -781,7 +772,7 @@ func testGC(t *testing.T, s storage.Storage) {
 		},
 	}
 
-	if err := s.CreateAuthCode(ctx, c); err != nil {
+	if err := s.CreateAuthCode(c); err != nil {
 		t.Fatalf("failed creating auth code: %v", err)
 	}
 
@@ -832,7 +823,7 @@ func testGC(t *testing.T, s storage.Storage) {
 		HMACKey: []byte("hmac_key"),
 	}
 
-	if err := s.CreateAuthRequest(ctx, a); err != nil {
+	if err := s.CreateAuthRequest(a); err != nil {
 		t.Fatalf("failed creating auth request: %v", err)
 	}
 
@@ -869,7 +860,7 @@ func testGC(t *testing.T, s storage.Storage) {
 		Expiry:       expiry,
 	}
 
-	if err := s.CreateDeviceRequest(ctx, d); err != nil {
+	if err := s.CreateDeviceRequest(d); err != nil {
 		t.Fatalf("failed creating device request: %v", err)
 	}
 
@@ -909,7 +900,7 @@ func testGC(t *testing.T, s storage.Storage) {
 		},
 	}
 
-	if err := s.CreateDeviceToken(ctx, dt); err != nil {
+	if err := s.CreateDeviceToken(dt); err != nil {
 		t.Fatalf("failed creating device token: %v", err)
 	}
 
@@ -940,7 +931,6 @@ func testGC(t *testing.T, s storage.Storage) {
 // testTimezones tests that backends either fully support timezones or
 // do the correct standardization.
 func testTimezones(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	est, err := time.LoadLocation("America/New_York")
 	if err != nil {
 		t.Fatal(err)
@@ -966,7 +956,7 @@ func testTimezones(t *testing.T, s storage.Storage) {
 			Groups:        []string{"a", "b"},
 		},
 	}
-	if err := s.CreateAuthCode(ctx, c); err != nil {
+	if err := s.CreateAuthCode(c); err != nil {
 		t.Fatalf("failed creating auth code: %v", err)
 	}
 	got, err := s.GetAuthCode(c.ID)
@@ -985,7 +975,6 @@ func testTimezones(t *testing.T, s storage.Storage) {
 }
 
 func testDeviceRequestCRUD(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	d1 := storage.DeviceRequest{
 		UserCode:     storage.NewUserCode(),
 		DeviceCode:   storage.NewID(),
@@ -995,12 +984,12 @@ func testDeviceRequestCRUD(t *testing.T, s storage.Storage) {
 		Expiry:       neverExpire.Round(time.Second),
 	}
 
-	if err := s.CreateDeviceRequest(ctx, d1); err != nil {
+	if err := s.CreateDeviceRequest(d1); err != nil {
 		t.Fatalf("failed creating device request: %v", err)
 	}
 
 	// Attempt to create same DeviceRequest twice.
-	err := s.CreateDeviceRequest(ctx, d1)
+	err := s.CreateDeviceRequest(d1)
 	mustBeErrAlreadyExists(t, "device request", err)
 
 	got, err := s.GetDeviceRequest(d1.UserCode)
@@ -1015,7 +1004,6 @@ func testDeviceRequestCRUD(t *testing.T, s storage.Storage) {
 }
 
 func testDeviceTokenCRUD(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	codeChallenge := storage.PKCE{
 		CodeChallenge:       "code_challenge_test",
 		CodeChallengeMethod: "plain",
@@ -1032,12 +1020,12 @@ func testDeviceTokenCRUD(t *testing.T, s storage.Storage) {
 		PKCE:                codeChallenge,
 	}
 
-	if err := s.CreateDeviceToken(ctx, d1); err != nil {
+	if err := s.CreateDeviceToken(d1); err != nil {
 		t.Fatalf("failed creating device token: %v", err)
 	}
 
 	// Attempt to create same Device Token twice.
-	err := s.CreateDeviceToken(ctx, d1)
+	err := s.CreateDeviceToken(d1)
 	mustBeErrAlreadyExists(t, "device token", err)
 
 	// Update the device token, simulate a redemption
diff --git a/storage/conformance/transactions.go b/storage/conformance/transactions.go
index 69ed5517..1d4011a4 100644
--- a/storage/conformance/transactions.go
+++ b/storage/conformance/transactions.go
@@ -1,7 +1,6 @@
 package conformance
 
 import (
-	"context"
 	"testing"
 	"time"
 
@@ -27,7 +26,6 @@ func RunTransactionTests(t *testing.T, newStorage func() storage.Storage) {
 }
 
 func testClientConcurrentUpdate(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	c := storage.Client{
 		ID:           storage.NewID(),
 		Secret:       "foobar",
@@ -36,7 +34,7 @@ func testClientConcurrentUpdate(t *testing.T, s storage.Storage) {
 		LogoURL:      "https://goo.gl/JIyzIC",
 	}
 
-	if err := s.CreateClient(ctx, c); err != nil {
+	if err := s.CreateClient(c); err != nil {
 		t.Fatalf("create client: %v", err)
 	}
 
@@ -57,7 +55,6 @@ func testClientConcurrentUpdate(t *testing.T, s storage.Storage) {
 }
 
 func testAuthRequestConcurrentUpdate(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	a := storage.AuthRequest{
 		ID:                  storage.NewID(),
 		ClientID:            "foobar",
@@ -81,7 +78,7 @@ func testAuthRequestConcurrentUpdate(t *testing.T, s storage.Storage) {
 		HMACKey: []byte("hmac_key"),
 	}
 
-	if err := s.CreateAuthRequest(ctx, a); err != nil {
+	if err := s.CreateAuthRequest(a); err != nil {
 		t.Fatalf("failed creating auth request: %v", err)
 	}
 
@@ -102,7 +99,6 @@ func testAuthRequestConcurrentUpdate(t *testing.T, s storage.Storage) {
 }
 
 func testPasswordConcurrentUpdate(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	// Use bcrypt.MinCost to keep the tests short.
 	passwordHash, err := bcrypt.GenerateFromPassword([]byte("secret"), bcrypt.MinCost)
 	if err != nil {
@@ -115,7 +111,7 @@ func testPasswordConcurrentUpdate(t *testing.T, s storage.Storage) {
 		Username: "jane",
 		UserID:   "foobar",
 	}
-	if err := s.CreatePassword(ctx, password); err != nil {
+	if err := s.CreatePassword(password); err != nil {
 		t.Fatalf("create password token: %v", err)
 	}
 
diff --git a/storage/ent/client/authcode.go b/storage/ent/client/authcode.go
index 8ac12314..b6b263bf 100644
--- a/storage/ent/client/authcode.go
+++ b/storage/ent/client/authcode.go
@@ -7,7 +7,7 @@ import (
 )
 
 // CreateAuthCode saves provided auth code into the database.
-func (d *Database) CreateAuthCode(ctx context.Context, code storage.AuthCode) error {
+func (d *Database) CreateAuthCode(code storage.AuthCode) error {
 	_, err := d.client.AuthCode.Create().
 		SetID(code.ID).
 		SetClientID(code.ClientID).
@@ -26,7 +26,7 @@ func (d *Database) CreateAuthCode(ctx context.Context, code storage.AuthCode) er
 		SetExpiry(code.Expiry.UTC()).
 		SetConnectorID(code.ConnectorID).
 		SetConnectorData(code.ConnectorData).
-		Save(ctx)
+		Save(context.TODO())
 	if err != nil {
 		return convertDBError("create auth code: %w", err)
 	}
diff --git a/storage/ent/client/authrequest.go b/storage/ent/client/authrequest.go
index 42db702d..d68fd438 100644
--- a/storage/ent/client/authrequest.go
+++ b/storage/ent/client/authrequest.go
@@ -8,7 +8,7 @@ import (
 )
 
 // CreateAuthRequest saves provided auth request into the database.
-func (d *Database) CreateAuthRequest(ctx context.Context, authRequest storage.AuthRequest) error {
+func (d *Database) CreateAuthRequest(authRequest storage.AuthRequest) error {
 	_, err := d.client.AuthRequest.Create().
 		SetID(authRequest.ID).
 		SetClientID(authRequest.ClientID).
@@ -32,7 +32,7 @@ func (d *Database) CreateAuthRequest(ctx context.Context, authRequest storage.Au
 		SetConnectorID(authRequest.ConnectorID).
 		SetConnectorData(authRequest.ConnectorData).
 		SetHmacKey(authRequest.HMACKey).
-		Save(ctx)
+		Save(context.TODO())
 	if err != nil {
 		return convertDBError("create auth request: %w", err)
 	}
diff --git a/storage/ent/client/client.go b/storage/ent/client/client.go
index 4cb02c0c..07434bd6 100644
--- a/storage/ent/client/client.go
+++ b/storage/ent/client/client.go
@@ -7,7 +7,7 @@ import (
 )
 
 // CreateClient saves provided oauth2 client settings into the database.
-func (d *Database) CreateClient(ctx context.Context, client storage.Client) error {
+func (d *Database) CreateClient(client storage.Client) error {
 	_, err := d.client.OAuth2Client.Create().
 		SetID(client.ID).
 		SetName(client.Name).
@@ -16,7 +16,7 @@ func (d *Database) CreateClient(ctx context.Context, client storage.Client) erro
 		SetLogoURL(client.LogoURL).
 		SetRedirectUris(client.RedirectURIs).
 		SetTrustedPeers(client.TrustedPeers).
-		Save(ctx)
+		Save(context.TODO())
 	if err != nil {
 		return convertDBError("create oauth2 client: %w", err)
 	}
diff --git a/storage/ent/client/connector.go b/storage/ent/client/connector.go
index 1534e522..bfec4418 100644
--- a/storage/ent/client/connector.go
+++ b/storage/ent/client/connector.go
@@ -7,14 +7,14 @@ import (
 )
 
 // CreateConnector saves a connector into the database.
-func (d *Database) CreateConnector(ctx context.Context, connector storage.Connector) error {
+func (d *Database) CreateConnector(connector storage.Connector) error {
 	_, err := d.client.Connector.Create().
 		SetID(connector.ID).
 		SetName(connector.Name).
 		SetType(connector.Type).
 		SetResourceVersion(connector.ResourceVersion).
 		SetConfig(connector.Config).
-		Save(ctx)
+		Save(context.TODO())
 	if err != nil {
 		return convertDBError("create connector: %w", err)
 	}
diff --git a/storage/ent/client/devicerequest.go b/storage/ent/client/devicerequest.go
index d8d371c9..6e9c2500 100644
--- a/storage/ent/client/devicerequest.go
+++ b/storage/ent/client/devicerequest.go
@@ -8,7 +8,7 @@ import (
 )
 
 // CreateDeviceRequest saves provided device request into the database.
-func (d *Database) CreateDeviceRequest(ctx context.Context, request storage.DeviceRequest) error {
+func (d *Database) CreateDeviceRequest(request storage.DeviceRequest) error {
 	_, err := d.client.DeviceRequest.Create().
 		SetClientID(request.ClientID).
 		SetClientSecret(request.ClientSecret).
@@ -17,7 +17,7 @@ func (d *Database) CreateDeviceRequest(ctx context.Context, request storage.Devi
 		SetDeviceCode(request.DeviceCode).
 		// Save utc time into database because ent doesn't support comparing dates with different timezones
 		SetExpiry(request.Expiry.UTC()).
-		Save(ctx)
+		Save(context.TODO())
 	if err != nil {
 		return convertDBError("create device request: %w", err)
 	}
diff --git a/storage/ent/client/devicetoken.go b/storage/ent/client/devicetoken.go
index 18d483b9..99cf077d 100644
--- a/storage/ent/client/devicetoken.go
+++ b/storage/ent/client/devicetoken.go
@@ -8,7 +8,7 @@ import (
 )
 
 // CreateDeviceToken saves provided token into the database.
-func (d *Database) CreateDeviceToken(ctx context.Context, token storage.DeviceToken) error {
+func (d *Database) CreateDeviceToken(token storage.DeviceToken) error {
 	_, err := d.client.DeviceToken.Create().
 		SetDeviceCode(token.DeviceCode).
 		SetToken([]byte(token.Token)).
@@ -19,7 +19,7 @@ func (d *Database) CreateDeviceToken(ctx context.Context, token storage.DeviceTo
 		SetStatus(token.Status).
 		SetCodeChallenge(token.PKCE.CodeChallenge).
 		SetCodeChallengeMethod(token.PKCE.CodeChallengeMethod).
-		Save(ctx)
+		Save(context.TODO())
 	if err != nil {
 		return convertDBError("create device token: %w", err)
 	}
diff --git a/storage/ent/client/offlinesession.go b/storage/ent/client/offlinesession.go
index 22469ece..9f54ea1d 100644
--- a/storage/ent/client/offlinesession.go
+++ b/storage/ent/client/offlinesession.go
@@ -9,7 +9,7 @@ import (
 )
 
 // CreateOfflineSessions saves provided offline session into the database.
-func (d *Database) CreateOfflineSessions(ctx context.Context, session storage.OfflineSessions) error {
+func (d *Database) CreateOfflineSessions(session storage.OfflineSessions) error {
 	encodedRefresh, err := json.Marshal(session.Refresh)
 	if err != nil {
 		return fmt.Errorf("encode refresh offline session: %w", err)
@@ -22,7 +22,7 @@ func (d *Database) CreateOfflineSessions(ctx context.Context, session storage.Of
 		SetConnID(session.ConnID).
 		SetConnectorData(session.ConnectorData).
 		SetRefresh(encodedRefresh).
-		Save(ctx)
+		Save(context.TODO())
 	if err != nil {
 		return convertDBError("create offline session: %w", err)
 	}
diff --git a/storage/ent/client/password.go b/storage/ent/client/password.go
index 3e4aace8..daaae30c 100644
--- a/storage/ent/client/password.go
+++ b/storage/ent/client/password.go
@@ -9,13 +9,13 @@ import (
 )
 
 // CreatePassword saves provided password into the database.
-func (d *Database) CreatePassword(ctx context.Context, password storage.Password) error {
+func (d *Database) CreatePassword(password storage.Password) error {
 	_, err := d.client.Password.Create().
 		SetEmail(password.Email).
 		SetHash(password.Hash).
 		SetUsername(password.Username).
 		SetUserID(password.UserID).
-		Save(ctx)
+		Save(context.TODO())
 	if err != nil {
 		return convertDBError("create password: %w", err)
 	}
diff --git a/storage/ent/client/refreshtoken.go b/storage/ent/client/refreshtoken.go
index 6861b079..eca048f4 100644
--- a/storage/ent/client/refreshtoken.go
+++ b/storage/ent/client/refreshtoken.go
@@ -7,7 +7,7 @@ import (
 )
 
 // CreateRefresh saves provided refresh token into the database.
-func (d *Database) CreateRefresh(ctx context.Context, refresh storage.RefreshToken) error {
+func (d *Database) CreateRefresh(refresh storage.RefreshToken) error {
 	_, err := d.client.RefreshToken.Create().
 		SetID(refresh.ID).
 		SetClientID(refresh.ClientID).
@@ -26,7 +26,7 @@ func (d *Database) CreateRefresh(ctx context.Context, refresh storage.RefreshTok
 		// Save utc time into database because ent doesn't support comparing dates with different timezones
 		SetLastUsed(refresh.LastUsed.UTC()).
 		SetCreatedAt(refresh.CreatedAt.UTC()).
-		Save(ctx)
+		Save(context.TODO())
 	if err != nil {
 		return convertDBError("create refresh token: %w", err)
 	}
diff --git a/storage/etcd/etcd.go b/storage/etcd/etcd.go
index e4b24b4a..0343ade9 100644
--- a/storage/etcd/etcd.go
+++ b/storage/etcd/etcd.go
@@ -29,8 +29,6 @@ const (
 	defaultStorageTimeout = 5 * time.Second
 )
 
-var _ storage.Storage = (*conn)(nil)
-
 type conn struct {
 	db     *clientv3.Client
 	logger log.Logger
@@ -109,7 +107,9 @@ func (c *conn) GarbageCollect(now time.Time) (result storage.GCResult, err error
 	return result, delErr
 }
 
-func (c *conn) CreateAuthRequest(ctx context.Context, a storage.AuthRequest) error {
+func (c *conn) CreateAuthRequest(a storage.AuthRequest) error {
+	ctx, cancel := context.WithTimeout(context.Background(), defaultStorageTimeout)
+	defer cancel()
 	return c.txnCreate(ctx, keyID(authRequestPrefix, a.ID), fromStorageAuthRequest(a))
 }
 
@@ -147,7 +147,9 @@ func (c *conn) DeleteAuthRequest(id string) error {
 	return c.deleteKey(ctx, keyID(authRequestPrefix, id))
 }
 
-func (c *conn) CreateAuthCode(ctx context.Context, a storage.AuthCode) error {
+func (c *conn) CreateAuthCode(a storage.AuthCode) error {
+	ctx, cancel := context.WithTimeout(context.Background(), defaultStorageTimeout)
+	defer cancel()
 	return c.txnCreate(ctx, keyID(authCodePrefix, a.ID), fromStorageAuthCode(a))
 }
 
@@ -168,7 +170,9 @@ func (c *conn) DeleteAuthCode(id string) error {
 	return c.deleteKey(ctx, keyID(authCodePrefix, id))
 }
 
-func (c *conn) CreateRefresh(ctx context.Context, r storage.RefreshToken) error {
+func (c *conn) CreateRefresh(r storage.RefreshToken) error {
+	ctx, cancel := context.WithTimeout(context.Background(), defaultStorageTimeout)
+	defer cancel()
 	return c.txnCreate(ctx, keyID(refreshTokenPrefix, r.ID), fromStorageRefreshToken(r))
 }
 
@@ -223,7 +227,9 @@ func (c *conn) ListRefreshTokens() (tokens []storage.RefreshToken, err error) {
 	return tokens, nil
 }
 
-func (c *conn) CreateClient(ctx context.Context, cli storage.Client) error {
+func (c *conn) CreateClient(cli storage.Client) error {
+	ctx, cancel := context.WithTimeout(context.Background(), defaultStorageTimeout)
+	defer cancel()
 	return c.txnCreate(ctx, keyID(clientPrefix, cli.ID), cli)
 }
 
@@ -275,7 +281,9 @@ func (c *conn) ListClients() (clients []storage.Client, err error) {
 	return clients, nil
 }
 
-func (c *conn) CreatePassword(ctx context.Context, p storage.Password) error {
+func (c *conn) CreatePassword(p storage.Password) error {
+	ctx, cancel := context.WithTimeout(context.Background(), defaultStorageTimeout)
+	defer cancel()
 	return c.txnCreate(ctx, passwordPrefix+strings.ToLower(p.Email), p)
 }
 
@@ -327,7 +335,9 @@ func (c *conn) ListPasswords() (passwords []storage.Password, err error) {
 	return passwords, nil
 }
 
-func (c *conn) CreateOfflineSessions(ctx context.Context, s storage.OfflineSessions) error {
+func (c *conn) CreateOfflineSessions(s storage.OfflineSessions) error {
+	ctx, cancel := context.WithTimeout(context.Background(), defaultStorageTimeout)
+	defer cancel()
 	return c.txnCreate(ctx, keySession(s.UserID, s.ConnID), fromStorageOfflineSessions(s))
 }
 
@@ -365,7 +375,9 @@ func (c *conn) DeleteOfflineSessions(userID string, connID string) error {
 	return c.deleteKey(ctx, keySession(userID, connID))
 }
 
-func (c *conn) CreateConnector(ctx context.Context, connector storage.Connector) error {
+func (c *conn) CreateConnector(connector storage.Connector) error {
+	ctx, cancel := context.WithTimeout(context.Background(), defaultStorageTimeout)
+	defer cancel()
 	return c.txnCreate(ctx, keyID(connectorPrefix, connector.ID), connector)
 }
 
@@ -556,7 +568,9 @@ func keySession(userID, connID string) string {
 	return offlineSessionPrefix + strings.ToLower(userID+"|"+connID)
 }
 
-func (c *conn) CreateDeviceRequest(ctx context.Context, d storage.DeviceRequest) error {
+func (c *conn) CreateDeviceRequest(d storage.DeviceRequest) error {
+	ctx, cancel := context.WithTimeout(context.Background(), defaultStorageTimeout)
+	defer cancel()
 	return c.txnCreate(ctx, keyID(deviceRequestPrefix, d.UserCode), fromStorageDeviceRequest(d))
 }
 
@@ -585,7 +599,9 @@ func (c *conn) listDeviceRequests(ctx context.Context) (requests []DeviceRequest
 	return requests, nil
 }
 
-func (c *conn) CreateDeviceToken(ctx context.Context, t storage.DeviceToken) error {
+func (c *conn) CreateDeviceToken(t storage.DeviceToken) error {
+	ctx, cancel := context.WithTimeout(context.Background(), defaultStorageTimeout)
+	defer cancel()
 	return c.txnCreate(ctx, keyID(deviceTokenPrefix, t.DeviceCode), fromStorageDeviceToken(t))
 }
 
diff --git a/storage/health.go b/storage/health.go
index 8cdefddf..1b6e22c6 100644
--- a/storage/health.go
+++ b/storage/health.go
@@ -9,7 +9,7 @@ import (
 
 // NewCustomHealthCheckFunc returns a new health check function.
 func NewCustomHealthCheckFunc(s Storage, now func() time.Time) func(context.Context) (details interface{}, err error) {
-	return func(ctx context.Context) (details interface{}, err error) {
+	return func(_ context.Context) (details interface{}, err error) {
 		a := AuthRequest{
 			ID:       NewID(),
 			ClientID: NewID(),
@@ -19,7 +19,7 @@ func NewCustomHealthCheckFunc(s Storage, now func() time.Time) func(context.Cont
 			HMACKey: NewHMACKey(crypto.SHA256),
 		}
 
-		if err := s.CreateAuthRequest(ctx, a); err != nil {
+		if err := s.CreateAuthRequest(a); err != nil {
 			return nil, fmt.Errorf("create auth request: %v", err)
 		}
 
diff --git a/storage/kubernetes/storage.go b/storage/kubernetes/storage.go
index c08362b8..0979f14a 100644
--- a/storage/kubernetes/storage.go
+++ b/storage/kubernetes/storage.go
@@ -40,8 +40,6 @@ const (
 	resourceDeviceToken     = "devicetokens"
 )
 
-var _ storage.Storage = (*client)(nil)
-
 const (
 	gcResultLimit = 500
 )
@@ -234,31 +232,31 @@ func (cli *client) Close() error {
 	return nil
 }
 
-func (cli *client) CreateAuthRequest(ctx context.Context, a storage.AuthRequest) error {
+func (cli *client) CreateAuthRequest(a storage.AuthRequest) error {
 	return cli.post(resourceAuthRequest, cli.fromStorageAuthRequest(a))
 }
 
-func (cli *client) CreateClient(ctx context.Context, c storage.Client) error {
+func (cli *client) CreateClient(c storage.Client) error {
 	return cli.post(resourceClient, cli.fromStorageClient(c))
 }
 
-func (cli *client) CreateAuthCode(ctx context.Context, c storage.AuthCode) error {
+func (cli *client) CreateAuthCode(c storage.AuthCode) error {
 	return cli.post(resourceAuthCode, cli.fromStorageAuthCode(c))
 }
 
-func (cli *client) CreatePassword(ctx context.Context, p storage.Password) error {
+func (cli *client) CreatePassword(p storage.Password) error {
 	return cli.post(resourcePassword, cli.fromStoragePassword(p))
 }
 
-func (cli *client) CreateRefresh(ctx context.Context, r storage.RefreshToken) error {
+func (cli *client) CreateRefresh(r storage.RefreshToken) error {
 	return cli.post(resourceRefreshToken, cli.fromStorageRefreshToken(r))
 }
 
-func (cli *client) CreateOfflineSessions(ctx context.Context, o storage.OfflineSessions) error {
+func (cli *client) CreateOfflineSessions(o storage.OfflineSessions) error {
 	return cli.post(resourceOfflineSessions, cli.fromStorageOfflineSessions(o))
 }
 
-func (cli *client) CreateConnector(ctx context.Context, c storage.Connector) error {
+func (cli *client) CreateConnector(c storage.Connector) error {
 	return cli.post(resourceConnector, cli.fromStorageConnector(c))
 }
 
@@ -683,7 +681,7 @@ func (cli *client) GarbageCollect(now time.Time) (result storage.GCResult, err e
 	return result, delErr
 }
 
-func (cli *client) CreateDeviceRequest(ctx context.Context, d storage.DeviceRequest) error {
+func (cli *client) CreateDeviceRequest(d storage.DeviceRequest) error {
 	return cli.post(resourceDeviceRequest, cli.fromStorageDeviceRequest(d))
 }
 
@@ -695,7 +693,7 @@ func (cli *client) GetDeviceRequest(userCode string) (storage.DeviceRequest, err
 	return toStorageDeviceRequest(req), nil
 }
 
-func (cli *client) CreateDeviceToken(ctx context.Context, t storage.DeviceToken) error {
+func (cli *client) CreateDeviceToken(t storage.DeviceToken) error {
 	return cli.post(resourceDeviceToken, cli.fromStorageDeviceToken(t))
 }
 
diff --git a/storage/memory/memory.go b/storage/memory/memory.go
index 8e080c9f..a9406657 100644
--- a/storage/memory/memory.go
+++ b/storage/memory/memory.go
@@ -2,7 +2,6 @@
 package memory
 
 import (
-	"context"
 	"strings"
 	"sync"
 	"time"
@@ -11,8 +10,6 @@ import (
 	"github.com/dexidp/dex/storage"
 )
 
-var _ storage.Storage = (*memStorage)(nil)
-
 // New returns an in memory storage.
 func New(logger log.Logger) storage.Storage {
 	return &memStorage{
@@ -101,7 +98,7 @@ func (s *memStorage) GarbageCollect(now time.Time) (result storage.GCResult, err
 	return result, nil
 }
 
-func (s *memStorage) CreateClient(ctx context.Context, c storage.Client) (err error) {
+func (s *memStorage) CreateClient(c storage.Client) (err error) {
 	s.tx(func() {
 		if _, ok := s.clients[c.ID]; ok {
 			err = storage.ErrAlreadyExists
@@ -112,7 +109,7 @@ func (s *memStorage) CreateClient(ctx context.Context, c storage.Client) (err er
 	return
 }
 
-func (s *memStorage) CreateAuthCode(ctx context.Context, c storage.AuthCode) (err error) {
+func (s *memStorage) CreateAuthCode(c storage.AuthCode) (err error) {
 	s.tx(func() {
 		if _, ok := s.authCodes[c.ID]; ok {
 			err = storage.ErrAlreadyExists
@@ -123,7 +120,7 @@ func (s *memStorage) CreateAuthCode(ctx context.Context, c storage.AuthCode) (er
 	return
 }
 
-func (s *memStorage) CreateRefresh(ctx context.Context, r storage.RefreshToken) (err error) {
+func (s *memStorage) CreateRefresh(r storage.RefreshToken) (err error) {
 	s.tx(func() {
 		if _, ok := s.refreshTokens[r.ID]; ok {
 			err = storage.ErrAlreadyExists
@@ -134,7 +131,7 @@ func (s *memStorage) CreateRefresh(ctx context.Context, r storage.RefreshToken)
 	return
 }
 
-func (s *memStorage) CreateAuthRequest(ctx context.Context, a storage.AuthRequest) (err error) {
+func (s *memStorage) CreateAuthRequest(a storage.AuthRequest) (err error) {
 	s.tx(func() {
 		if _, ok := s.authReqs[a.ID]; ok {
 			err = storage.ErrAlreadyExists
@@ -145,7 +142,7 @@ func (s *memStorage) CreateAuthRequest(ctx context.Context, a storage.AuthReques
 	return
 }
 
-func (s *memStorage) CreatePassword(ctx context.Context, p storage.Password) (err error) {
+func (s *memStorage) CreatePassword(p storage.Password) (err error) {
 	lowerEmail := strings.ToLower(p.Email)
 	s.tx(func() {
 		if _, ok := s.passwords[lowerEmail]; ok {
@@ -157,7 +154,7 @@ func (s *memStorage) CreatePassword(ctx context.Context, p storage.Password) (er
 	return
 }
 
-func (s *memStorage) CreateOfflineSessions(ctx context.Context, o storage.OfflineSessions) (err error) {
+func (s *memStorage) CreateOfflineSessions(o storage.OfflineSessions) (err error) {
 	id := offlineSessionID{
 		userID: o.UserID,
 		connID: o.ConnID,
@@ -172,7 +169,7 @@ func (s *memStorage) CreateOfflineSessions(ctx context.Context, o storage.Offlin
 	return
 }
 
-func (s *memStorage) CreateConnector(ctx context.Context, connector storage.Connector) (err error) {
+func (s *memStorage) CreateConnector(connector storage.Connector) (err error) {
 	s.tx(func() {
 		if _, ok := s.connectors[connector.ID]; ok {
 			err = storage.ErrAlreadyExists
@@ -484,7 +481,7 @@ func (s *memStorage) UpdateConnector(id string, updater func(c storage.Connector
 	return
 }
 
-func (s *memStorage) CreateDeviceRequest(ctx context.Context, d storage.DeviceRequest) (err error) {
+func (s *memStorage) CreateDeviceRequest(d storage.DeviceRequest) (err error) {
 	s.tx(func() {
 		if _, ok := s.deviceRequests[d.UserCode]; ok {
 			err = storage.ErrAlreadyExists
@@ -506,7 +503,7 @@ func (s *memStorage) GetDeviceRequest(userCode string) (req storage.DeviceReques
 	return
 }
 
-func (s *memStorage) CreateDeviceToken(ctx context.Context, t storage.DeviceToken) (err error) {
+func (s *memStorage) CreateDeviceToken(t storage.DeviceToken) (err error) {
 	s.tx(func() {
 		if _, ok := s.deviceTokens[t.DeviceCode]; ok {
 			err = storage.ErrAlreadyExists
diff --git a/storage/sql/crud.go b/storage/sql/crud.go
index 1249243c..7f8666db 100644
--- a/storage/sql/crud.go
+++ b/storage/sql/crud.go
@@ -1,7 +1,6 @@
 package sql
 
 import (
-	"context"
 	"database/sql"
 	"database/sql/driver"
 	"encoding/json"
@@ -84,8 +83,6 @@ type scanner interface {
 	Scan(dest ...interface{}) error
 }
 
-var _ storage.Storage = (*conn)(nil)
-
 func (c *conn) GarbageCollect(now time.Time) (storage.GCResult, error) {
 	result := storage.GCResult{}
 
@@ -124,7 +121,7 @@ func (c *conn) GarbageCollect(now time.Time) (storage.GCResult, error) {
 	return result, err
 }
 
-func (c *conn) CreateAuthRequest(ctx context.Context, a storage.AuthRequest) error {
+func (c *conn) CreateAuthRequest(a storage.AuthRequest) error {
 	_, err := c.Exec(`
 		insert into auth_request (
 			id, client_id, response_types, scopes, redirect_uri, nonce, state,
@@ -232,7 +229,7 @@ func getAuthRequest(q querier, id string) (a storage.AuthRequest, err error) {
 	return a, nil
 }
 
-func (c *conn) CreateAuthCode(ctx context.Context, a storage.AuthCode) error {
+func (c *conn) CreateAuthCode(a storage.AuthCode) error {
 	_, err := c.Exec(`
 		insert into auth_code (
 			id, client_id, scopes, nonce, redirect_uri,
@@ -283,7 +280,7 @@ func (c *conn) GetAuthCode(id string) (a storage.AuthCode, err error) {
 	return a, nil
 }
 
-func (c *conn) CreateRefresh(ctx context.Context, r storage.RefreshToken) error {
+func (c *conn) CreateRefresh(r storage.RefreshToken) error {
 	_, err := c.Exec(`
 		insert into refresh_token (
 			id, client_id, scopes, nonce,
@@ -524,7 +521,7 @@ func (c *conn) UpdateClient(id string, updater func(old storage.Client) (storage
 	})
 }
 
-func (c *conn) CreateClient(ctx context.Context, cli storage.Client) error {
+func (c *conn) CreateClient(cli storage.Client) error {
 	_, err := c.Exec(`
 		insert into client (
 			id, secret, redirect_uris, trusted_peers, public, name, logo_url
@@ -594,7 +591,7 @@ func scanClient(s scanner) (cli storage.Client, err error) {
 	return cli, nil
 }
 
-func (c *conn) CreatePassword(ctx context.Context, p storage.Password) error {
+func (c *conn) CreatePassword(p storage.Password) error {
 	p.Email = strings.ToLower(p.Email)
 	_, err := c.Exec(`
 		insert into password (
@@ -691,7 +688,7 @@ func scanPassword(s scanner) (p storage.Password, err error) {
 	return p, nil
 }
 
-func (c *conn) CreateOfflineSessions(ctx context.Context, s storage.OfflineSessions) error {
+func (c *conn) CreateOfflineSessions(s storage.OfflineSessions) error {
 	_, err := c.Exec(`
 		insert into offline_session (
 			user_id, conn_id, refresh, connector_data
@@ -764,7 +761,7 @@ func scanOfflineSessions(s scanner) (o storage.OfflineSessions, err error) {
 	return o, nil
 }
 
-func (c *conn) CreateConnector(ctx context.Context, connector storage.Connector) error {
+func (c *conn) CreateConnector(connector storage.Connector) error {
 	_, err := c.Exec(`
 		insert into connector (
 			id, type, name, resource_version, config
@@ -910,7 +907,7 @@ func (c *conn) delete(table, field, id string) error {
 	return nil
 }
 
-func (c *conn) CreateDeviceRequest(ctx context.Context, d storage.DeviceRequest) error {
+func (c *conn) CreateDeviceRequest(d storage.DeviceRequest) error {
 	_, err := c.Exec(`
 		insert into device_request (
 			user_code, device_code, client_id, client_secret, scopes, expiry
@@ -929,7 +926,7 @@ func (c *conn) CreateDeviceRequest(ctx context.Context, d storage.DeviceRequest)
 	return nil
 }
 
-func (c *conn) CreateDeviceToken(ctx context.Context, t storage.DeviceToken) error {
+func (c *conn) CreateDeviceToken(t storage.DeviceToken) error {
 	_, err := c.Exec(`
 		insert into device_token (
 			device_code, status, token, expiry, last_request, poll_interval, code_challenge, code_challenge_method
@@ -1004,7 +1001,7 @@ func (c *conn) UpdateDeviceToken(deviceCode string, updater func(old storage.Dev
 		_, err = tx.Exec(`
 			update device_token
 			set
-				status = $1,
+				status = $1, 
 				token = $2,
 				last_request = $3,
 				poll_interval = $4,
diff --git a/storage/static.go b/storage/static.go
index e8902b9b..806b61f9 100644
--- a/storage/static.go
+++ b/storage/static.go
@@ -1,7 +1,6 @@
 package storage
 
 import (
-	"context"
 	"errors"
 	"strings"
 
@@ -61,11 +60,11 @@ func (s staticClientsStorage) ListClients() ([]Client, error) {
 	return append(clients[:n], s.clients...), nil
 }
 
-func (s staticClientsStorage) CreateClient(ctx context.Context, c Client) error {
+func (s staticClientsStorage) CreateClient(c Client) error {
 	if s.isStatic(c.ID) {
 		return errors.New("static clients: read-only cannot create client")
 	}
-	return s.Storage.CreateClient(ctx, c)
+	return s.Storage.CreateClient(c)
 }
 
 func (s staticClientsStorage) DeleteClient(id string) error {
@@ -141,11 +140,11 @@ func (s staticPasswordsStorage) ListPasswords() ([]Password, error) {
 	return append(passwords[:n], s.passwords...), nil
 }
 
-func (s staticPasswordsStorage) CreatePassword(ctx context.Context, p Password) error {
+func (s staticPasswordsStorage) CreatePassword(p Password) error {
 	if s.isStatic(p.Email) {
 		return errors.New("static passwords: read-only cannot create password")
 	}
-	return s.Storage.CreatePassword(ctx, p)
+	return s.Storage.CreatePassword(p)
 }
 
 func (s staticPasswordsStorage) DeletePassword(email string) error {
@@ -211,11 +210,11 @@ func (s staticConnectorsStorage) ListConnectors() ([]Connector, error) {
 	return append(connectors[:n], s.connectors...), nil
 }
 
-func (s staticConnectorsStorage) CreateConnector(ctx context.Context, c Connector) error {
+func (s staticConnectorsStorage) CreateConnector(c Connector) error {
 	if s.isStatic(c.ID) {
 		return errors.New("static connectors: read-only cannot create connector")
 	}
-	return s.Storage.CreateConnector(ctx, c)
+	return s.Storage.CreateConnector(c)
 }
 
 func (s staticConnectorsStorage) DeleteConnector(id string) error {
diff --git a/storage/storage.go b/storage/storage.go
index 214c2d49..743d2ecb 100644
--- a/storage/storage.go
+++ b/storage/storage.go
@@ -1,7 +1,6 @@
 package storage
 
 import (
-	"context"
 	"crypto"
 	"crypto/rand"
 	"encoding/base32"
@@ -77,15 +76,15 @@ type Storage interface {
 	Close() error
 
 	// TODO(ericchiang): Let the storages set the IDs of these objects.
-	CreateAuthRequest(ctx context.Context, a AuthRequest) error
-	CreateClient(ctx context.Context, c Client) error
-	CreateAuthCode(ctx context.Context, c AuthCode) error
-	CreateRefresh(ctx context.Context, r RefreshToken) error
-	CreatePassword(ctx context.Context, p Password) error
-	CreateOfflineSessions(ctx context.Context, s OfflineSessions) error
-	CreateConnector(ctx context.Context, c Connector) error
-	CreateDeviceRequest(ctx context.Context, d DeviceRequest) error
-	CreateDeviceToken(ctx context.Context, d DeviceToken) error
+	CreateAuthRequest(a AuthRequest) error
+	CreateClient(c Client) error
+	CreateAuthCode(c AuthCode) error
+	CreateRefresh(r RefreshToken) error
+	CreatePassword(p Password) error
+	CreateOfflineSessions(s OfflineSessions) error
+	CreateConnector(c Connector) error
+	CreateDeviceRequest(d DeviceRequest) error
+	CreateDeviceToken(d DeviceToken) error
 
 	// TODO(ericchiang): return (T, bool, error) so we can indicate not found
 	// requests that way instead of using ErrNotFound.


Test patch:
diff --git a/cmd/dex/config_test.go b/cmd/dex/config_test.go
index 21037084..16803d6d 100644
--- a/cmd/dex/config_test.go
+++ b/cmd/dex/config_test.go
@@ -71,7 +71,9 @@ storage:
     connMaxLifetime: 30
     connectionTimeout: 3
 web:
-  http: 127.0.0.1:5556
+  https: 127.0.0.1:5556
+  tlsMinVersion: 1.3
+  tlsMaxVersion: 1.2
 
 frontend:
   dir: ./web
@@ -144,7 +146,9 @@ logger:
 			},
 		},
 		Web: Web{
-			HTTP: "127.0.0.1:5556",
+			HTTPS:         "127.0.0.1:5556",
+			TLSMinVersion: "1.3",
+			TLSMaxVersion: "1.2",
 		},
 		Frontend: server.WebConfig{
 			Dir: "./web",
diff --git a/server/api_test.go b/server/api_test.go
index b023beb5..bc0dcf11 100644
--- a/server/api_test.go
+++ b/server/api_test.go
@@ -262,7 +262,7 @@ func TestRefreshToken(t *testing.T) {
 		ConnectorData: []byte(`{"some":"data"}`),
 	}
 
-	if err := s.CreateRefresh(ctx, r); err != nil {
+	if err := s.CreateRefresh(r); err != nil {
 		t.Fatalf("create refresh token: %v", err)
 	}
 
@@ -280,7 +280,7 @@ func TestRefreshToken(t *testing.T) {
 	}
 	session.Refresh[tokenRef.ClientID] = &tokenRef
 
-	if err := s.CreateOfflineSessions(ctx, session); err != nil {
+	if err := s.CreateOfflineSessions(session); err != nil {
 		t.Fatalf("create offline session: %v", err)
 	}
 
diff --git a/server/deviceflowhandlers_test.go b/server/deviceflowhandlers_test.go
index 151c7508..9abe4a62 100644
--- a/server/deviceflowhandlers_test.go
+++ b/server/deviceflowhandlers_test.go
@@ -366,15 +366,15 @@ func TestDeviceCallback(t *testing.T) {
 			})
 			defer httpServer.Close()
 
-			if err := s.storage.CreateAuthCode(ctx, tc.testAuthCode); err != nil {
+			if err := s.storage.CreateAuthCode(tc.testAuthCode); err != nil {
 				t.Fatalf("failed to create auth code: %v", err)
 			}
 
-			if err := s.storage.CreateDeviceRequest(ctx, tc.testDeviceRequest); err != nil {
+			if err := s.storage.CreateDeviceRequest(tc.testDeviceRequest); err != nil {
 				t.Fatalf("failed to create device request: %v", err)
 			}
 
-			if err := s.storage.CreateDeviceToken(ctx, tc.testDeviceToken); err != nil {
+			if err := s.storage.CreateDeviceToken(tc.testDeviceToken); err != nil {
 				t.Fatalf("failed to create device token: %v", err)
 			}
 
@@ -383,7 +383,7 @@ func TestDeviceCallback(t *testing.T) {
 				Secret:       "",
 				RedirectURIs: []string{deviceCallbackURI},
 			}
-			if err := s.storage.CreateClient(ctx, client); err != nil {
+			if err := s.storage.CreateClient(client); err != nil {
 				t.Fatalf("failed to create client: %v", err)
 			}
 
@@ -660,11 +660,11 @@ func TestDeviceTokenResponse(t *testing.T) {
 			})
 			defer httpServer.Close()
 
-			if err := s.storage.CreateDeviceRequest(ctx, tc.testDeviceRequest); err != nil {
+			if err := s.storage.CreateDeviceRequest(tc.testDeviceRequest); err != nil {
 				t.Fatalf("Failed to store device token %v", err)
 			}
 
-			if err := s.storage.CreateDeviceToken(ctx, tc.testDeviceToken); err != nil {
+			if err := s.storage.CreateDeviceToken(tc.testDeviceToken); err != nil {
 				t.Fatalf("Failed to store device token %v", err)
 			}
 
@@ -794,7 +794,7 @@ func TestVerifyCodeResponse(t *testing.T) {
 			})
 			defer httpServer.Close()
 
-			if err := s.storage.CreateDeviceRequest(ctx, tc.testDeviceRequest); err != nil {
+			if err := s.storage.CreateDeviceRequest(tc.testDeviceRequest); err != nil {
 				t.Fatalf("Failed to store device token %v", err)
 			}
 
diff --git a/server/handlers_test.go b/server/handlers_test.go
index f6ada363..212b25fe 100644
--- a/server/handlers_test.go
+++ b/server/handlers_test.go
@@ -213,7 +213,7 @@ func TestHandleAuthCode(t *testing.T) {
 				Secret:       "testclientsecret",
 				RedirectURIs: []string{redirectURL},
 			}
-			err = s.storage.CreateClient(ctx, client)
+			err = s.storage.CreateClient(client)
 			require.NoError(t, err)
 
 			oauth2Client.config = &oauth2.Config{
@@ -233,7 +233,6 @@ func TestHandleAuthCode(t *testing.T) {
 }
 
 func mockConnectorDataTestStorage(t *testing.T, s storage.Storage) {
-	ctx := context.Background()
 	c := storage.Client{
 		ID:           "test",
 		Secret:       "barfoo",
@@ -242,7 +241,7 @@ func mockConnectorDataTestStorage(t *testing.T, s storage.Storage) {
 		LogoURL:      "https://goo.gl/JIyzIC",
 	}
 
-	err := s.CreateClient(ctx, c)
+	err := s.CreateClient(c)
 	require.NoError(t, err)
 
 	c1 := storage.Connector{
@@ -255,7 +254,7 @@ func mockConnectorDataTestStorage(t *testing.T, s storage.Storage) {
 }`),
 	}
 
-	err = s.CreateConnector(ctx, c1)
+	err = s.CreateConnector(c1)
 	require.NoError(t, err)
 
 	c2 := storage.Connector{
@@ -264,7 +263,7 @@ func mockConnectorDataTestStorage(t *testing.T, s storage.Storage) {
 		Name: "mockURLID",
 	}
 
-	err = s.CreateConnector(ctx, c2)
+	err = s.CreateConnector(c2)
 	require.NoError(t, err)
 }
 
@@ -468,13 +467,13 @@ func TestHandlePasswordLoginWithSkipApproval(t *testing.T) {
 				ResourceVersion: "1",
 				Config:          []byte("{\"username\": \"foo\", \"password\": \"password\"}"),
 			}
-			if err := s.storage.CreateConnector(ctx, sc); err != nil {
+			if err := s.storage.CreateConnector(sc); err != nil {
 				t.Fatalf("create connector: %v", err)
 			}
 			if _, err := s.OpenConnector(sc); err != nil {
 				t.Fatalf("open connector: %v", err)
 			}
-			if err := s.storage.CreateAuthRequest(ctx, tc.authReq); err != nil {
+			if err := s.storage.CreateAuthRequest(tc.authReq); err != nil {
 				t.Fatalf("failed to create AuthRequest: %v", err)
 			}
 
@@ -615,7 +614,7 @@ func TestHandleConnectorCallbackWithSkipApproval(t *testing.T) {
 			})
 			defer httpServer.Close()
 
-			if err := s.storage.CreateAuthRequest(ctx, tc.authReq); err != nil {
+			if err := s.storage.CreateAuthRequest(tc.authReq); err != nil {
 				t.Fatalf("failed to create AuthRequest: %v", err)
 			}
 			rr := httptest.NewRecorder()
@@ -713,7 +712,7 @@ func TestHandleTokenExchange(t *testing.T) {
 			ctx, cancel := context.WithCancel(context.Background())
 			defer cancel()
 			httpServer, s := newTestServer(ctx, t, func(c *Config) {
-				c.Storage.CreateClient(ctx, storage.Client{
+				c.Storage.CreateClient(storage.Client{
 					ID:     "client_1",
 					Secret: "secret_1",
 				})
diff --git a/server/refreshhandlers_test.go b/server/refreshhandlers_test.go
index 6b0925c2..c64c50b3 100644
--- a/server/refreshhandlers_test.go
+++ b/server/refreshhandlers_test.go
@@ -18,7 +18,6 @@ import (
 )
 
 func mockRefreshTokenTestStorage(t *testing.T, s storage.Storage, useObsolete bool) {
-	ctx := context.Background()
 	c := storage.Client{
 		ID:           "test",
 		Secret:       "barfoo",
@@ -27,7 +26,7 @@ func mockRefreshTokenTestStorage(t *testing.T, s storage.Storage, useObsolete bo
 		LogoURL:      "https://goo.gl/JIyzIC",
 	}
 
-	err := s.CreateClient(ctx, c)
+	err := s.CreateClient(c)
 	require.NoError(t, err)
 
 	c1 := storage.Connector{
@@ -37,7 +36,7 @@ func mockRefreshTokenTestStorage(t *testing.T, s storage.Storage, useObsolete bo
 		Config: nil,
 	}
 
-	err = s.CreateConnector(ctx, c1)
+	err = s.CreateConnector(c1)
 	require.NoError(t, err)
 
 	refresh := storage.RefreshToken{
@@ -65,7 +64,7 @@ func mockRefreshTokenTestStorage(t *testing.T, s storage.Storage, useObsolete bo
 		refresh.ObsoleteToken = "bar"
 	}
 
-	err = s.CreateRefresh(ctx, refresh)
+	err = s.CreateRefresh(refresh)
 	require.NoError(t, err)
 
 	offlineSessions := storage.OfflineSessions{
@@ -75,7 +74,7 @@ func mockRefreshTokenTestStorage(t *testing.T, s storage.Storage, useObsolete bo
 		ConnectorData: nil,
 	}
 
-	err = s.CreateOfflineSessions(ctx, offlineSessions)
+	err = s.CreateOfflineSessions(offlineSessions)
 	require.NoError(t, err)
 }
 
diff --git a/server/server_test.go b/server/server_test.go
index f9bfa4a3..dd21d737 100644
--- a/server/server_test.go
+++ b/server/server_test.go
@@ -119,7 +119,7 @@ func newTestServer(ctx context.Context, t *testing.T, updateConfig func(c *Confi
 		Name:            "Mock",
 		ResourceVersion: "1",
 	}
-	if err := config.Storage.CreateConnector(ctx, connector); err != nil {
+	if err := config.Storage.CreateConnector(connector); err != nil {
 		t.Fatalf("create connector: %v", err)
 	}
 
@@ -172,10 +172,10 @@ func newTestServerMultipleConnectors(ctx context.Context, t *testing.T, updateCo
 		Name:            "Mock",
 		ResourceVersion: "1",
 	}
-	if err := config.Storage.CreateConnector(ctx, connector); err != nil {
+	if err := config.Storage.CreateConnector(connector); err != nil {
 		t.Fatalf("create connector: %v", err)
 	}
-	if err := config.Storage.CreateConnector(ctx, connector2); err != nil {
+	if err := config.Storage.CreateConnector(connector2); err != nil {
 		t.Fatalf("create connector: %v", err)
 	}
 
@@ -837,11 +837,11 @@ func TestOAuth2CodeFlow(t *testing.T) {
 				Secret:       clientSecret,
 				RedirectURIs: []string{redirectURL},
 			}
-			if err := s.storage.CreateClient(ctx, client); err != nil {
+			if err := s.storage.CreateClient(client); err != nil {
 				t.Fatalf("failed to create client: %v", err)
 			}
 
-			if err := s.storage.CreateRefresh(ctx, storage.RefreshToken{
+			if err := s.storage.CreateRefresh(storage.RefreshToken{
 				ID:       "existedrefrestoken",
 				ClientID: "unexcistedclientid",
 			}); err != nil {
@@ -955,7 +955,7 @@ func TestOAuth2ImplicitFlow(t *testing.T) {
 		Secret:       "testclientsecret",
 		RedirectURIs: []string{redirectURL},
 	}
-	if err := s.storage.CreateClient(ctx, client); err != nil {
+	if err := s.storage.CreateClient(client); err != nil {
 		t.Fatalf("failed to create client: %v", err)
 	}
 
@@ -1113,7 +1113,7 @@ func TestCrossClientScopes(t *testing.T) {
 		Secret:       "testclientsecret",
 		RedirectURIs: []string{redirectURL},
 	}
-	if err := s.storage.CreateClient(ctx, client); err != nil {
+	if err := s.storage.CreateClient(client); err != nil {
 		t.Fatalf("failed to create client: %v", err)
 	}
 
@@ -1123,7 +1123,7 @@ func TestCrossClientScopes(t *testing.T) {
 		TrustedPeers: []string{"testclient"},
 	}
 
-	if err := s.storage.CreateClient(ctx, peer); err != nil {
+	if err := s.storage.CreateClient(peer); err != nil {
 		t.Fatalf("failed to create client: %v", err)
 	}
 
@@ -1236,7 +1236,7 @@ func TestCrossClientScopesWithAzpInAudienceByDefault(t *testing.T) {
 		Secret:       "testclientsecret",
 		RedirectURIs: []string{redirectURL},
 	}
-	if err := s.storage.CreateClient(ctx, client); err != nil {
+	if err := s.storage.CreateClient(client); err != nil {
 		t.Fatalf("failed to create client: %v", err)
 	}
 
@@ -1246,7 +1246,7 @@ func TestCrossClientScopesWithAzpInAudienceByDefault(t *testing.T) {
 		TrustedPeers: []string{"testclient"},
 	}
 
-	if err := s.storage.CreateClient(ctx, peer); err != nil {
+	if err := s.storage.CreateClient(peer); err != nil {
 		t.Fatalf("failed to create client: %v", err)
 	}
 
@@ -1276,7 +1276,6 @@ func TestCrossClientScopesWithAzpInAudienceByDefault(t *testing.T) {
 }
 
 func TestPasswordDB(t *testing.T) {
-	ctx := context.Background()
 	s := memory.New(logger)
 	conn := newPasswordDB(s)
 
@@ -1287,7 +1286,7 @@ func TestPasswordDB(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	s.CreatePassword(ctx, storage.Password{
+	s.CreatePassword(storage.Password{
 		Email:    "jane@example.com",
 		Username: "jane",
 		UserID:   "foobar",
@@ -1535,7 +1534,7 @@ func TestRefreshTokenFlow(t *testing.T) {
 		Secret:       "testclientsecret",
 		RedirectURIs: []string{redirectURL},
 	}
-	if err := s.storage.CreateClient(ctx, client); err != nil {
+	if err := s.storage.CreateClient(client); err != nil {
 		t.Fatalf("failed to create client: %v", err)
 	}
 
@@ -1634,11 +1633,11 @@ func TestOAuth2DeviceFlow(t *testing.T) {
 					RedirectURIs: []string{deviceCallbackURI},
 					Public:       true,
 				}
-				if err := s.storage.CreateClient(ctx, client); err != nil {
+				if err := s.storage.CreateClient(client); err != nil {
 					t.Fatalf("failed to create client: %v", err)
 				}
 
-				if err := s.storage.CreateRefresh(ctx, storage.RefreshToken{
+				if err := s.storage.CreateRefresh(storage.RefreshToken{
 					ID:       "existedrefrestoken",
 					ClientID: "unexcistedclientid",
 				}); err != nil {
diff --git a/storage/kubernetes/storage_test.go b/storage/kubernetes/storage_test.go
index b4b42688..07475fcd 100644
--- a/storage/kubernetes/storage_test.go
+++ b/storage/kubernetes/storage_test.go
@@ -302,7 +302,6 @@ func TestRetryOnConflict(t *testing.T) {
 }
 
 func TestRefreshTokenLock(t *testing.T) {
-	ctx := context.Background()
 	if os.Getenv(kubeconfigPathVariableName) == "" {
 		t.Skipf("variable %q not set, skipping kubernetes storage tests\n", kubeconfigPathVariableName)
 	}
@@ -346,7 +345,7 @@ func TestRefreshTokenLock(t *testing.T) {
 		ConnectorData: []byte(`{"some":"data"}`),
 	}
 
-	err = kubeClient.CreateRefresh(ctx, r)
+	err = kubeClient.CreateRefresh(r)
 	require.NoError(t, err)
 
 	t.Run("Timeout lock error", func(t *testing.T) {
diff --git a/storage/memory/static_test.go b/storage/memory/static_test.go
index 4be23a1e..8513e0ee 100644
--- a/storage/memory/static_test.go
+++ b/storage/memory/static_test.go
@@ -1,7 +1,6 @@
 package memory
 
 import (
-	"context"
 	"fmt"
 	"os"
 	"strings"
@@ -13,7 +12,6 @@ import (
 )
 
 func TestStaticClients(t *testing.T) {
-	ctx := context.Background()
 	logger := &logrus.Logger{
 		Out:       os.Stderr,
 		Formatter: &logrus.TextFormatter{DisableColors: true},
@@ -25,7 +23,7 @@ func TestStaticClients(t *testing.T) {
 	c2 := storage.Client{ID: "bar", Secret: "bar_secret"}
 	c3 := storage.Client{ID: "spam", Secret: "spam_secret"}
 
-	backing.CreateClient(ctx, c1)
+	backing.CreateClient(c1)
 	s := storage.WithStaticClients(backing, []storage.Client{c2})
 
 	tests := []struct {
@@ -84,7 +82,7 @@ func TestStaticClients(t *testing.T) {
 		{
 			name: "create client",
 			action: func() error {
-				return s.CreateClient(ctx, c3)
+				return s.CreateClient(c3)
 			},
 		},
 	}
@@ -101,7 +99,6 @@ func TestStaticClients(t *testing.T) {
 }
 
 func TestStaticPasswords(t *testing.T) {
-	ctx := context.Background()
 	logger := &logrus.Logger{
 		Out:       os.Stderr,
 		Formatter: &logrus.TextFormatter{DisableColors: true},
@@ -114,7 +111,7 @@ func TestStaticPasswords(t *testing.T) {
 	p3 := storage.Password{Email: "spam@example.com", Username: "spam_secret"}
 	p4 := storage.Password{Email: "Spam@example.com", Username: "Spam_secret"}
 
-	backing.CreatePassword(ctx, p1)
+	backing.CreatePassword(p1)
 	s := storage.WithStaticPasswords(backing, []storage.Password{p2}, logger)
 
 	tests := []struct {
@@ -167,10 +164,10 @@ func TestStaticPasswords(t *testing.T) {
 		{
 			name: "create passwords",
 			action: func() error {
-				if err := s.CreatePassword(ctx, p4); err != nil {
+				if err := s.CreatePassword(p4); err != nil {
 					return err
 				}
-				return s.CreatePassword(ctx, p3)
+				return s.CreatePassword(p3)
 			},
 			wantErr: true,
 		},
@@ -214,7 +211,6 @@ func TestStaticPasswords(t *testing.T) {
 }
 
 func TestStaticConnectors(t *testing.T) {
-	ctx := context.Background()
 	logger := &logrus.Logger{
 		Out:       os.Stderr,
 		Formatter: &logrus.TextFormatter{DisableColors: true},
@@ -230,7 +226,7 @@ func TestStaticConnectors(t *testing.T) {
 	c2 := storage.Connector{ID: storage.NewID(), Type: "ldap", Name: "ldap", ResourceVersion: "1", Config: config2}
 	c3 := storage.Connector{ID: storage.NewID(), Type: "saml", Name: "saml", ResourceVersion: "1", Config: config3}
 
-	backing.CreateConnector(ctx, c1)
+	backing.CreateConnector(c1)
 	s := storage.WithStaticConnectors(backing, []storage.Connector{c2})
 
 	tests := []struct {
@@ -289,7 +285,7 @@ func TestStaticConnectors(t *testing.T) {
 		{
 			name: "create connector",
 			action: func() error {
-				return s.CreateConnector(ctx, c3)
+				return s.CreateConnector(c3)
 			},
 		},
 	}