feat: include prompt=select_account in back link for multiple connectors (#4694)

Signed-off-by: maksim.nabokikh <max.nabokih@gmail.com>
Signed-off-by: Maksim Nabokikh <max.nabokih@gmail.com>
This commit is contained in:
Maksim Nabokikh
2026-03-30 16:12:04 +02:00
committed by GitHub
parent 8031f5b1ca
commit bc8f045ad8
2 changed files with 58 additions and 1 deletions
+9 -1
View File
@@ -10,6 +10,7 @@ import (
"errors"
"fmt"
"html/template"
"maps"
"net/http"
"net/url"
"path"
@@ -464,11 +465,18 @@ func (s *Server) handleConnectorLogin(w http.ResponseWriter, r *http.Request) {
scopes := parseScopes(authReq.Scopes)
// Work out where the "Select another login method" link should go.
// Include prompt=select_account so that handleAuthorization skips
// session-based connector reuse and shows the connector list.
backLink := ""
if len(s.connectors) > 1 {
backLinkParams := make(url.Values)
maps.Copy(backLinkParams, r.Form)
if s.sessionConfig != nil {
backLinkParams.Set("prompt", "select_account")
}
backLinkURL := url.URL{
Path: s.absPath("/auth"),
RawQuery: r.Form.Encode(),
RawQuery: backLinkParams.Encode(),
}
backLink = backLinkURL.String()
}
+49
View File
@@ -2074,3 +2074,52 @@ func TestHandleAuthorizationWithoutAllowedConnectors(t *testing.T) {
// With multiple connectors and no filter, the login page should be rendered (200 OK)
require.Equal(t, http.StatusOK, rr.Code)
}
func TestBackLinkIncludesPromptSelectAccount(t *testing.T) {
ctx := t.Context()
httpServer, s := newTestServerMultipleConnectors(t, nil)
defer httpServer.Close()
// select_account prompt only works with the sessions feature flag enabled.
s.sessionConfig = &SessionConfig{}
// Add a password connector so handleConnectorLogin passes the backlink via redirect.
pwConn := storage.Connector{
ID: "mockPw",
Type: "mockPassword",
Name: "MockPassword",
ResourceVersion: "1",
Config: []byte(`{"username": "foo", "password": "bar"}`),
}
require.NoError(t, s.storage.CreateConnector(ctx, pwConn))
_, err := s.OpenConnector(pwConn)
require.NoError(t, err)
client := storage.Client{
ID: "test-client",
Secret: "secret",
RedirectURIs: []string{"https://example.com/callback"},
Name: "Test Client",
}
require.NoError(t, s.storage.CreateClient(ctx, client))
rr := httptest.NewRecorder()
authURL := fmt.Sprintf("/auth/mockPw?client_id=%s&redirect_uri=%s&response_type=code&scope=openid",
client.ID, url.QueryEscape("https://example.com/callback"))
req := httptest.NewRequest("GET", authURL, nil)
s.ServeHTTP(rr, req)
require.Equal(t, http.StatusFound, rr.Code)
loc, err := url.Parse(rr.Header().Get("Location"))
require.NoError(t, err)
backLink := loc.Query().Get("back")
require.NotEmpty(t, backLink, "back link should be set when multiple connectors exist")
backURL, err := url.Parse(backLink)
require.NoError(t, err)
require.Equal(t, "select_account", backURL.Query().Get("prompt"),
"back link should include prompt=select_account")
}