mirror of
https://github.com/netbirdio/netbird.git
synced 2026-03-31 06:24:18 -04:00
[client, management] Add OAuth select_account prompt support to PKCE flow (#4880)
* Add OAuth select_account prompt support to PKCE flow Extends LoginFlag enum with select_account options to enable multi-account selection during authentication. This allows users to choose which account to use when multiple accounts have active sessions with the identity provider. The new flags are backward compatible - existing LoginFlag values (0=prompt login, 1=max_age=0) retain their original behavior.
This commit is contained in:
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/netbirdio/netbird/client/internal"
|
||||
"github.com/netbirdio/netbird/client/internal/templates"
|
||||
"github.com/netbirdio/netbird/shared/management/client/common"
|
||||
)
|
||||
|
||||
var _ OAuthFlow = &PKCEAuthorizationFlow{}
|
||||
@@ -104,11 +105,12 @@ func (p *PKCEAuthorizationFlow) RequestAuthInfo(ctx context.Context) (AuthFlowIn
|
||||
oauth2.SetAuthURLParam("audience", p.providerConfig.Audience),
|
||||
}
|
||||
if !p.providerConfig.DisablePromptLogin {
|
||||
if p.providerConfig.LoginFlag.IsPromptLogin() {
|
||||
params = append(params, oauth2.SetAuthURLParam("prompt", "login"))
|
||||
}
|
||||
if p.providerConfig.LoginFlag.IsMaxAge0Login() {
|
||||
switch p.providerConfig.LoginFlag {
|
||||
case common.LoginFlagPromptLogin:
|
||||
params = append(params, oauth2.SetAuthURLParam("prompt", "login select_account"))
|
||||
case common.LoginFlagMaxAge0:
|
||||
params = append(params, oauth2.SetAuthURLParam("max_age", "0"))
|
||||
params = append(params, oauth2.SetAuthURLParam("prompt", "select_account"))
|
||||
}
|
||||
}
|
||||
if p.providerConfig.LoginHint != "" {
|
||||
|
||||
@@ -15,30 +15,37 @@ import (
|
||||
|
||||
func TestPromptLogin(t *testing.T) {
|
||||
const (
|
||||
promptLogin = "prompt=login"
|
||||
maxAge0 = "max_age=0"
|
||||
promptSelectAccountLogin = "prompt=login+select_account"
|
||||
promptSelectAccount = "prompt=select_account"
|
||||
maxAge0 = "max_age=0"
|
||||
)
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
loginFlag mgm.LoginFlag
|
||||
disablePromptLogin bool
|
||||
expect string
|
||||
expectContains []string
|
||||
}{
|
||||
{
|
||||
name: "Prompt login",
|
||||
loginFlag: mgm.LoginFlagPrompt,
|
||||
expect: promptLogin,
|
||||
name: "Prompt login with select account",
|
||||
loginFlag: mgm.LoginFlagPromptLogin,
|
||||
expectContains: []string{promptSelectAccountLogin},
|
||||
},
|
||||
{
|
||||
name: "Max age 0 login",
|
||||
loginFlag: mgm.LoginFlagMaxAge0,
|
||||
expect: maxAge0,
|
||||
name: "Max age 0 with select account",
|
||||
loginFlag: mgm.LoginFlagMaxAge0,
|
||||
expectContains: []string{maxAge0, promptSelectAccount},
|
||||
},
|
||||
{
|
||||
name: "Disable prompt login",
|
||||
loginFlag: mgm.LoginFlagPrompt,
|
||||
loginFlag: mgm.LoginFlagPromptLogin,
|
||||
disablePromptLogin: true,
|
||||
expectContains: []string{},
|
||||
},
|
||||
{
|
||||
name: "None flag should not add parameters",
|
||||
loginFlag: mgm.LoginFlagNone,
|
||||
expectContains: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -53,6 +60,7 @@ func TestPromptLogin(t *testing.T) {
|
||||
RedirectURLs: []string{"http://127.0.0.1:33992/"},
|
||||
UseIDToken: true,
|
||||
LoginFlag: tc.loginFlag,
|
||||
DisablePromptLogin: tc.disablePromptLogin,
|
||||
}
|
||||
pkce, err := NewPKCEAuthorizationFlow(config)
|
||||
if err != nil {
|
||||
@@ -63,11 +71,8 @@ func TestPromptLogin(t *testing.T) {
|
||||
t.Fatalf("Failed to request auth info: %v", err)
|
||||
}
|
||||
|
||||
if !tc.disablePromptLogin {
|
||||
require.Contains(t, authInfo.VerificationURIComplete, tc.expect)
|
||||
} else {
|
||||
require.Contains(t, authInfo.VerificationURIComplete, promptLogin)
|
||||
require.NotContains(t, authInfo.VerificationURIComplete, maxAge0)
|
||||
for _, expected := range tc.expectContains {
|
||||
require.Contains(t, authInfo.VerificationURIComplete, expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
package common
|
||||
|
||||
// LoginFlag introduces additional login flags to the PKCE authorization request
|
||||
// LoginFlag introduces additional login flags to the PKCE authorization request.
|
||||
//
|
||||
// # Config Values
|
||||
//
|
||||
// | Value | Flag | OAuth Parameters |
|
||||
// |-------|----------------------|-----------------------------------------|
|
||||
// | 0 | LoginFlagPromptLogin | prompt=select_account login |
|
||||
// | 1 | LoginFlagMaxAge0 | max_age=0 & prompt=select_account |
|
||||
type LoginFlag uint8
|
||||
|
||||
const (
|
||||
// LoginFlagPrompt adds prompt=login to the authorization request
|
||||
LoginFlagPrompt LoginFlag = iota
|
||||
// LoginFlagMaxAge0 adds max_age=0 to the authorization request
|
||||
// LoginFlagPromptLogin adds prompt=select_account login to the authorization request
|
||||
LoginFlagPromptLogin LoginFlag = iota
|
||||
// LoginFlagMaxAge0 adds max_age=0 and prompt=select_account to the authorization request
|
||||
LoginFlagMaxAge0
|
||||
// LoginFlagNone disables all login flags
|
||||
LoginFlagNone
|
||||
)
|
||||
|
||||
func (l LoginFlag) IsPromptLogin() bool {
|
||||
return l == LoginFlagPrompt
|
||||
}
|
||||
|
||||
func (l LoginFlag) IsMaxAge0Login() bool {
|
||||
return l == LoginFlagMaxAge0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user