pomerium/authenticate/identity_profile.go
Kenneth Jenkins 2f4005cc09
authenticate: remove extraneous error log (#4319)
Currently the Authenticate.storeIdentityProfile() method always emits an
Error log. If there is no error from cookieChunker.SetCookie(), this
results in an empty log entry:

    {"level":"error","time":"2023-06-27T23:56:38Z"}

Refactor this method to instead return the error from SetCookie(), and
update the calling code so that it logs a message only when this error
is non-nil.

(Moving the log call to the calling method gives access to the request
context, so the log entry will include the request ID and other related
info.)
2023-06-28 11:02:06 -07:00

101 lines
3.1 KiB
Go

package authenticate
import (
"context"
"crypto/cipher"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"golang.org/x/oauth2"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/types/known/structpb"
"github.com/pomerium/pomerium/internal/httputil"
"github.com/pomerium/pomerium/internal/identity"
"github.com/pomerium/pomerium/internal/sessions"
"github.com/pomerium/pomerium/internal/urlutil"
"github.com/pomerium/pomerium/pkg/cryptutil"
identitypb "github.com/pomerium/pomerium/pkg/grpc/identity"
)
var cookieChunker = httputil.NewCookieChunker()
func (a *Authenticate) buildIdentityProfile(
ctx context.Context,
r *http.Request,
_ *sessions.State,
claims identity.SessionClaims,
oauthToken *oauth2.Token,
) (*identitypb.Profile, error) {
options := a.options.Load()
idpID := r.FormValue(urlutil.QueryIdentityProviderID)
authenticator, err := a.cfg.getIdentityProvider(options, idpID)
if err != nil {
return nil, fmt.Errorf("authenticate: error getting identity provider authenticator: %w", err)
}
err = authenticator.UpdateUserInfo(ctx, oauthToken, &claims)
if err != nil {
return nil, fmt.Errorf("authenticate: error retrieving user info: %w", err)
}
rawIDToken := []byte(claims.RawIDToken)
rawOAuthToken, err := json.Marshal(oauthToken)
if err != nil {
return nil, fmt.Errorf("authenticate: error marshaling oauth token: %w", err)
}
rawClaims, err := structpb.NewStruct(claims.Claims)
if err != nil {
return nil, fmt.Errorf("authenticate: error creating claims struct: %w", err)
}
return &identitypb.Profile{
ProviderId: idpID,
IdToken: rawIDToken,
OauthToken: rawOAuthToken,
Claims: rawClaims,
}, nil
}
func (a *Authenticate) loadIdentityProfile(r *http.Request, aead cipher.AEAD) (*identitypb.Profile, error) {
cookie, err := cookieChunker.LoadCookie(r, urlutil.QueryIdentityProfile)
if err != nil {
return nil, fmt.Errorf("authenticate: error loading identity profile cookie: %w", err)
}
encrypted, err := base64.RawURLEncoding.DecodeString(cookie.Value)
if err != nil {
return nil, fmt.Errorf("authenticate: error decoding identity profile cookie: %w", err)
}
decrypted, err := cryptutil.Decrypt(aead, encrypted, nil)
if err != nil {
return nil, fmt.Errorf("authenticate: error decrypting identity profile cookie: %w", err)
}
var profile identitypb.Profile
err = protojson.Unmarshal(decrypted, &profile)
if err != nil {
return nil, fmt.Errorf("authenticate: error unmarshaling identity profile cookie: %w", err)
}
return &profile, nil
}
func (a *Authenticate) storeIdentityProfile(w http.ResponseWriter, aead cipher.AEAD, profile *identitypb.Profile) error {
options := a.options.Load()
decrypted, err := protojson.Marshal(profile)
if err != nil {
// this shouldn't happen
panic(fmt.Errorf("error marshaling message: %w", err))
}
encrypted := cryptutil.Encrypt(aead, decrypted, nil)
cookie := options.NewCookie()
cookie.Name = urlutil.QueryIdentityProfile
cookie.Value = base64.RawURLEncoding.EncodeToString(encrypted)
cookie.Path = "/"
return cookieChunker.SetCookie(w, cookie)
}