Skip to content

Commit

Permalink
feat: Add support for configurable prompt type for Google connector (d…
Browse files Browse the repository at this point in the history
…exidp#3475)

Signed-off-by: abhisek <abhisek.datta@gmail.com>
Signed-off-by: Maksim Nabokikh <max.nabokih@gmail.com>
Co-authored-by: Maksim Nabokikh <max.nabokih@gmail.com>
  • Loading branch information
abhisek and nabokihms authored Apr 15, 2024
1 parent 1ca4583 commit 677ab36
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 2 deletions.
14 changes: 13 additions & 1 deletion connector/google/google.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ type Config struct {

// If this field is true, fetch direct group membership and transitive group membership
FetchTransitiveGroupMembership bool `json:"fetchTransitiveGroupMembership"`

// Optional value for the prompt parameter, defaults to consent when offline_access
// scope is requested
PromptType *string `json:"promptType"`
}

// Open returns a connector which can be used to login users through Google.
Expand Down Expand Up @@ -107,6 +111,11 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
}
}

promptType := "consent"
if c.PromptType != nil {
promptType = *c.PromptType
}

clientID := c.ClientID
return &googleConnector{
redirectURI: c.RedirectURI,
Expand All @@ -128,6 +137,7 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
domainToAdminEmail: c.DomainToAdminEmail,
fetchTransitiveGroupMembership: c.FetchTransitiveGroupMembership,
adminSrv: adminSrv,
promptType: promptType,
}, nil
}

Expand All @@ -148,6 +158,7 @@ type googleConnector struct {
domainToAdminEmail map[string]string
fetchTransitiveGroupMembership bool
adminSrv map[string]*admin.Service
promptType string
}

func (c *googleConnector) Close() error {
Expand All @@ -170,8 +181,9 @@ func (c *googleConnector) LoginURL(s connector.Scopes, callbackURL, state string
}

if s.OfflineAccess {
opts = append(opts, oauth2.AccessTypeOffline, oauth2.SetAuthURLParam("prompt", "consent"))
opts = append(opts, oauth2.AccessTypeOffline, oauth2.SetAuthURLParam("prompt", c.promptType))
}

return c.oauth2Config.AuthCodeURL(state, opts...), nil
}

Expand Down
60 changes: 60 additions & 0 deletions connector/google/google_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import (
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"os"
"testing"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
admin "google.golang.org/api/admin/directory/v1"
"google.golang.org/api/option"

"github.com/dexidp/dex/connector"
)

var (
Expand Down Expand Up @@ -291,3 +294,60 @@ func TestDomainToAdminEmailConfig(t *testing.T) {
})
}
}

func TestPromptTypeConfig(t *testing.T) {
promptTypeLogin := "login"
cases := []struct {
name string
promptType *string
expectedPromptTypeValue string
}{
{
name: "prompt type is nil",
promptType: nil,
expectedPromptTypeValue: "consent",
},
{
name: "prompt type is empty",
promptType: new(string),
expectedPromptTypeValue: "",
},
{
name: "prompt type is set",
promptType: &promptTypeLogin,
expectedPromptTypeValue: "login",
},
}

ts := testSetup()
defer ts.Close()

serviceAccountFilePath, err := tempServiceAccountKey()
assert.Nil(t, err)

os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", serviceAccountFilePath)

for _, test := range cases {
t.Run(test.name, func(t *testing.T) {
conn, err := newConnector(&Config{
ClientID: "testClient",
ClientSecret: "testSecret",
RedirectURI: ts.URL + "/callback",
Scopes: []string{"openid", "groups", "offline_access"},
DomainToAdminEmail: map[string]string{"dexidp.com": "admin@dexidp.com"},
PromptType: test.promptType,
})

assert.Nil(t, err)
assert.Equal(t, test.expectedPromptTypeValue, conn.promptType)

loginURL, err := conn.LoginURL(connector.Scopes{OfflineAccess: true}, ts.URL+"/callback", "state")
assert.Nil(t, err)

urlp, err := url.Parse(loginURL)
assert.Nil(t, err)

assert.Equal(t, test.expectedPromptTypeValue, urlp.Query().Get("prompt"))
})
}
}
2 changes: 1 addition & 1 deletion connector/oidc/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ type Config struct {

UserNameKey string `json:"userNameKey"`

// PromptType will be used fot the prompt parameter (when offline_access, by default prompt=consent)
// PromptType will be used for the prompt parameter (when offline_access, by default prompt=consent)
PromptType *string `json:"promptType"`

// OverrideClaimMapping will be used to override the options defined in claimMappings.
Expand Down

0 comments on commit 677ab36

Please sign in to comment.