Skip to content

Commit db73b1d

Browse files
committed
fix pkce implementation
Initial implementation was using the same verifier during the lifetime of the agent instance. Now instanciated a pkce verifier at each authorization.
1 parent d1e3d03 commit db73b1d

File tree

3 files changed

+24
-4
lines changed

3 files changed

+24
-4
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.22
55
require (
66
github.com/coreos/go-oidc/v3 v3.11.0
77
github.com/go-ldap/ldap/v3 v3.4.8
8+
github.com/go-pkgz/expirable-cache/v3 v3.0.0
89
github.com/negasus/haproxy-spoe-go v1.0.5
910
github.com/sirupsen/logrus v1.9.3
1011
github.com/spf13/viper v1.19.0

go.sum

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0
3232
github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
3333
github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ=
3434
github.com/go-ldap/ldap/v3 v3.4.8/go.mod h1:qS3Sjlu76eHfHGpUdWkAXQTw4beih+cHsco2jXlIXrk=
35+
github.com/go-pkgz/expirable-cache/v3 v3.0.0 h1:u3/gcu3sabLYiTCevoRKv+WzjIn5oo7P8XtiXBeRDLw=
36+
github.com/go-pkgz/expirable-cache/v3 v3.0.0/go.mod h1:2OQiDyEGQalYecLWmXprm3maPXeVb5/6/X7yRPYTzec=
3537
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
3638
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
3739
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@@ -61,6 +63,9 @@ github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/C
6163
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
6264
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
6365
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
66+
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
67+
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
68+
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
6469
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
6570
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
6671
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=

internal/auth/authenticator_oidc.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/vmihailenco/msgpack/v5"
1616

1717
"github.com/coreos/go-oidc/v3/oidc"
18+
cache "github.com/go-pkgz/expirable-cache/v3"
1819
action "github.com/negasus/haproxy-spoe-go/action"
1920
message "github.com/negasus/haproxy-spoe-go/message"
2021

@@ -74,7 +75,7 @@ type OIDCAuthenticator struct {
7475

7576
signatureComputer *HmacSha256Computer
7677
encryptor *AESEncryptor
77-
pkceVerifier string
78+
pkceVerifierCache cache.Cache[string, string]
7879

7980
options OIDCAuthenticatorOptions
8081
}
@@ -120,7 +121,7 @@ func NewOIDCAuthenticator(options OIDCAuthenticatorOptions) *OIDCAuthenticator {
120121
options: options,
121122
signatureComputer: NewHmacSha256Computer(options.SignatureSecret),
122123
encryptor: NewAESEncryptor(options.EncryptionSecret),
123-
pkceVerifier: oauth2.GenerateVerifier(),
124+
pkceVerifierCache: cache.NewCache[string, string](),
124125
}
125126

126127
go func() {
@@ -396,8 +397,15 @@ func (oa *OIDCAuthenticator) buildAuthorizationURL(domain string, oauthArgs OAut
396397
}
397398

398399
var authorizationURL string
400+
pkceVerifier := oauth2.GenerateVerifier()
401+
stateStr := base64.StdEncoding.EncodeToString(stateBytes)
402+
cacheTTL := time.Second * 3600
403+
if oa.options.CookieTTL != 0 {
404+
cacheTTL = oa.options.CookieTTL
405+
}
406+
oa.pkceVerifierCache.Set(stateStr, pkceVerifier, cacheTTL)
399407
err = oa.withOAuth2Config(domain, func(config oauth2.Config) error {
400-
authorizationURL = config.AuthCodeURL(base64.StdEncoding.EncodeToString(stateBytes), oauth2.S256ChallengeOption(oa.pkceVerifier))
408+
authorizationURL = config.AuthCodeURL(stateStr, oauth2.S256ChallengeOption(pkceVerifier))
401409
return nil
402410
})
403411
if err != nil {
@@ -435,9 +443,15 @@ func (oa *OIDCAuthenticator) handleOAuth2Callback(tmpl *template.Template, error
435443

436444
domain := extractDomainFromHost(r.Host)
437445

446+
pkceVerifier, ok := oa.pkceVerifierCache.Get(stateB64Payload)
447+
if !ok {
448+
logrus.Error("cannot retrieve pkce verifier")
449+
http.Error(w, "Bad request", http.StatusBadRequest)
450+
return
451+
}
438452
var oauth2Token *oauth2.Token
439453
err := oa.withOAuth2Config(domain, func(config oauth2.Config) error {
440-
token, err := config.Exchange(r.Context(), r.URL.Query().Get("code"), oauth2.VerifierOption(oa.pkceVerifier))
454+
token, err := config.Exchange(r.Context(), r.URL.Query().Get("code"), oauth2.VerifierOption(pkceVerifier))
441455
oauth2Token = token
442456
return err
443457
})

0 commit comments

Comments
 (0)