Merge pull request #4238 from wansir/feat-4177
Support skip information reconfirm when using external IDP
This commit is contained in:
@@ -37,7 +37,8 @@ const (
|
||||
GrantHandlerPrompt GrantHandlerType = "prompt"
|
||||
// GrantHandlerDeny auto-denies client authorization grant requests
|
||||
GrantHandlerDeny GrantHandlerType = "deny"
|
||||
// MappingMethodAuto The default value.The user will automatically create and mapping when login successful.
|
||||
// MappingMethodAuto The default value.
|
||||
// The user will automatically create and mapping when login successful.
|
||||
// Fails if a user with that username is already mapped to another identity.
|
||||
MappingMethodAuto MappingMethod = "auto"
|
||||
// MappingMethodLookup Looks up an existing identity, user identity mapping, and user, but does not automatically
|
||||
@@ -141,6 +142,11 @@ type IdentityProviderOptions struct {
|
||||
// - mixed: A user entity can be mapped with multiple identifyProvider.
|
||||
MappingMethod MappingMethod `json:"mappingMethod" yaml:"mappingMethod"`
|
||||
|
||||
// DisableLoginConfirmation means that when the user login successfully,
|
||||
// reconfirm the account information is not required.
|
||||
// Username from IDP must math [a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*
|
||||
DisableLoginConfirmation bool `json:"disableLoginConfirmation" yaml:"disableLoginConfirmation"`
|
||||
|
||||
// The type of identify provider
|
||||
// OpenIDIdentityProvider LDAPIdentityProvider GitHubIdentityProvider
|
||||
Type string `json:"type" yaml:"type"`
|
||||
|
||||
@@ -136,7 +136,7 @@ identityProviders:
|
||||
if err := yaml.Unmarshal([]byte(config), &options); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
expected := `{"identityProviders":[{"name":"ldap","mappingMethod":"auto","type":"LDAPIdentityProvider","provider":{"host":"xxxx.sn.mynetname.net:389","loginAttribute":"uid","mailAttribute":"mail","managerDN":"uid=root,cn=users,dc=xxxx,dc=sn,dc=mynetname,dc=net","userSearchBase":"dc=xxxx,dc=sn,dc=mynetname,dc=net"}},{"name":"github","mappingMethod":"mixed","type":"GitHubIdentityProvider","provider":{"clientID":"xxxxxx","endpoint":{"authURL":"https://github.com/login/oauth/authorize","tokenURL":"https://github.com/login/oauth/access_token"},"redirectURL":"https://ks-console/oauth/redirect","scopes":["user"]}}],"accessTokenMaxAge":3600000000000,"accessTokenInactivityTimeout":1800000000000}`
|
||||
expected := `{"identityProviders":[{"name":"ldap","mappingMethod":"auto","disableLoginConfirmation":false,"type":"LDAPIdentityProvider","provider":{"host":"xxxx.sn.mynetname.net:389","loginAttribute":"uid","mailAttribute":"mail","managerDN":"uid=root,cn=users,dc=xxxx,dc=sn,dc=mynetname,dc=net","userSearchBase":"dc=xxxx,dc=sn,dc=mynetname,dc=net"}},{"name":"github","mappingMethod":"mixed","disableLoginConfirmation":false,"type":"GitHubIdentityProvider","provider":{"clientID":"xxxxxx","endpoint":{"authURL":"https://github.com/login/oauth/authorize","tokenURL":"https://github.com/login/oauth/access_token"},"redirectURL":"https://ks-console/oauth/redirect","scopes":["user"]}}],"accessTokenMaxAge":3600000000000,"accessTokenInactivityTimeout":1800000000000}`
|
||||
output, _ := json.Marshal(options)
|
||||
if expected != string(output) {
|
||||
t.Errorf("expected: %s, but got: %s", expected, output)
|
||||
|
||||
@@ -58,6 +58,10 @@ func (a *EmailValidator) Handle(ctx context.Context, req admission.Request) admi
|
||||
}
|
||||
|
||||
func emailAlreadyExist(users v1alpha2.UserList, user *v1alpha2.User) bool {
|
||||
// empty email is allowed
|
||||
if user.Spec.Email == "" {
|
||||
return false
|
||||
}
|
||||
for _, exist := range users.Items {
|
||||
if exist.Spec.Email == user.Spec.Email && exist.Name != user.Name {
|
||||
return true
|
||||
|
||||
@@ -19,8 +19,12 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/mail"
|
||||
"strings"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
@@ -113,17 +117,27 @@ func (p *passwordAuthenticator) Authenticate(username, password string) (authuse
|
||||
return nil, providerOptions.Name, err
|
||||
}
|
||||
linkedAccount, err := p.userGetter.findLinkedAccount(providerOptions.Name, authenticated.GetUserID())
|
||||
if err != nil {
|
||||
return nil, providerOptions.Name, err
|
||||
}
|
||||
// using this method requires you to manually provision users.
|
||||
if providerOptions.MappingMethod == oauth.MappingMethodLookup && linkedAccount == nil {
|
||||
continue
|
||||
}
|
||||
// the user will automatically create and mapping when login successful.
|
||||
if linkedAccount == nil && providerOptions.MappingMethod == oauth.MappingMethodAuto {
|
||||
if !providerOptions.DisableLoginConfirmation {
|
||||
return preRegistrationUser(providerOptions.Name, authenticated), providerOptions.Name, nil
|
||||
}
|
||||
|
||||
linkedAccount, err = p.ksClient.IamV1alpha2().Users().Create(context.Background(), mappedUser(providerOptions.Name, authenticated), metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, providerOptions.Name, err
|
||||
}
|
||||
}
|
||||
if linkedAccount != nil {
|
||||
return &authuser.DefaultInfo{Name: linkedAccount.GetName()}, providerOptions.Name, nil
|
||||
}
|
||||
// the user will automatically create and mapping when login successful.
|
||||
if providerOptions.MappingMethod == oauth.MappingMethodAuto {
|
||||
return preRegistrationUser(providerOptions.Name, authenticated), providerOptions.Name, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +197,22 @@ func preRegistrationUser(idp string, identity identityprovider.Identity) authuse
|
||||
}
|
||||
}
|
||||
|
||||
func (o oauth2Authenticator) Authenticate(provider, code string) (authuser.Info, string, error) {
|
||||
func mappedUser(idp string, identity identityprovider.Identity) *iamv1alpha2.User {
|
||||
// username convert
|
||||
username := strings.ToLower(identity.GetUsername())
|
||||
return &iamv1alpha2.User{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: username,
|
||||
Labels: map[string]string{
|
||||
iamv1alpha2.IdentifyProviderLabel: idp,
|
||||
iamv1alpha2.OriginUIDLabel: identity.GetUserID(),
|
||||
},
|
||||
},
|
||||
Spec: iamv1alpha2.UserSpec{Email: identity.GetEmail()},
|
||||
}
|
||||
}
|
||||
|
||||
func (o *oauth2Authenticator) Authenticate(provider, code string) (authuser.Info, string, error) {
|
||||
providerOptions, err := o.authOptions.OAuthOptions.IdentityProviderOptions(provider)
|
||||
// identity provider not registered
|
||||
if err != nil {
|
||||
@@ -206,10 +235,18 @@ func (o oauth2Authenticator) Authenticate(provider, code string) (authuser.Info,
|
||||
klog.Error(err)
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
// the user will automatically create and mapping when login successful.
|
||||
if user == nil && providerOptions.MappingMethod == oauth.MappingMethodAuto {
|
||||
return preRegistrationUser(providerOptions.Name, authenticated), providerOptions.Name, nil
|
||||
if !providerOptions.DisableLoginConfirmation {
|
||||
return preRegistrationUser(providerOptions.Name, authenticated), providerOptions.Name, nil
|
||||
}
|
||||
user, err = o.ksClient.IamV1alpha2().Users().Create(context.Background(), mappedUser(providerOptions.Name, authenticated), metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, providerOptions.Name, err
|
||||
}
|
||||
}
|
||||
|
||||
if user != nil {
|
||||
return &authuser.DefaultInfo{Name: user.GetName()}, providerOptions.Name, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user