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:
		@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user