Skip to content
Snippets Groups Projects
handlers.go 34.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • 		old.LastUsed = lastUsed
    
    
    	// Update LastUsed time stamp in refresh token reference object
    	// in offline session for the user.
    	if err := s.storage.UpdateOfflineSessions(refresh.Claims.UserID, refresh.ConnectorID, func(old storage.OfflineSessions) (storage.OfflineSessions, error) {
    		if old.Refresh[refresh.ClientID].ID != refresh.ID {
    			return old, errors.New("refresh token invalid")
    		}
    		old.Refresh[refresh.ClientID].LastUsed = lastUsed
    		return old, nil
    	}); err != nil {
    		s.logger.Errorf("failed to update offline session: %v", err)
    		s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
    		return
    	}
    
    	// Update refresh token in the storage.
    
    	if err := s.storage.UpdateRefreshToken(refresh.ID, updater); err != nil {
    		s.logger.Errorf("failed to update refresh token: %v", err)
    
    		s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
    
    Eric Chiang's avatar
    Eric Chiang committed
    		return
    	}
    
    	s.writeAccessToken(w, idToken, accessToken, rawNewToken, expiry)
    
    Eric Chiang's avatar
    Eric Chiang committed
    }
    
    
    func (s *Server) writeAccessToken(w http.ResponseWriter, idToken, accessToken, refreshToken string, expiry time.Time) {
    
    Eric Chiang's avatar
    Eric Chiang committed
    	// TODO(ericchiang): figure out an access token story and support the user info
    	// endpoint. For now use a random value so no one depends on the access_token
    	// holding a specific structure.
    	resp := struct {
    		AccessToken  string `json:"access_token"`
    		TokenType    string `json:"token_type"`
    		ExpiresIn    int    `json:"expires_in"`
    		RefreshToken string `json:"refresh_token,omitempty"`
    		IDToken      string `json:"id_token"`
    	}{
    
    		accessToken,
    
    Eric Chiang's avatar
    Eric Chiang committed
    		"bearer",
    
    		int(expiry.Sub(s.now()).Seconds()),
    
    Eric Chiang's avatar
    Eric Chiang committed
    		refreshToken,
    		idToken,
    	}
    	data, err := json.Marshal(resp)
    	if err != nil {
    
    		s.logger.Errorf("failed to marshal access token response: %v", err)
    		s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
    
    Eric Chiang's avatar
    Eric Chiang committed
    		return
    	}
    	w.Header().Set("Content-Type", "application/json")
    	w.Header().Set("Content-Length", strconv.Itoa(len(data)))
    	w.Write(data)
    }
    
    
    func (s *Server) renderError(w http.ResponseWriter, status int, description string) {
    
    	if err := s.templates.err(w, status, description); err != nil {
    
    		s.logger.Errorf("Server template error: %v", err)
    	}
    
    Eric Chiang's avatar
    Eric Chiang committed
    }
    
    
    func (s *Server) tokenErrHelper(w http.ResponseWriter, typ string, description string, statusCode int) {
    	if err := tokenErr(w, typ, description, statusCode); err != nil {
    
    		s.logger.Errorf("token error response: %v", err)
    
    
    // Check for username prompt override from connector. Defaults to "Username".
    func usernamePrompt(conn connector.PasswordConnector) string {
    	if attr := conn.Prompt(); attr != "" {
    		return attr
    	}
    	return "Username"
    }