github.com/greenpau/go-authcrunch@v1.1.4/pkg/authn/handle_http_portal.go (about)

     1  // Copyright 2022 Paul Greenberg greenpau@outlook.com
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package authn
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"net/http"
    21  	"net/url"
    22  	"strings"
    23  
    24  	"github.com/greenpau/go-authcrunch/pkg/requests"
    25  	"github.com/greenpau/go-authcrunch/pkg/user"
    26  	addrutil "github.com/greenpau/go-authcrunch/pkg/util/addr"
    27  	"go.uber.org/zap"
    28  )
    29  
    30  func getEndpoint(p, s string) (string, error) {
    31  	i := strings.Index(p, s)
    32  	if i < 0 {
    33  		return s, fmt.Errorf("%s is not in %s", p, s)
    34  	}
    35  	return strings.TrimPrefix(p[i:], s), nil
    36  }
    37  
    38  func getEndpointKeyID(p, s string) (string, error) {
    39  	sp, err := getEndpoint(p, s)
    40  	if err != nil {
    41  		return "", err
    42  	}
    43  	arr := strings.Split(sp, "/")
    44  	if len(arr) != 1 {
    45  		return "", fmt.Errorf("invalid key id")
    46  	}
    47  	return arr[0], nil
    48  }
    49  
    50  func (p *Portal) handleHTTPPortal(ctx context.Context, w http.ResponseWriter, r *http.Request, rr *requests.Request, parsedUser *user.User) error {
    51  	p.disableClientCache(w)
    52  	p.injectRedirectURL(ctx, w, r, rr)
    53  	if parsedUser == nil {
    54  		return p.handleHTTPRedirect(ctx, w, r, rr, "/login")
    55  	}
    56  	usr, err := p.sessions.Get(parsedUser.Claims.ID)
    57  	if err != nil {
    58  		p.deleteAuthCookies(w, r)
    59  		p.logger.Debug(
    60  			"User session not found, redirect to login",
    61  			zap.String("session_id", rr.Upstream.SessionID),
    62  			zap.String("request_id", rr.ID),
    63  			zap.Any("user", parsedUser.Claims),
    64  			zap.Error(err),
    65  		)
    66  		return p.handleHTTPRedirect(ctx, w, r, rr, "/login")
    67  	}
    68  	return p.handleHTTPPortalScreen(ctx, w, r, rr, usr)
    69  }
    70  
    71  func (p *Portal) handleHTTPPortalScreen(ctx context.Context, w http.ResponseWriter, r *http.Request, rr *requests.Request, usr *user.User) error {
    72  	if cookie, err := r.Cookie(p.cookie.Referer); err == nil {
    73  		redirectURL, err := url.Parse(cookie.Value)
    74  		if err == nil {
    75  			p.logger.Debug(
    76  				"Cookie-based redirect",
    77  				zap.String("session_id", rr.Upstream.SessionID),
    78  				zap.String("request_id", rr.ID),
    79  				zap.String("redirect_url", redirectURL.String()),
    80  			)
    81  			w.Header().Set("Location", redirectURL.String())
    82  			w.Header().Add("Set-Cookie", p.cookie.GetDeleteCookie(addrutil.GetSourceHost(r), p.cookie.Referer))
    83  			w.WriteHeader(http.StatusSeeOther)
    84  			return nil
    85  		}
    86  	}
    87  	resp := p.ui.GetArgs()
    88  	resp.BaseURL(rr.Upstream.BasePath)
    89  	resp.PageTitle = "Applications"
    90  	if len(usr.FrontendLinks) > 0 {
    91  		// Add additional frontend links.
    92  		resp.AddFrontendLinks(usr.FrontendLinks)
    93  	}
    94  	content, err := p.ui.Render("portal", resp)
    95  	if err != nil {
    96  		return p.handleHTTPRenderError(ctx, w, r, rr, err)
    97  	}
    98  	return p.handleHTTPRenderHTML(ctx, w, http.StatusOK, content.Bytes())
    99  }