Unverified Commit 7633029c authored by Dave Walker's avatar Dave Walker Committed by GitHub
Browse files

Remap Google IDs for new auth flow. (#1035)

parent c7d34a89
Loading
Loading
Loading
Loading

CHANGELOG.md

100644 → 100755
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr
## [Unreleased]
### Fixed
- Correct cursor usage in group listings using only open/closed group state filter.
- Remap original Google IDs to "next generation player IDs" 

## [3.16.0] - 2023-04-18
### Added
+21 −2
Original line number Diff line number Diff line
@@ -624,6 +624,15 @@ func AuthenticateGameCenter(ctx context.Context, logger *zap.Logger, db *sql.DB,
	return userID, username, true, nil
}

func RemapGoogleId(ctx context.Context, logger *zap.Logger, db *sql.DB, googleProfile social.GoogleProfile) error {
	// Look for an account with original ID if different, and remap to new ID
	var err error = nil
	if len(googleProfile.GetOriginalGoogleId()) > 0 && googleProfile.GetGoogleId() != googleProfile.GetOriginalGoogleId() {
		_, err = db.ExecContext(ctx, "UPDATE users SET google_id = $1 where google_id = $2", googleProfile.GetGoogleId(), googleProfile.GetOriginalGoogleId())
	}
	return err
}

func AuthenticateGoogle(ctx context.Context, logger *zap.Logger, db *sql.DB, client *social.Client, idToken, username string, create bool) (string, string, bool, error) {
	googleProfile, err := client.CheckGoogleToken(ctx, idToken)
	if err != nil {
@@ -641,10 +650,20 @@ func AuthenticateGoogle(ctx context.Context, logger *zap.Logger, db *sql.DB, cli
	var dbAvatarURL sql.NullString
	err = db.QueryRowContext(ctx, query, googleProfile.GetGoogleId()).Scan(&dbUserID, &dbUsername, &dbDisableTime, &dbDisplayName, &dbAvatarURL)
	if err != nil {
		if err == sql.ErrNoRows {
			err = RemapGoogleId(ctx, logger, db, googleProfile)
			if err == nil {
				err = db.QueryRowContext(ctx, query, googleProfile.GetGoogleId()).Scan(&dbUserID, &dbUsername, &dbDisableTime, &dbDisplayName, &dbAvatarURL)
			}
		}

		if err == sql.ErrNoRows {
			found = false
		} else {
			logger.Error("Error looking up user by Google ID.", zap.Error(err), zap.String("googleID", googleProfile.GetGoogleId()), zap.String("username", username), zap.Bool("create", create))
		} else if err != nil {
			logger.Error("Error looking up user by Google ID.", zap.Error(err),
				zap.String("googleID", googleProfile.GetGoogleId()),
				zap.String("originalGoogleID", googleProfile.GetOriginalGoogleId()),
				zap.String("username", username), zap.Bool("create", create))
			return "", "", false, status.Error(codes.Internal, "Error finding user account.")
		}
	}
+7 −0
Original line number Diff line number Diff line
@@ -355,6 +355,13 @@ func LinkGoogle(ctx context.Context, logger *zap.Logger, db *sql.DB, socialClien
		avatarURL = ""
	}

	err = RemapGoogleId(ctx, logger, db, googleProfile)
	if err != nil {
		logger.Error("Could not remap Google ID.", zap.Error(err), zap.String("googleId", googleProfile.GetGoogleId()),
			zap.String("originalGoogleId", googleProfile.GetOriginalGoogleId()), zap.Any("input", idToken))
		return status.Error(codes.Internal, "Error while trying to link Google ID.")
	}

	res, err := db.ExecContext(ctx, `
UPDATE users AS u
SET google_id = $2, display_name = COALESCE(NULLIF(u.display_name, ''), $3), avatar_url = COALESCE(NULLIF(u.avatar_url, ''), $4), update_time = now()
+8 −0
Original line number Diff line number Diff line
@@ -291,6 +291,7 @@ func UnlinkGameCenter(ctx context.Context, logger *zap.Logger, db *sql.DB, socia
}

func UnlinkGoogle(ctx context.Context, logger *zap.Logger, db *sql.DB, socialClient *social.Client, id uuid.UUID, token string) error {

	params := []any{id}
	query := `UPDATE users SET google_id = NULL, update_time = now() WHERE id = $1`

@@ -302,6 +303,13 @@ func UnlinkGoogle(ctx context.Context, logger *zap.Logger, db *sql.DB, socialCli
		}
		params = append(params, googleProfile.GetGoogleId())
		query = query + ` AND google_id = $2`

		err = RemapGoogleId(ctx, logger, db, googleProfile)
		if err != nil {
			logger.Error("Could not remap Google ID.", zap.Error(err), zap.String("googleId", googleProfile.GetGoogleId()),
				zap.String("originalGoogleId", googleProfile.GetOriginalGoogleId()), zap.Any("input", token))
			return status.Error(codes.Internal, "Error while trying to unlink Google ID.")
		}
	}

	query = query +
+14 −4
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ type GoogleProfile interface {
	GetEmail() string
	GetAvatarImageUrl() string
	GetGoogleId() string
	GetOriginalGoogleId() string
}

// JWTGoogleProfile is an abbreviated version of a Google profile extracted from a verified JWT token.
@@ -160,11 +161,17 @@ func (p *JWTGoogleProfile) GetGoogleId() string {
	return p.Sub
}

func (p *JWTGoogleProfile) GetOriginalGoogleId() string {
	// Dummy implementation
	return ""
}

// GooglePlayServiceProfile is an abbreviated version of a Google profile using an access token.
type GooglePlayServiceProfile struct {
	PlayerId         string `json:"playerId"`
	DisplayName      string `json:"displayName"`
	AvatarImageUrl   string `json:"avatarImageUrl"`
	OriginalPlayerId string `json:"originalPlayerId"`
}

func (p *GooglePlayServiceProfile) GetDisplayName() string {
@@ -180,6 +187,9 @@ func (p *GooglePlayServiceProfile) GetAvatarImageUrl() string {
func (p *GooglePlayServiceProfile) GetGoogleId() string {
	return p.PlayerId
}
func (p *GooglePlayServiceProfile) GetOriginalGoogleId() string {
	return p.OriginalPlayerId
}

// SteamProfile is an abbreviated version of a Steam profile.
type SteamProfile struct {
@@ -416,7 +426,7 @@ func (c *Client) CheckGoogleToken(ctx context.Context, idToken string) (GooglePr

	// All verification attempts failed.
	if token == nil {
		// The id provided could be from the new auth flow. Let's exchahge it for a token.
		// The id provided could be from the new auth flow. Let's exchange it for a token.
		t, err := c.exchangeGoogleAuthCode(ctx, idToken)
		if err != nil {
			c.logger.Debug("Failed to exchange an authorization code for an access token.", zap.String("auth_token", idToken), zap.Error(err))