Browse Source

feat: Add support for configurable prompt type for Google connector (#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>
pull/2039/merge
Abhisek Datta 2 years ago committed by GitHub
parent
commit
677ab36020
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 14
      connector/google/google.go
  2. 60
      connector/google/google_test.go
  3. 2
      connector/oidc/oidc.go

14
connector/google/google.go

@ -58,6 +58,10 @@ type Config struct {
// If this field is true, fetch direct group membership and transitive group membership // If this field is true, fetch direct group membership and transitive group membership
FetchTransitiveGroupMembership bool `json:"fetchTransitiveGroupMembership"` 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. // Open returns a connector which can be used to login users through Google.
@ -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 clientID := c.ClientID
return &googleConnector{ return &googleConnector{
redirectURI: c.RedirectURI, redirectURI: c.RedirectURI,
@ -128,6 +137,7 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
domainToAdminEmail: c.DomainToAdminEmail, domainToAdminEmail: c.DomainToAdminEmail,
fetchTransitiveGroupMembership: c.FetchTransitiveGroupMembership, fetchTransitiveGroupMembership: c.FetchTransitiveGroupMembership,
adminSrv: adminSrv, adminSrv: adminSrv,
promptType: promptType,
}, nil }, nil
} }
@ -148,6 +158,7 @@ type googleConnector struct {
domainToAdminEmail map[string]string domainToAdminEmail map[string]string
fetchTransitiveGroupMembership bool fetchTransitiveGroupMembership bool
adminSrv map[string]*admin.Service adminSrv map[string]*admin.Service
promptType string
} }
func (c *googleConnector) Close() error { func (c *googleConnector) Close() error {
@ -170,8 +181,9 @@ func (c *googleConnector) LoginURL(s connector.Scopes, callbackURL, state string
} }
if s.OfflineAccess { 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 return c.oauth2Config.AuthCodeURL(state, opts...), nil
} }

60
connector/google/google_test.go

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"net/url"
"os" "os"
"testing" "testing"
@ -13,6 +14,8 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
admin "google.golang.org/api/admin/directory/v1" admin "google.golang.org/api/admin/directory/v1"
"google.golang.org/api/option" "google.golang.org/api/option"
"github.com/dexidp/dex/connector"
) )
var ( var (
@ -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
connector/oidc/oidc.go

@ -75,7 +75,7 @@ type Config struct {
UserNameKey string `json:"userNameKey"` 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"` PromptType *string `json:"promptType"`
// OverrideClaimMapping will be used to override the options defined in claimMappings. // OverrideClaimMapping will be used to override the options defined in claimMappings.

Loading…
Cancel
Save