mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-30 02:46:30 +02:00
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.)
101 lines
3.1 KiB
Go
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)
|
|
}
|