Merge pull request #1773 from faro-oss/faro-upstream/add-c_hash-to-id_token

Add c_hash to id_token, issued on /auth endpoint, when in hybrid flow
This commit is contained in:
Márk Sági-Kazár 2021-02-10 16:12:54 +01:00 committed by GitHub
commit 5a667bbee0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 9 deletions

View File

@ -681,7 +681,7 @@ func (s *Server) sendCodeResponse(w http.ResponseWriter, r *http.Request, authRe
return return
} }
idToken, idTokenExpiry, err = s.newIDToken(authReq.ClientID, authReq.Claims, authReq.Scopes, authReq.Nonce, accessToken, authReq.ConnectorID) idToken, idTokenExpiry, err = s.newIDToken(authReq.ClientID, authReq.Claims, authReq.Scopes, authReq.Nonce, accessToken, code.ID, authReq.ConnectorID)
if err != nil { if err != nil {
s.logger.Errorf("failed to create ID token: %v", err) s.logger.Errorf("failed to create ID token: %v", err)
s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError) s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
@ -868,7 +868,7 @@ func (s *Server) exchangeAuthCode(w http.ResponseWriter, authCode storage.AuthCo
return nil, err return nil, err
} }
idToken, expiry, err := s.newIDToken(client.ID, authCode.Claims, authCode.Scopes, authCode.Nonce, accessToken, authCode.ConnectorID) idToken, expiry, err := s.newIDToken(client.ID, authCode.Claims, authCode.Scopes, authCode.Nonce, accessToken, authCode.ID, authCode.ConnectorID)
if err != nil { if err != nil {
s.logger.Errorf("failed to create ID token: %v", err) s.logger.Errorf("failed to create ID token: %v", err)
s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError) s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
@ -1140,7 +1140,7 @@ func (s *Server) handleRefreshToken(w http.ResponseWriter, r *http.Request, clie
return return
} }
idToken, expiry, err := s.newIDToken(client.ID, claims, scopes, refresh.Nonce, accessToken, refresh.ConnectorID) idToken, expiry, err := s.newIDToken(client.ID, claims, scopes, refresh.Nonce, accessToken, "", refresh.ConnectorID)
if err != nil { if err != nil {
s.logger.Errorf("failed to create ID token: %v", err) s.logger.Errorf("failed to create ID token: %v", err)
s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError) s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
@ -1325,7 +1325,7 @@ func (s *Server) handlePasswordGrant(w http.ResponseWriter, r *http.Request, cli
} }
accessToken := storage.NewID() accessToken := storage.NewID()
idToken, expiry, err := s.newIDToken(client.ID, claims, scopes, nonce, accessToken, connID) idToken, expiry, err := s.newIDToken(client.ID, claims, scopes, nonce, accessToken, "", connID)
if err != nil { if err != nil {
s.tokenErrHelper(w, errServerError, fmt.Sprintf("failed to create ID token: %v", err), http.StatusInternalServerError) s.tokenErrHelper(w, errServerError, fmt.Sprintf("failed to create ID token: %v", err), http.StatusInternalServerError)
return return

View File

@ -230,11 +230,11 @@ func accessTokenHash(alg jose.SignatureAlgorithm, accessToken string) (string, e
return "", fmt.Errorf("unsupported signature algorithm: %s", alg) return "", fmt.Errorf("unsupported signature algorithm: %s", alg)
} }
hash := newHash() hashFunc := newHash()
if _, err := io.WriteString(hash, accessToken); err != nil { if _, err := io.WriteString(hashFunc, accessToken); err != nil {
return "", fmt.Errorf("computing hash: %v", err) return "", fmt.Errorf("computing hash: %v", err)
} }
sum := hash.Sum(nil) sum := hashFunc.Sum(nil)
return base64.RawURLEncoding.EncodeToString(sum[:len(sum)/2]), nil return base64.RawURLEncoding.EncodeToString(sum[:len(sum)/2]), nil
} }
@ -266,6 +266,7 @@ type idTokenClaims struct {
Nonce string `json:"nonce,omitempty"` Nonce string `json:"nonce,omitempty"`
AccessTokenHash string `json:"at_hash,omitempty"` AccessTokenHash string `json:"at_hash,omitempty"`
CodeHash string `json:"c_hash,omitempty"`
Email string `json:"email,omitempty"` Email string `json:"email,omitempty"`
EmailVerified *bool `json:"email_verified,omitempty"` EmailVerified *bool `json:"email_verified,omitempty"`
@ -284,11 +285,11 @@ type federatedIDClaims struct {
} }
func (s *Server) newAccessToken(clientID string, claims storage.Claims, scopes []string, nonce, connID string) (accessToken string, err error) { func (s *Server) newAccessToken(clientID string, claims storage.Claims, scopes []string, nonce, connID string) (accessToken string, err error) {
idToken, _, err := s.newIDToken(clientID, claims, scopes, nonce, storage.NewID(), connID) idToken, _, err := s.newIDToken(clientID, claims, scopes, nonce, storage.NewID(), "", connID)
return idToken, err return idToken, err
} }
func (s *Server) newIDToken(clientID string, claims storage.Claims, scopes []string, nonce, accessToken, connID string) (idToken string, expiry time.Time, err error) { func (s *Server) newIDToken(clientID string, claims storage.Claims, scopes []string, nonce, accessToken, code, connID string) (idToken string, expiry time.Time, err error) {
keys, err := s.storage.GetKeys() keys, err := s.storage.GetKeys()
if err != nil { if err != nil {
s.logger.Errorf("Failed to get keys: %v", err) s.logger.Errorf("Failed to get keys: %v", err)
@ -335,6 +336,15 @@ func (s *Server) newIDToken(clientID string, claims storage.Claims, scopes []str
tok.AccessTokenHash = atHash tok.AccessTokenHash = atHash
} }
if code != "" {
cHash, err := accessTokenHash(signingAlg, code)
if err != nil {
s.logger.Errorf("error computing c_hash: %v", err)
return "", expiry, fmt.Errorf("error computing c_hash: #{err}")
}
tok.CodeHash = cHash
}
for _, scope := range scopes { for _, scope := range scopes {
switch { switch {
case scope == scopeEmail: case scope == scopeEmail: