mirror of
https://github.com/drakkan/sftpgo.git
synced 2026-03-14 14:25:52 +01:00
OAuth2: add PKCE
Fixes #2134 Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
d42bbef16e
commit
21639b963c
4 changed files with 12 additions and 4 deletions
|
|
@ -120,6 +120,6 @@ func (s *httpdServer) handleSMTPOAuth2TokenRequestPost(w http.ResponseWriter, r
|
|||
sendAPIResponse(w, r, nil, "unable to create state token", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
u := cfg.AuthCodeURL(stateToken, oauth2.AccessTypeOffline)
|
||||
u := cfg.AuthCodeURL(stateToken, oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(pendingAuth.Verifier))
|
||||
sendAPIResponse(w, r, nil, u, http.StatusOK)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/drakkan/sftpgo/v2/internal/dataprovider"
|
||||
"github.com/drakkan/sftpgo/v2/internal/kms"
|
||||
"github.com/drakkan/sftpgo/v2/internal/logger"
|
||||
|
|
@ -48,6 +50,7 @@ type oauth2PendingAuth struct {
|
|||
ClientSecret *kms.Secret `json:"client_secret"`
|
||||
RedirectURL string `json:"redirect_url"`
|
||||
IssuedAt int64 `json:"issued_at"`
|
||||
Verifier string `json:"verifier"`
|
||||
}
|
||||
|
||||
func newOAuth2PendingAuth(provider int, redirectURL, clientID string, clientSecret *kms.Secret) oauth2PendingAuth {
|
||||
|
|
@ -58,6 +61,7 @@ func newOAuth2PendingAuth(provider int, redirectURL, clientID string, clientSecr
|
|||
ClientSecret: clientSecret,
|
||||
RedirectURL: redirectURL,
|
||||
IssuedAt: util.GetTimeAsMsSinceEpoch(time.Now()),
|
||||
Verifier: oauth2.GenerateVerifier(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ type oidcPendingAuth struct {
|
|||
Nonce string `json:"nonce"`
|
||||
Audience tokenAudience `json:"audience"`
|
||||
IssuedAt int64 `json:"issued_at"`
|
||||
Verifier string `json:"verifier"`
|
||||
}
|
||||
|
||||
func newOIDCPendingAuth(audience tokenAudience) oidcPendingAuth {
|
||||
|
|
@ -208,6 +209,7 @@ func newOIDCPendingAuth(audience tokenAudience) oidcPendingAuth {
|
|||
Nonce: util.GenerateOpaqueString(),
|
||||
Audience: audience,
|
||||
IssuedAt: util.GetTimeAsMsSinceEpoch(time.Now()),
|
||||
Verifier: oauth2.GenerateVerifier(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -595,7 +597,7 @@ func (s *httpdServer) oidcLoginRedirect(w http.ResponseWriter, r *http.Request,
|
|||
pendingAuth := newOIDCPendingAuth(audience)
|
||||
oidcMgr.addPendingAuth(pendingAuth)
|
||||
http.Redirect(w, r, s.binding.OIDC.oauth2Config.AuthCodeURL(pendingAuth.State,
|
||||
oidc.Nonce(pendingAuth.Nonce)), http.StatusFound)
|
||||
oidc.Nonce(pendingAuth.Nonce), oauth2.S256ChallengeOption(pendingAuth.Verifier)), http.StatusFound)
|
||||
}
|
||||
|
||||
func (s *httpdServer) debugTokenClaims(claims map[string]any, rawIDToken string) {
|
||||
|
|
@ -634,7 +636,8 @@ func (s *httpdServer) handleOIDCRedirect(w http.ResponseWriter, r *http.Request)
|
|||
ctx, cancel := context.WithTimeout(r.Context(), 20*time.Second)
|
||||
defer cancel()
|
||||
|
||||
oauth2Token, err := s.binding.OIDC.oauth2Config.Exchange(ctx, r.URL.Query().Get("code"))
|
||||
oauth2Token, err := s.binding.OIDC.oauth2Config.Exchange(ctx, r.URL.Query().Get("code"),
|
||||
oauth2.VerifierOption(authReq.Verifier))
|
||||
if err != nil {
|
||||
logger.Debug(logSender, "", "failed to exchange oidc token: %v", err)
|
||||
setFlashMessage(w, r, newFlashMessage("Failed to exchange OpenID token", util.I18nOIDCErrTokenExchange))
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import (
|
|||
|
||||
"github.com/sftpgo/sdk"
|
||||
sdkkms "github.com/sftpgo/sdk/kms"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/drakkan/sftpgo/v2/internal/acme"
|
||||
"github.com/drakkan/sftpgo/v2/internal/common"
|
||||
|
|
@ -4425,7 +4426,7 @@ func (s *httpdServer) handleOAuth2TokenRedirect(w http.ResponseWriter, r *http.R
|
|||
|
||||
cfg := oauth2Config.GetOAuth2()
|
||||
cfg.RedirectURL = pendingAuth.RedirectURL
|
||||
token, err := cfg.Exchange(ctx, r.URL.Query().Get("code"))
|
||||
token, err := cfg.Exchange(ctx, r.URL.Query().Get("code"), oauth2.VerifierOption(pendingAuth.Verifier))
|
||||
if err != nil {
|
||||
s.renderMessagePage(w, r, util.I18nOAuth2ErrorTitle, http.StatusInternalServerError,
|
||||
util.NewI18nError(err, util.I18nOAuth2ErrTokenExchange), "")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue