mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 01:37:31 +00:00
feat(actions): local users (#5089)
Actions are extended to to local users. It's possible to run custom code during registration and authentication of local users.
This commit is contained in:
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/dop251/goja"
|
||||
"github.com/zitadel/logging"
|
||||
"github.com/zitadel/oidc/v2/pkg/oidc"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
@@ -30,25 +29,7 @@ func (l *Login) customExternalUserMapping(ctx context.Context, user *domain.Exte
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctxFields := actions.SetContextFields(
|
||||
actions.SetFields("accessToken", tokens.AccessToken),
|
||||
actions.SetFields("idToken", tokens.IDToken),
|
||||
actions.SetFields("getClaim", func(claim string) interface{} {
|
||||
return tokens.IDTokenClaims.GetClaim(claim)
|
||||
}),
|
||||
actions.SetFields("claimsJSON", func() (string, error) {
|
||||
c, err := json.Marshal(tokens.IDTokenClaims)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(c), nil
|
||||
}),
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("externalUser", func(c *actions.FieldConfig) interface{} {
|
||||
return object.UserFromExternalUser(c, user)
|
||||
}),
|
||||
),
|
||||
)
|
||||
metadataList := object.MetadataListFromDomain(user.Metadatas)
|
||||
apiFields := actions.WithAPIFields(
|
||||
actions.SetFields("setFirstName", func(firstName string) {
|
||||
user.FirstName = firstName
|
||||
@@ -80,35 +61,28 @@ func (l *Login) customExternalUserMapping(ctx context.Context, user *domain.Exte
|
||||
actions.SetFields("setPhoneVerified", func(verified bool) {
|
||||
user.IsPhoneVerified = verified
|
||||
}),
|
||||
actions.SetFields("metadata", &user.Metadatas),
|
||||
actions.SetFields("metadata", &metadataList.Metadata),
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("user",
|
||||
actions.SetFields("appendMetadata", func(call goja.FunctionCall) goja.Value {
|
||||
if len(call.Arguments) != 2 {
|
||||
panic("exactly 2 (key, value) arguments expected")
|
||||
}
|
||||
key := call.Arguments[0].Export().(string)
|
||||
val := call.Arguments[1].Export()
|
||||
|
||||
value, err := json.Marshal(val)
|
||||
if err != nil {
|
||||
logging.WithError(err).Debug("unable to marshal")
|
||||
panic(err)
|
||||
}
|
||||
|
||||
user.Metadatas = append(user.Metadatas,
|
||||
&domain.Metadata{
|
||||
Key: key,
|
||||
Value: value,
|
||||
})
|
||||
return nil
|
||||
}),
|
||||
actions.SetFields("appendMetadata", metadataList.AppendMetadataFunc),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
for _, a := range triggerActions {
|
||||
actionCtx, cancel := context.WithTimeout(ctx, a.Timeout())
|
||||
|
||||
ctxFieldOptions := append(tokenCtxFields(tokens),
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("externalUser", func(c *actions.FieldConfig) interface{} {
|
||||
return object.UserFromExternalUser(c, user)
|
||||
}),
|
||||
actions.SetFields("authRequest", object.AuthRequestField(req)),
|
||||
),
|
||||
)
|
||||
|
||||
ctxFields := actions.SetContextFields(ctxFieldOptions...)
|
||||
|
||||
err = actions.Run(
|
||||
actionCtx,
|
||||
ctxFields,
|
||||
@@ -122,22 +96,78 @@ func (l *Login) customExternalUserMapping(ctx context.Context, user *domain.Exte
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
user.Metadatas = object.MetadataListToDomain(metadataList)
|
||||
return user, err
|
||||
}
|
||||
|
||||
func (l *Login) customExternalUserToLoginUserMapping(ctx context.Context, user *domain.Human, tokens *oidc.Tokens, req *domain.AuthRequest, config *iam_model.IDPConfigView, metadata []*domain.Metadata, resourceOwner string) (*domain.Human, []*domain.Metadata, error) {
|
||||
triggerActions, err := l.query.GetActiveActionsByFlowAndTriggerType(ctx, domain.FlowTypeExternalAuthentication, domain.TriggerTypePreCreation, resourceOwner, false)
|
||||
type authMethod string
|
||||
|
||||
const (
|
||||
authMethodPassword authMethod = "password"
|
||||
authMethodOTP authMethod = "OTP"
|
||||
authMethodU2F authMethod = "U2F"
|
||||
authMethodPasswordless authMethod = "passwordless"
|
||||
)
|
||||
|
||||
func (l *Login) triggerPostLocalAuthentication(ctx context.Context, req *domain.AuthRequest, authMethod authMethod, authenticationError error) ([]*domain.Metadata, error) {
|
||||
resourceOwner := req.RequestedOrgID
|
||||
if resourceOwner == "" {
|
||||
resourceOwner = req.UserOrgID
|
||||
}
|
||||
|
||||
triggerActions, err := l.query.GetActiveActionsByFlowAndTriggerType(ctx, domain.FlowTypeInternalAuthentication, domain.TriggerTypePostAuthentication, resourceOwner, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
metadataList := object.MetadataListFromDomain(nil)
|
||||
apiFields := actions.WithAPIFields(
|
||||
actions.SetFields("metadata", &metadataList.Metadata),
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("user",
|
||||
actions.SetFields("appendMetadata", metadataList.AppendMetadataFunc),
|
||||
),
|
||||
),
|
||||
)
|
||||
for _, a := range triggerActions {
|
||||
actionCtx, cancel := context.WithTimeout(ctx, a.Timeout())
|
||||
|
||||
authErrStr := "none"
|
||||
if authenticationError != nil {
|
||||
authErrStr = authenticationError.Error()
|
||||
}
|
||||
|
||||
ctxFields := actions.SetContextFields(
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("authMethod", authMethod),
|
||||
actions.SetFields("authError", authErrStr),
|
||||
actions.SetFields("authRequest", object.AuthRequestField(req)),
|
||||
),
|
||||
)
|
||||
|
||||
err = actions.Run(
|
||||
actionCtx,
|
||||
ctxFields,
|
||||
apiFields,
|
||||
a.Script,
|
||||
a.Name,
|
||||
append(actions.ActionToOptions(a), actions.WithHTTP(actionCtx), actions.WithLogger(actions.ServerLog))...,
|
||||
)
|
||||
cancel()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return object.MetadataListToDomain(metadataList), err
|
||||
}
|
||||
|
||||
func (l *Login) customUserToLoginUserMapping(ctx context.Context, authRequest *domain.AuthRequest, user *domain.Human, metadata []*domain.Metadata, resourceOwner string, flowType domain.FlowType) (*domain.Human, []*domain.Metadata, error) {
|
||||
triggerActions, err := l.query.GetActiveActionsByFlowAndTriggerType(ctx, flowType, domain.TriggerTypePreCreation, resourceOwner, false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
ctxOpts := actions.SetContextFields(
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("user", func(c *actions.FieldConfig) interface{} {
|
||||
return object.UserFromHuman(c, user)
|
||||
}),
|
||||
),
|
||||
)
|
||||
metadataList := object.MetadataListFromDomain(metadata)
|
||||
apiFields := actions.WithAPIFields(
|
||||
actions.SetFields("setFirstName", func(firstName string) {
|
||||
user.FirstName = firstName
|
||||
@@ -184,35 +214,26 @@ func (l *Login) customExternalUserToLoginUserMapping(ctx context.Context, user *
|
||||
}
|
||||
user.Phone.IsPhoneVerified = verified
|
||||
}),
|
||||
actions.SetFields("metadata", metadata),
|
||||
actions.SetFields("metadata", &metadataList.Metadata),
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("user",
|
||||
actions.SetFields("appendMetadata", func(call goja.FunctionCall) goja.Value {
|
||||
if len(call.Arguments) != 2 {
|
||||
panic("exactly 2 (key, value) arguments expected")
|
||||
}
|
||||
key := call.Arguments[0].Export().(string)
|
||||
val := call.Arguments[1].Export()
|
||||
|
||||
value, err := json.Marshal(val)
|
||||
if err != nil {
|
||||
logging.WithError(err).Debug("unable to marshal")
|
||||
panic(err)
|
||||
}
|
||||
|
||||
metadata = append(metadata,
|
||||
&domain.Metadata{
|
||||
Key: key,
|
||||
Value: value,
|
||||
})
|
||||
return nil
|
||||
}),
|
||||
actions.SetFields("appendMetadata", metadataList.AppendMetadataFunc),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
for _, a := range triggerActions {
|
||||
actionCtx, cancel := context.WithTimeout(ctx, a.Timeout())
|
||||
|
||||
ctxOpts := actions.SetContextFields(
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("user", func(c *actions.FieldConfig) interface{} {
|
||||
return object.UserFromHuman(c, user)
|
||||
}),
|
||||
actions.SetFields("authRequest", object.AuthRequestField(authRequest)),
|
||||
),
|
||||
)
|
||||
|
||||
err = actions.Run(
|
||||
actionCtx,
|
||||
ctxOpts,
|
||||
@@ -226,57 +247,21 @@ func (l *Login) customExternalUserToLoginUserMapping(ctx context.Context, user *
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
return user, metadata, err
|
||||
return user, object.MetadataListToDomain(metadataList), err
|
||||
}
|
||||
|
||||
func (l *Login) customGrants(ctx context.Context, userID string, tokens *oidc.Tokens, req *domain.AuthRequest, config *iam_model.IDPConfigView, resourceOwner string) ([]*domain.UserGrant, error) {
|
||||
triggerActions, err := l.query.GetActiveActionsByFlowAndTriggerType(ctx, domain.FlowTypeExternalAuthentication, domain.TriggerTypePostCreation, resourceOwner, false)
|
||||
func (l *Login) customGrants(ctx context.Context, userID string, authRequest *domain.AuthRequest, resourceOwner string, flowType domain.FlowType) ([]*domain.UserGrant, error) {
|
||||
triggerActions, err := l.query.GetActiveActionsByFlowAndTriggerType(ctx, flowType, domain.TriggerTypePostCreation, resourceOwner, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
actionUserGrants := make([]actions.UserGrant, 0)
|
||||
mutableUserGrants := &object.UserGrants{UserGrants: make([]object.UserGrant, 0)}
|
||||
|
||||
apiFields := actions.WithAPIFields(
|
||||
actions.SetFields("userGrants", &actionUserGrants),
|
||||
actions.SetFields("userGrants", &mutableUserGrants.UserGrants),
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("appendUserGrant", func(c *actions.FieldConfig) interface{} {
|
||||
return func(call goja.FunctionCall) goja.Value {
|
||||
if len(call.Arguments) != 1 {
|
||||
panic("exactly one argument expected")
|
||||
}
|
||||
object := call.Arguments[0].ToObject(c.Runtime)
|
||||
if object == nil {
|
||||
panic("unable to unmarshal arg")
|
||||
}
|
||||
grant := actions.UserGrant{}
|
||||
|
||||
for _, key := range object.Keys() {
|
||||
switch key {
|
||||
case "projectId":
|
||||
grant.ProjectID = object.Get(key).String()
|
||||
case "projectGrantId":
|
||||
grant.ProjectGrantID = object.Get(key).String()
|
||||
case "roles":
|
||||
if roles, ok := object.Get(key).Export().([]interface{}); ok {
|
||||
for _, role := range roles {
|
||||
if r, ok := role.(string); ok {
|
||||
grant.Roles = append(grant.Roles, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if grant.ProjectID == "" {
|
||||
panic("projectId not set")
|
||||
}
|
||||
|
||||
actionUserGrants = append(actionUserGrants, grant)
|
||||
|
||||
return nil
|
||||
}
|
||||
}),
|
||||
actions.SetFields("appendUserGrant", object.AppendGrantFunc(mutableUserGrants)),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -287,13 +272,14 @@ func (l *Login) customGrants(ctx context.Context, userID string, tokens *oidc.To
|
||||
actions.SetFields("v1",
|
||||
actions.SetFields("getUser", func(c *actions.FieldConfig) interface{} {
|
||||
return func(call goja.FunctionCall) goja.Value {
|
||||
user, err := l.query.GetUserByID(actionCtx, true, userID, false)
|
||||
user, err := l.query.GetUserByID(actionCtx, true, authRequest.UserID, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return object.UserFromQuery(c, user)
|
||||
}
|
||||
}),
|
||||
actions.SetFields("authRequest", object.AuthRequestField(authRequest)),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -310,21 +296,22 @@ func (l *Login) customGrants(ctx context.Context, userID string, tokens *oidc.To
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return actionUserGrantsToDomain(userID, actionUserGrants), err
|
||||
return object.UserGrantsToDomain(userID, mutableUserGrants.UserGrants), err
|
||||
}
|
||||
|
||||
func actionUserGrantsToDomain(userID string, actionUserGrants []actions.UserGrant) []*domain.UserGrant {
|
||||
if actionUserGrants == nil {
|
||||
return nil
|
||||
func tokenCtxFields(tokens *oidc.Tokens) []actions.FieldOption {
|
||||
return []actions.FieldOption{
|
||||
actions.SetFields("accessToken", tokens.AccessToken),
|
||||
actions.SetFields("idToken", tokens.IDToken),
|
||||
actions.SetFields("getClaim", func(claim string) interface{} {
|
||||
return tokens.IDTokenClaims.GetClaim(claim)
|
||||
}),
|
||||
actions.SetFields("claimsJSON", func() (string, error) {
|
||||
c, err := json.Marshal(tokens.IDTokenClaims)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(c), nil
|
||||
}),
|
||||
}
|
||||
userGrants := make([]*domain.UserGrant, len(actionUserGrants))
|
||||
for i, grant := range actionUserGrants {
|
||||
userGrants[i] = &domain.UserGrant{
|
||||
UserID: userID,
|
||||
ProjectID: grant.ProjectID,
|
||||
ProjectGrantID: grant.ProjectGrantID,
|
||||
RoleKeys: grant.Roles,
|
||||
}
|
||||
}
|
||||
return userGrants
|
||||
}
|
||||
|
@@ -383,7 +383,7 @@ func (l *Login) handleAutoRegister(w http.ResponseWriter, r *http.Request, authR
|
||||
|
||||
user, externalIDP, metadata := l.mapExternalUserToLoginUser(orgIamPolicy, linkingUser, idpConfig)
|
||||
|
||||
user, metadata, err = l.customExternalUserToLoginUserMapping(r.Context(), user, nil, authReq, idpConfig, metadata, resourceOwner)
|
||||
user, metadata, err = l.customUserToLoginUserMapping(r.Context(), authReq, user, metadata, resourceOwner, domain.FlowTypeExternalAuthentication)
|
||||
if err != nil {
|
||||
l.renderExternalNotFoundOption(w, r, authReq, orgIamPolicy, nil, nil, err)
|
||||
return
|
||||
@@ -398,7 +398,7 @@ func (l *Login) handleAutoRegister(w http.ResponseWriter, r *http.Request, authR
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
userGrants, err := l.customGrants(r.Context(), authReq.UserID, nil, authReq, idpConfig, resourceOwner)
|
||||
userGrants, err := l.customGrants(r.Context(), authReq.UserID, authReq, resourceOwner, domain.FlowTypeExternalAuthentication)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
|
@@ -161,7 +161,7 @@ func (l *Login) registerExternalUser(w http.ResponseWriter, r *http.Request, aut
|
||||
return
|
||||
}
|
||||
user, externalIDP, metadata := l.mapExternalUserToLoginUser(orgIamPolicy, externalUser, idpConfig)
|
||||
user, metadata, err = l.customExternalUserToLoginUserMapping(r.Context(), user, nil, authReq, idpConfig, metadata, resourceOwner)
|
||||
user, metadata, err = l.customUserToLoginUserMapping(r.Context(), authReq, user, metadata, resourceOwner, domain.FlowTypeExternalAuthentication)
|
||||
if err != nil {
|
||||
l.renderRegisterOption(w, r, authReq, err)
|
||||
return
|
||||
@@ -177,7 +177,7 @@ func (l *Login) registerExternalUser(w http.ResponseWriter, r *http.Request, aut
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
userGrants, err := l.customGrants(r.Context(), authReq.UserID, nil, authReq, idpConfig, resourceOwner)
|
||||
userGrants, err := l.customGrants(r.Context(), authReq.UserID, authReq, resourceOwner, domain.FlowTypeExternalAuthentication)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
|
@@ -129,7 +129,7 @@ func (l *Login) jwtExtractionUserNotFound(w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
|
||||
user, externalIDP, metadata := l.mapExternalUserToLoginUser(orgIamPolicy, authReq.LinkingUsers[len(authReq.LinkingUsers)-1], idpConfig)
|
||||
user, metadata, err = l.customExternalUserToLoginUserMapping(r.Context(), user, tokens, authReq, idpConfig, metadata, resourceOwner)
|
||||
user, metadata, err = l.customUserToLoginUserMapping(r.Context(), authReq, user, metadata, resourceOwner, domain.FlowTypeExternalAuthentication)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
@@ -144,7 +144,7 @@ func (l *Login) jwtExtractionUserNotFound(w http.ResponseWriter, r *http.Request
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
userGrants, err := l.customGrants(r.Context(), authReq.UserID, tokens, authReq, idpConfig, resourceOwner)
|
||||
userGrants, err := l.customGrants(r.Context(), authReq.UserID, authReq, resourceOwner, domain.FlowTypeExternalAuthentication)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
|
@@ -73,7 +73,6 @@ func CreateLogin(config Config,
|
||||
idpConfigAlg crypto.EncryptionAlgorithm,
|
||||
csrfCookieKey []byte,
|
||||
) (*Login, error) {
|
||||
|
||||
login := &Login{
|
||||
oidcAuthCallbackURL: oidcAuthCallbackURL,
|
||||
samlAuthCallbackURL: samlAuthCallbackURL,
|
||||
|
@@ -36,6 +36,14 @@ func (l *Login) handleMFAVerify(w http.ResponseWriter, r *http.Request) {
|
||||
if data.MFAType == domain.MFATypeOTP {
|
||||
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
|
||||
err = l.authRepo.VerifyMFAOTP(setContext(r.Context(), authReq.UserOrgID), authReq.ID, authReq.UserID, authReq.UserOrgID, data.Code, userAgentID, domain.BrowserInfoFromRequest(r))
|
||||
|
||||
metadata, actionErr := l.triggerPostLocalAuthentication(r.Context(), authReq, authMethodOTP, err)
|
||||
if err == nil && actionErr == nil && len(metadata) > 0 {
|
||||
_, err = l.command.BulkSetUserMetadata(r.Context(), authReq.UserID, authReq.UserOrgID, metadata...)
|
||||
} else if actionErr != nil && err == nil {
|
||||
err = actionErr
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
l.renderMFAVerifySelected(w, r, authReq, step, domain.MFATypeOTP, err)
|
||||
return
|
||||
|
@@ -71,6 +71,14 @@ func (l *Login) handleU2FVerification(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
|
||||
err = l.authRepo.VerifyMFAU2F(setContext(r.Context(), authReq.UserOrgID), authReq.UserID, authReq.UserOrgID, authReq.ID, userAgentID, credData, domain.BrowserInfoFromRequest(r))
|
||||
|
||||
metadata, actionErr := l.triggerPostLocalAuthentication(r.Context(), authReq, authMethodU2F, err)
|
||||
if err == nil && actionErr == nil && len(metadata) > 0 {
|
||||
_, err = l.command.BulkSetUserMetadata(r.Context(), authReq.UserID, authReq.UserOrgID, metadata...)
|
||||
} else if actionErr != nil && err == nil {
|
||||
err = actionErr
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
l.renderU2FVerification(w, r, authReq, step.MFAProviders, err)
|
||||
return
|
||||
|
@@ -39,6 +39,14 @@ func (l *Login) handlePasswordCheck(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
err = l.authRepo.VerifyPassword(setContext(r.Context(), authReq.UserOrgID), authReq.ID, authReq.UserID, authReq.UserOrgID, data.Password, authReq.AgentID, domain.BrowserInfoFromRequest(r))
|
||||
|
||||
metadata, actionErr := l.triggerPostLocalAuthentication(r.Context(), authReq, authMethodPassword, err)
|
||||
if err == nil && actionErr == nil && len(metadata) > 0 {
|
||||
_, err = l.command.BulkSetUserMetadata(r.Context(), authReq.UserID, authReq.UserOrgID, metadata...)
|
||||
} else if actionErr != nil && err == nil {
|
||||
err = actionErr
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if authReq.LoginPolicy.IgnoreUnknownUsernames {
|
||||
l.renderLogin(w, r, authReq, err)
|
||||
|
@@ -63,6 +63,14 @@ func (l *Login) handlePasswordlessVerification(w http.ResponseWriter, r *http.Re
|
||||
return
|
||||
}
|
||||
err = l.authRepo.VerifyPasswordless(setContext(r.Context(), authReq.UserOrgID), authReq.UserID, authReq.UserOrgID, authReq.ID, authReq.AgentID, credData, domain.BrowserInfoFromRequest(r))
|
||||
|
||||
metadata, actionErr := l.triggerPostLocalAuthentication(r.Context(), authReq, authMethodPasswordless, err)
|
||||
if err == nil && actionErr == nil && len(metadata) > 0 {
|
||||
_, err = l.command.BulkSetUserMetadata(r.Context(), authReq.UserID, authReq.UserOrgID, metadata...)
|
||||
} else if actionErr != nil && err == nil {
|
||||
err = actionErr
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
l.renderPasswordlessVerification(w, r, authReq, formData.PasswordLogin, err)
|
||||
return
|
||||
|
@@ -82,11 +82,48 @@ func (l *Login) handleRegisterCheck(w http.ResponseWriter, r *http.Request) {
|
||||
l.renderRegister(w, r, authRequest, data, err)
|
||||
return
|
||||
}
|
||||
user, err := l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, data.toHumanDomain(), nil, nil, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator)
|
||||
|
||||
// For consistency with the external authentication flow,
|
||||
// the setMetadata() function is provided on the pre creation hook, for now,
|
||||
// like for the ExternalAuthentication flow.
|
||||
// If there is a need for additional context after registration,
|
||||
// we could provide that method in the PostCreation trigger too,
|
||||
// without breaking existing actions.
|
||||
// Also, if that field is needed, we probably also should provide it
|
||||
// for ExternalAuthentication.
|
||||
user, metadatas, err := l.customUserToLoginUserMapping(r.Context(), authRequest, data.toHumanDomain(), make([]*domain.Metadata, 0), resourceOwner, domain.FlowTypeInternalAuthentication)
|
||||
if err != nil {
|
||||
l.renderRegister(w, r, authRequest, data, err)
|
||||
return
|
||||
}
|
||||
|
||||
user, err = l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, user, nil, nil, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
l.renderRegister(w, r, authRequest, data, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(metadatas) > 0 {
|
||||
_, err = l.command.BulkSetUserMetadata(r.Context(), user.AggregateID, resourceOwner, metadatas...)
|
||||
if err != nil {
|
||||
// TODO: What if action is configured to be allowed to fail? Same question for external registration.
|
||||
l.renderRegister(w, r, authRequest, data, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
userGrants, err := l.customGrants(r.Context(), user.AggregateID, authRequest, resourceOwner, domain.FlowTypeInternalAuthentication)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = l.appendUserGrants(r.Context(), userGrants, resourceOwner)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
if authRequest == nil {
|
||||
l.defaultRedirect(w, r)
|
||||
return
|
||||
|
Reference in New Issue
Block a user