mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 03:57:32 +00:00
feat: select idp and auto register (#2336)
* faet: auto regsiter config on idp * feat: auto register on login * feat: auto register on register * feat: redirect to selected identity provider * fix: test * fix: test * fix: user by id request org id * fix: migration version and test Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
@@ -12,10 +12,11 @@ import (
|
||||
|
||||
func addOIDCIDPRequestToDomain(req *admin_pb.AddOIDCIDPRequest) *domain.IDPConfig {
|
||||
return &domain.IDPConfig{
|
||||
Name: req.Name,
|
||||
OIDCConfig: addOIDCIDPRequestToDomainOIDCIDPConfig(req),
|
||||
StylingType: idp_grpc.IDPStylingTypeToDomain(req.StylingType),
|
||||
Type: domain.IDPConfigTypeOIDC,
|
||||
Name: req.Name,
|
||||
OIDCConfig: addOIDCIDPRequestToDomainOIDCIDPConfig(req),
|
||||
StylingType: idp_grpc.IDPStylingTypeToDomain(req.StylingType),
|
||||
Type: domain.IDPConfigTypeOIDC,
|
||||
AutoRegister: req.AutoRegister,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +33,10 @@ func addOIDCIDPRequestToDomainOIDCIDPConfig(req *admin_pb.AddOIDCIDPRequest) *do
|
||||
|
||||
func updateIDPToDomain(req *admin_pb.UpdateIDPRequest) *domain.IDPConfig {
|
||||
return &domain.IDPConfig{
|
||||
IDPConfigID: req.IdpId,
|
||||
Name: req.Name,
|
||||
StylingType: idp_grpc.IDPStylingTypeToDomain(req.StylingType),
|
||||
IDPConfigID: req.IdpId,
|
||||
Name: req.Name,
|
||||
StylingType: idp_grpc.IDPStylingTypeToDomain(req.StylingType),
|
||||
AutoRegister: req.AutoRegister,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -28,6 +28,7 @@ func Test_addOIDCIDPRequestToDomain(t *testing.T) {
|
||||
Scopes: []string{"email", "profile"},
|
||||
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
|
||||
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
|
||||
AutoRegister: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -98,9 +99,10 @@ func Test_updateIDPToDomain(t *testing.T) {
|
||||
name: "all fields filled",
|
||||
args: args{
|
||||
req: &admin_pb.UpdateIDPRequest{
|
||||
IdpId: "13523",
|
||||
Name: "new name",
|
||||
StylingType: idp.IDPStylingType_STYLING_TYPE_GOOGLE,
|
||||
IdpId: "13523",
|
||||
Name: "new name",
|
||||
StylingType: idp.IDPStylingType_STYLING_TYPE_GOOGLE,
|
||||
AutoRegister: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@@ -18,29 +18,31 @@ func IDPViewsToPb(idps []*iam_model.IDPConfigView) []*idp_pb.IDP {
|
||||
|
||||
func ModelIDPViewToPb(idp *iam_model.IDPConfigView) *idp_pb.IDP {
|
||||
return &idp_pb.IDP{
|
||||
Id: idp.IDPConfigID,
|
||||
State: ModelIDPStateToPb(idp.State),
|
||||
Name: idp.Name,
|
||||
StylingType: ModelIDPStylingTypeToPb(idp.StylingType),
|
||||
Owner: ModelIDPProviderTypeToPb(idp.IDPProviderType),
|
||||
Config: ModelIDPViewToConfigPb(idp),
|
||||
Id: idp.IDPConfigID,
|
||||
State: ModelIDPStateToPb(idp.State),
|
||||
Name: idp.Name,
|
||||
StylingType: ModelIDPStylingTypeToPb(idp.StylingType),
|
||||
AutoRegister: idp.AutoRegister,
|
||||
Owner: ModelIDPProviderTypeToPb(idp.IDPProviderType),
|
||||
Config: ModelIDPViewToConfigPb(idp),
|
||||
Details: obj_grpc.ToViewDetailsPb(
|
||||
idp.Sequence,
|
||||
idp.CreationDate,
|
||||
idp.ChangeDate,
|
||||
"", //TODO: backend
|
||||
idp.AggregateID,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func IDPViewToPb(idp *domain.IDPConfigView) *idp_pb.IDP {
|
||||
mapped := &idp_pb.IDP{
|
||||
Id: idp.AggregateID,
|
||||
State: IDPStateToPb(idp.State),
|
||||
Name: idp.Name,
|
||||
StylingType: IDPStylingTypeToPb(idp.StylingType),
|
||||
Config: IDPViewToConfigPb(idp),
|
||||
Details: obj_grpc.ToViewDetailsPb(idp.Sequence, idp.CreationDate, idp.ChangeDate, ""), //TODO: resource owner in view
|
||||
Id: idp.AggregateID,
|
||||
State: IDPStateToPb(idp.State),
|
||||
Name: idp.Name,
|
||||
StylingType: IDPStylingTypeToPb(idp.StylingType),
|
||||
AutoRegister: idp.AutoRegister,
|
||||
Config: IDPViewToConfigPb(idp),
|
||||
Details: obj_grpc.ToViewDetailsPb(idp.Sequence, idp.CreationDate, idp.ChangeDate, idp.AggregateID),
|
||||
}
|
||||
return mapped
|
||||
}
|
||||
|
@@ -32,9 +32,10 @@ func addOIDCIDPRequestToDomainOIDCIDPConfig(req *mgmt_pb.AddOrgOIDCIDPRequest) *
|
||||
|
||||
func updateIDPToDomain(req *mgmt_pb.UpdateOrgIDPRequest) *domain.IDPConfig {
|
||||
return &domain.IDPConfig{
|
||||
IDPConfigID: req.IdpId,
|
||||
Name: req.Name,
|
||||
StylingType: idp_grpc.IDPStylingTypeToDomain(req.StylingType),
|
||||
IDPConfigID: req.IdpId,
|
||||
Name: req.Name,
|
||||
StylingType: idp_grpc.IDPStylingTypeToDomain(req.StylingType),
|
||||
AutoRegister: req.AutoRegister,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -28,6 +28,7 @@ func Test_addOIDCIDPRequestToDomain(t *testing.T) {
|
||||
Scopes: []string{"email", "profile"},
|
||||
DisplayNameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_EMAIL,
|
||||
UsernameMapping: idp.OIDCMappingField_OIDC_MAPPING_FIELD_PREFERRED_USERNAME,
|
||||
AutoRegister: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -45,6 +46,7 @@ func Test_addOIDCIDPRequestToDomain(t *testing.T) {
|
||||
"OIDCConfig.AuthorizationEndpoint",
|
||||
"OIDCConfig.TokenEndpoint",
|
||||
"Type", //TODO: default (0) is oidc
|
||||
"AutoRegister",
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -98,9 +100,10 @@ func Test_updateIDPToDomain(t *testing.T) {
|
||||
name: "all fields filled",
|
||||
args: args{
|
||||
req: &mgmt_pb.UpdateOrgIDPRequest{
|
||||
IdpId: "13523",
|
||||
Name: "new name",
|
||||
StylingType: idp.IDPStylingType_STYLING_TYPE_GOOGLE,
|
||||
IdpId: "13523",
|
||||
Name: "new name",
|
||||
StylingType: idp.IDPStylingType_STYLING_TYPE_GOOGLE,
|
||||
AutoRegister: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@@ -3,6 +3,7 @@ package oidc
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
"golang.org/x/text/language"
|
||||
|
||||
http_utils "github.com/caos/zitadel/internal/api/http"
|
||||
model2 "github.com/caos/zitadel/internal/auth_request/model"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/user/model"
|
||||
@@ -113,18 +115,19 @@ func AuthRequestFromBusiness(authReq *domain.AuthRequest) (_ op.AuthRequest, err
|
||||
|
||||
func CreateAuthRequestToBusiness(ctx context.Context, authReq *oidc.AuthRequest, userAgentID, userID string) *domain.AuthRequest {
|
||||
return &domain.AuthRequest{
|
||||
CreationDate: time.Now(),
|
||||
AgentID: userAgentID,
|
||||
BrowserInfo: ParseBrowserInfoFromContext(ctx),
|
||||
ApplicationID: authReq.ClientID,
|
||||
CallbackURI: authReq.RedirectURI,
|
||||
TransferState: authReq.State,
|
||||
Prompt: PromptToBusiness(authReq.Prompt),
|
||||
PossibleLOAs: ACRValuesToBusiness(authReq.ACRValues),
|
||||
UiLocales: UILocalesToBusiness(authReq.UILocales),
|
||||
LoginHint: authReq.LoginHint,
|
||||
MaxAuthAge: MaxAgeToBusiness(authReq.MaxAge),
|
||||
UserID: userID,
|
||||
CreationDate: time.Now(),
|
||||
AgentID: userAgentID,
|
||||
BrowserInfo: ParseBrowserInfoFromContext(ctx),
|
||||
ApplicationID: authReq.ClientID,
|
||||
CallbackURI: authReq.RedirectURI,
|
||||
TransferState: authReq.State,
|
||||
Prompt: PromptToBusiness(authReq.Prompt),
|
||||
PossibleLOAs: ACRValuesToBusiness(authReq.ACRValues),
|
||||
UiLocales: UILocalesToBusiness(authReq.UILocales),
|
||||
LoginHint: authReq.LoginHint,
|
||||
SelectedIDPConfigID: GetSelectedIDPIDFromScopes(authReq.Scopes),
|
||||
MaxAuthAge: MaxAgeToBusiness(authReq.MaxAge),
|
||||
UserID: userID,
|
||||
Request: &domain.AuthRequestOIDC{
|
||||
Scopes: authReq.Scopes,
|
||||
ResponseType: ResponseTypeToBusiness(authReq.ResponseType),
|
||||
@@ -196,6 +199,15 @@ func UILocalesToBusiness(tags []language.Tag) []string {
|
||||
return locales
|
||||
}
|
||||
|
||||
func GetSelectedIDPIDFromScopes(scopes oidc.SpaceDelimitedArray) string {
|
||||
for _, scope := range scopes {
|
||||
if strings.HasPrefix(scope, model2.SelectIDPScope) {
|
||||
return strings.TrimPrefix(scope, model2.SelectIDPScope)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func MaxAgeToBusiness(maxAge *uint) *time.Duration {
|
||||
if maxAge == nil {
|
||||
return nil
|
||||
|
@@ -106,6 +106,9 @@ func (c *Client) IsScopeAllowed(scope string) bool {
|
||||
if strings.HasPrefix(scope, authreq_model.ProjectIDScope) {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(scope, authreq_model.SelectIDPScope) {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(scope, ScopeUserMetaData) {
|
||||
return true
|
||||
}
|
||||
|
Reference in New Issue
Block a user