Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [unreleased]

### Fixes:
- Fixes JWKS Keyfunc call that resulted in a goroutine leak: https://github.com/supertokens/supertokens-golang/issues/155

## [0.8.1] - 2022-07-12

### Fixes:
Expand Down
9 changes: 1 addition & 8 deletions recipe/thirdparty/providers/apple.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"strings"
"time"

"github.com/MicahParks/keyfunc"
"github.com/golang-jwt/jwt/v4"
"github.com/supertokens/supertokens-golang/recipe/thirdparty/api"
"github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels"
Expand Down Expand Up @@ -177,14 +176,8 @@ func verifyAndGetClaimsAppleIdToken(idToken string, clientId string) (jwt.MapCla
// Get the JWKS URL.
jwksURL := "https://appleid.apple.com/auth/keys"

// Create the keyfunc options. Refresh the JWKS every hour and log errors.
refreshInterval := time.Hour
options := keyfunc.Options{
RefreshInterval: refreshInterval,
}

// Create the JWKS from the resource at the given URL.
jwks, err := keyfunc.Get(jwksURL, options)
jwks, err := getJWKSFromURL(jwksURL)
if err != nil {
return claims, err
}
Expand Down
10 changes: 1 addition & 9 deletions recipe/thirdparty/providers/googleWorkspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ package providers
import (
"errors"
"strings"
"time"

"github.com/MicahParks/keyfunc"
"github.com/golang-jwt/jwt/v4"
"github.com/supertokens/supertokens-golang/recipe/thirdparty/api"
"github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels"
Expand Down Expand Up @@ -140,14 +138,8 @@ func verifyAndGetClaims(idToken string, clientId string) (jwt.MapClaims, error)
// Get the JWKS URL.
jwksURL := "https://www.googleapis.com/oauth2/v3/certs"

// Create the keyfunc options. Refresh the JWKS every hour and log errors.
refreshInterval := time.Hour
options := keyfunc.Options{
RefreshInterval: refreshInterval,
}

// Create the JWKS from the resource at the given URL.
jwks, err := keyfunc.Get(jwksURL, options)
jwks, err := getJWKSFromURL(jwksURL)
if err != nil {
return claims, err
}
Expand Down
31 changes: 31 additions & 0 deletions recipe/thirdparty/providers/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import (
"fmt"
"io/ioutil"
"net/http"
"sync"
"time"

"github.com/MicahParks/keyfunc"
)

func doGetRequest(req *http.Request) (interface{}, error) {
Expand All @@ -47,3 +51,30 @@ func doGetRequest(req *http.Request) (interface{}, error) {
}
return result, nil
}

var jwksKeys = map[string]*keyfunc.JWKS{}
var jwksKeysLock = sync.Mutex{}

func getJWKSFromURL(url string) (*keyfunc.JWKS, error) {
if jwks, ok := jwksKeys[url]; ok {
return jwks, nil
}

jwksKeysLock.Lock()
defer jwksKeysLock.Unlock()

// Check again to see if it was added while we were waiting for the lock
if jwks, ok := jwksKeys[url]; ok {
return jwks, nil
}

options := keyfunc.Options{
RefreshInterval: time.Hour,
}
jwks, err := keyfunc.Get(url, options)
if err != nil {
return nil, err
}
jwksKeys[url] = jwks
return jwks, nil
}