Skip to content

Improve connectorData flow #2728

@nabokihms

Description

@nabokihms

Preflight Checklist

  • I agree to follow the Code of Conduct that this project adheres to.
  • I have searched the issue tracker for an issue that matches the one I want to file, without success.

Problem Description

There are four places for connector data to be persisted:

  1. After successful login Dex saves connectorData to the AuthRequest object.

    dex/server/handlers.go

    Lines 485 to 490 in 6172b49

    updater := func(a storage.AuthRequest) (storage.AuthRequest, error) {
    a.LoggedIn = true
    a.Claims = claims
    a.ConnectorData = identity.ConnectorData
    return a, nil
    }

  2. And the same data is saved to the OfflineSession object.

    dex/server/handlers.go

    Lines 524 to 529 in 6172b49

    offlineSessions := storage.OfflineSessions{
    UserID: identity.UserID,
    ConnID: authReq.ConnectorID,
    Refresh: make(map[string]*storage.RefreshTokenRef),
    ConnectorData: identity.ConnectorData,
    }

    dex/server/handlers.go

    Lines 542 to 550 in 6172b49

    if err := s.storage.UpdateOfflineSessions(session.UserID, session.ConnID, func(old storage.OfflineSessions) (storage.OfflineSessions, error) {
    if len(identity.ConnectorData) > 0 {
    old.ConnectorData = identity.ConnectorData
    }
    return old, nil
    }); err != nil {
    s.logger.Errorf("failed to update offline session: %v", err)
    return "", err
    }

  3. After login, connectorData is moved from the AuthRequest object to the AuthCode object.

    dex/server/handlers.go

    Lines 654 to 664 in 6172b49

    code = storage.AuthCode{
    ID: storage.NewID(),
    ClientID: authReq.ClientID,
    ConnectorID: authReq.ConnectorID,
    Nonce: authReq.Nonce,
    Scopes: authReq.Scopes,
    Claims: authReq.Claims,
    Expiry: s.now().Add(time.Minute * 30),
    RedirectURI: authReq.RedirectURI,
    ConnectorData: authReq.ConnectorData,
    PKCE: authReq.PKCE,

  4. Then connectorData is saved from the AuthCode object to the RefreshToken object.

    dex/server/handlers.go

    Lines 938 to 949 in 6172b49

    refresh := storage.RefreshToken{
    ID: storage.NewID(),
    Token: storage.NewID(),
    ClientID: authCode.ClientID,
    ConnectorID: authCode.ConnectorID,
    Scopes: authCode.Scopes,
    Claims: authCode.Claims,
    Nonce: authCode.Nonce,
    ConnectorData: authCode.ConnectorData,
    CreatedAt: s.now(),
    LastUsed: s.now(),
    }

Bonus: On the first refresh token update connectorData is deleted from the RefreshToken object.

Proposed Solution

Connector data is a fundamental thing for connectors that refresh tokens. Connector data can contain refresh tokens of other providers or access tokens. Providers like Gitlab or some OIDC providers can punish users for using the stale connector data, leading to the loss of the refresh token issued by Dex.

It seems that connector data should only be saved to the offline session after login finalizing and nowhere else. It is possible to skip stages 1, 3, and 4.

Alternatives Considered

No response

Additional Information

Maybe it is also good to consider having connector data per refresh token because it makes more sense to map provider refresh tokens and dex refresh tokens like 1:1.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions