Skip to content

Commit

Permalink
fix: offline access for google (#2502)
Browse files Browse the repository at this point in the history
- ensure we always get refresh token from google oidc
  • Loading branch information
BruceMacD committed Jul 7, 2022
1 parent 337a9eb commit 898ba7c
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 4 deletions.
22 changes: 18 additions & 4 deletions internal/cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,15 +294,13 @@ func oidcflow(provider *api.Provider) (string, error) {
return "", err
}

authorizeURL := fmt.Sprintf("%s?redirect_uri=http://localhost:8301&client_id=%s&response_type=code&scope=%s&state=%s", provider.AuthURL, provider.ClientID, strings.Join(provider.Scopes, "+"), state)

// the local server receives the response from the identity provider and sends it along to the infra server
ls, err := newLocalServer()
if err != nil {
return "", err
}

err = browser.OpenURL(authorizeURL)
err = browser.OpenURL(authURLForProvider(*provider, state))
if err != nil {
return "", err
}
Expand All @@ -313,7 +311,6 @@ func oidcflow(provider *api.Provider) (string, error) {
}

if state != recvstate {
//lint:ignore ST1005, user facing error
return "", Error{Message: "Login aborted, provider state did not match the expected state"}
}

Expand Down Expand Up @@ -724,3 +721,20 @@ PROMPT:

return email, nil
}

// authURLForProvider builds an authorization URL that will get the information we need from an identity provider
func authURLForProvider(provider api.Provider, state string) string {
// build the authorization query parameters based on attributes of the provider
params := url.Values{}
params.Add("redirect_uri", "http://localhost:8301") // where to send the access codes after the user logs in with an IDP
if provider.Kind == "google" {
params.Add("prompt", "consent") // google only sends a refresh token when a user consents, always prompt so we always get the ref token
params.Add("access_type", "offline") // specifies that we want a refresh token
}
params.Add("client_id", provider.ClientID)
params.Add("response_type", "code")
params.Add("scope", strings.Join(provider.Scopes, " "))
params.Add("state", state)

return fmt.Sprintf("%s?%s", provider.AuthURL, params.Encode())
}
38 changes: 38 additions & 0 deletions internal/cmd/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -503,3 +503,41 @@ func TestLoginCmd_TLSVerify(t *testing.T) {
golden.Assert(t, bufs.Stderr.String(), t.Name())
})
}

func TestAuthURLForProvider(t *testing.T) {
expectedOktaAuthURL := "https://okta.example.com/oauth2/v1/authorize?client_id=001&redirect_uri=http%3A%2F%2Flocalhost%3A8301&response_type=code&scope=email+openid&state=state"
okta := api.Provider{
AuthURL: "https://okta.example.com/oauth2/v1/authorize",
ClientID: "001",
Kind: "okta",
Scopes: []string{
"email",
"openid",
},
}
assert.Equal(t, authURLForProvider(okta, "state"), expectedOktaAuthURL)

expectedAzureAuthURL := "https://login.microsoftonline.com/0/oauth2/v2.0/authorize?client_id=001&redirect_uri=http%3A%2F%2Flocalhost%3A8301&response_type=code&scope=email+openid&state=state"
azure := api.Provider{
AuthURL: "https://login.microsoftonline.com/0/oauth2/v2.0/authorize",
ClientID: "001",
Kind: "azure",
Scopes: []string{
"email",
"openid",
},
}
assert.Equal(t, authURLForProvider(azure, "state"), expectedAzureAuthURL)

expectedGoogleAuthURL := "https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&client_id=001&prompt=consent&redirect_uri=http%3A%2F%2Flocalhost%3A8301&response_type=code&scope=email+openid&state=state"
google := api.Provider{
AuthURL: "https://accounts.google.com/o/oauth2/v2/auth",
ClientID: "001",
Kind: "google",
Scopes: []string{
"email",
"openid",
},
}
assert.Equal(t, authURLForProvider(google, "state"), expectedGoogleAuthURL)
}

0 comments on commit 898ba7c

Please sign in to comment.