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:
Fabi
2021-09-10 09:49:49 +02:00
committed by GitHub
parent 79fb8aa37a
commit e4bdaf26b0
42 changed files with 272 additions and 111 deletions

View File

@@ -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,
}
}

View File

@@ -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,
},
},
},

View File

@@ -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
}

View File

@@ -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,
}
}

View File

@@ -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,
},
},
},

View File

@@ -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

View File

@@ -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
}