add dex config flag for enabling client secret encryption

* if enabled, it will make sure client secret is bcrypted correctly
* if not, it falls back to old behaviour that allowing empty client
secret and comparing plain text, though now it will do
ConstantTimeCompare to avoid a timing attack.

So in either way it should provide more secure of client secret
verification.

Co-authored-by: Alex Surraci <suraci.alex@gmail.com>
Signed-off-by: Rui Yang <ruiya@vmware.com>
This commit is contained in:
Rui Yang
2020-09-25 11:59:42 -04:00
committed by CI Bot
parent ec6f3a2f19
commit d658c24e8f
3 changed files with 200 additions and 15 deletions

View File

@@ -2,6 +2,7 @@ package server
import (
"crypto/sha256"
"crypto/subtle"
"encoding/base64"
"encoding/json"
"errors"
@@ -681,22 +682,21 @@ func (s *Server) handleToken(w http.ResponseWriter, r *http.Request) {
return
}
if client.Secret != clientSecret {
if clientSecret == "" {
s.logger.Infof("missing client_secret on token request for client: %s", client.ID)
} else {
s.logger.Infof("invalid client_secret on token request for client: %s", client.ID)
if s.hashClientSecret {
if err := bcrypt.CompareHashAndPassword([]byte(client.Secret), []byte(clientSecret)); err != nil {
s.tokenErrHelper(w, errInvalidClient, "Invalid client credentials.", http.StatusUnauthorized)
return
}
} else {
if subtle.ConstantTimeCompare([]byte(client.Secret), []byte(clientSecret)) != 1 {
if clientSecret == "" {
s.logger.Infof("missing client_secret on token request for client: %s", client.ID)
} else {
s.logger.Infof("invalid client_secret on token request for client: %s", client.ID)
}
s.tokenErrHelper(w, errInvalidClient, "Invalid client credentials.", http.StatusUnauthorized)
return
}
}
if err := checkCost([]byte(client.Secret)); err != nil {
s.logger.Errorf("failed to check cost of client secret: %v", err)
s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
return
}
if err := bcrypt.CompareHashAndPassword([]byte(client.Secret), []byte(clientSecret)); err != nil {
s.tokenErrHelper(w, errInvalidClient, "Invalid client credentials.", http.StatusUnauthorized)
return
}
grantType := r.PostFormValue("grant_type")