mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 14:47:33 +00:00
feat: add http request to interal and external authentication actions (#5103)
Add functionality to provide http.Request and authError to actions for logging or other logic.
This commit is contained in:
@@ -22,7 +22,10 @@ The first parameter contains the following fields
|
|||||||
The id token which will be returned to the user
|
The id token which will be returned to the user
|
||||||
- `v1`
|
- `v1`
|
||||||
- `externalUser()` [*externalUser*](./objects#external-user)
|
- `externalUser()` [*externalUser*](./objects#external-user)
|
||||||
|
- `authError` *string*
|
||||||
|
This is a verification errors string representation. If the verification succeeds, this is "none"
|
||||||
- `authRequest` [*auth request*](/docs/apis/actions/objects#auth-request)
|
- `authRequest` [*auth request*](/docs/apis/actions/objects#auth-request)
|
||||||
|
- `httpRequest` [*http request*](/docs/apis/actions/objects#http-request)
|
||||||
- `api`
|
- `api`
|
||||||
The second parameter contains the following fields
|
The second parameter contains the following fields
|
||||||
- `v1`
|
- `v1`
|
||||||
@@ -63,6 +66,7 @@ A user selected **Register** on the overview page after external authentication.
|
|||||||
- `v1`
|
- `v1`
|
||||||
- `user` [*human*](./objects#human-user)
|
- `user` [*human*](./objects#human-user)
|
||||||
- `authRequest` [*auth request*](/docs/apis/actions/objects#auth-request)
|
- `authRequest` [*auth request*](/docs/apis/actions/objects#auth-request)
|
||||||
|
- `httpRequest` [*http request*](/docs/apis/actions/objects#http-request)
|
||||||
- `api`
|
- `api`
|
||||||
The second parameter contains the following fields
|
The second parameter contains the following fields
|
||||||
- `metadata`
|
- `metadata`
|
||||||
@@ -106,6 +110,7 @@ A user selected **Register** on the overview page after external authentication
|
|||||||
- `v1`
|
- `v1`
|
||||||
- `getUser()` [*user*](./objects#user)
|
- `getUser()` [*user*](./objects#user)
|
||||||
- `authRequest` [*auth request*](/docs/apis/actions/objects#auth-request)
|
- `authRequest` [*auth request*](/docs/apis/actions/objects#auth-request)
|
||||||
|
- `httpRequest` [*http request*](/docs/apis/actions/objects#http-request)
|
||||||
- `api`
|
- `api`
|
||||||
The second parameter contains the following fields
|
The second parameter contains the following fields
|
||||||
- `userGrants` Array of [*userGrant*](./objects#user-grant)'s
|
- `userGrants` Array of [*userGrant*](./objects#user-grant)'s
|
||||||
|
@@ -18,6 +18,7 @@ Each validation step triggers the action.
|
|||||||
- `authError` *string*
|
- `authError` *string*
|
||||||
This is a verification errors string representation. If the verification succeeds, this is "none"
|
This is a verification errors string representation. If the verification succeeds, this is "none"
|
||||||
- `authRequest` [*auth request*](/docs/apis/actions/objects#auth-request)
|
- `authRequest` [*auth request*](/docs/apis/actions/objects#auth-request)
|
||||||
|
- `httpRequest` [*http request*](/docs/apis/actions/objects#http-request)
|
||||||
- `api`
|
- `api`
|
||||||
The second parameter contains the following fields
|
The second parameter contains the following fields
|
||||||
- `metadata`
|
- `metadata`
|
||||||
@@ -39,6 +40,7 @@ ZITADEL did not create the user yet.
|
|||||||
- `v1`
|
- `v1`
|
||||||
- `user` [*human*](./objects#human-user)
|
- `user` [*human*](./objects#human-user)
|
||||||
- `authRequest` [*auth request*](/docs/apis/actions/objects#auth-request)
|
- `authRequest` [*auth request*](/docs/apis/actions/objects#auth-request)
|
||||||
|
- `httpRequest` [*http request*](/docs/apis/actions/objects#http-request)
|
||||||
- `api`
|
- `api`
|
||||||
The second parameter contains the following fields
|
The second parameter contains the following fields
|
||||||
- `metadata`
|
- `metadata`
|
||||||
@@ -83,6 +85,7 @@ ZITADEL successfully created the user.
|
|||||||
- `v1`
|
- `v1`
|
||||||
- `getUser()` [*user*](./objects#user)
|
- `getUser()` [*user*](./objects#user)
|
||||||
- `authRequest` [*auth request*](/docs/apis/actions/objects#auth-request)
|
- `authRequest` [*auth request*](/docs/apis/actions/objects#auth-request)
|
||||||
|
- `httpRequest` [*http request*](/docs/apis/actions/objects#http-request)
|
||||||
- `api`
|
- `api`
|
||||||
The second parameter contains the following fields
|
The second parameter contains the following fields
|
||||||
- `userGrants` Array of [*userGrant*](./objects#user-grant)'s
|
- `userGrants` Array of [*userGrant*](./objects#user-grant)'s
|
||||||
|
@@ -153,3 +153,17 @@ This object contains context information about the request to the [authorization
|
|||||||
<ul><li>0: OTP</li><li>1: U2F</li><li>2: U2F User verification</li></ul>
|
<ul><li>0: OTP</li><li>1: U2F</li><li>2: U2F User verification</li></ul>
|
||||||
- `audience` Array of *string*
|
- `audience` Array of *string*
|
||||||
- `authTime` *Date*
|
- `authTime` *Date*
|
||||||
|
|
||||||
|
## HTTP Request
|
||||||
|
|
||||||
|
This object is based on the Golang struct [http.Request](https://pkg.go.dev/net/http#Request), some attributes are removed as not all provided information is usable in this context.
|
||||||
|
|
||||||
|
- `method` *string*
|
||||||
|
- `url` *string*
|
||||||
|
- `proto` *string*
|
||||||
|
- `contentLength` *number*
|
||||||
|
- `host` *string*
|
||||||
|
- `form` Map *string* of Array of *string*
|
||||||
|
- `postForm` Map *string* of Array of *string*
|
||||||
|
- `remoteAddr` *string*
|
||||||
|
- `headers` Map *string* of Array of *string*
|
@@ -10,7 +10,7 @@ import (
|
|||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AuthRequestField accepts the domain.AuthRequest by value, so its not mutated
|
// AuthRequestField accepts the domain.AuthRequest by value, so it's not mutated
|
||||||
func AuthRequestField(authRequest *domain.AuthRequest) func(c *actions.FieldConfig) interface{} {
|
func AuthRequestField(authRequest *domain.AuthRequest) func(c *actions.FieldConfig) interface{} {
|
||||||
return func(c *actions.FieldConfig) interface{} {
|
return func(c *actions.FieldConfig) interface{} {
|
||||||
return AuthRequestFromDomain(c, authRequest)
|
return AuthRequestFromDomain(c, authRequest)
|
||||||
@@ -18,6 +18,12 @@ func AuthRequestField(authRequest *domain.AuthRequest) func(c *actions.FieldConf
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AuthRequestFromDomain(c *actions.FieldConfig, request *domain.AuthRequest) goja.Value {
|
func AuthRequestFromDomain(c *actions.FieldConfig, request *domain.AuthRequest) goja.Value {
|
||||||
|
var maxAuthAge *time.Duration
|
||||||
|
if request.MaxAuthAge != nil {
|
||||||
|
maxAuthAgeCopy := *request.MaxAuthAge
|
||||||
|
maxAuthAge = &maxAuthAgeCopy
|
||||||
|
}
|
||||||
|
|
||||||
return c.Runtime.ToValue(&authRequest{
|
return c.Runtime.ToValue(&authRequest{
|
||||||
Id: request.ID,
|
Id: request.ID,
|
||||||
AgentId: request.AgentID,
|
AgentId: request.AgentID,
|
||||||
@@ -34,7 +40,7 @@ func AuthRequestFromDomain(c *actions.FieldConfig, request *domain.AuthRequest)
|
|||||||
Prompt: request.Prompt,
|
Prompt: request.Prompt,
|
||||||
UiLocales: request.UiLocales,
|
UiLocales: request.UiLocales,
|
||||||
LoginHint: request.LoginHint,
|
LoginHint: request.LoginHint,
|
||||||
MaxAuthAge: request.MaxAuthAge,
|
MaxAuthAge: maxAuthAge,
|
||||||
InstanceId: request.InstanceID,
|
InstanceId: request.InstanceID,
|
||||||
Request: requestFromDomain(request.Request),
|
Request: requestFromDomain(request.Request),
|
||||||
UserId: request.UserID,
|
UserId: request.UserID,
|
||||||
|
44
internal/actions/object/http_request.go
Normal file
44
internal/actions/object/http_request.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package object
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/actions"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HTTPRequestField accepts the http.Request by value, so it's not mutated
|
||||||
|
func HTTPRequestField(request *http.Request) func(c *actions.FieldConfig) interface{} {
|
||||||
|
return func(c *actions.FieldConfig) interface{} {
|
||||||
|
return c.Runtime.ToValue(&httpRequest{
|
||||||
|
Method: request.Method,
|
||||||
|
Url: request.URL.String(),
|
||||||
|
Proto: request.Proto,
|
||||||
|
ContentLength: request.ContentLength,
|
||||||
|
Host: request.Host,
|
||||||
|
Form: copyMap(request.Form),
|
||||||
|
PostForm: copyMap(request.PostForm),
|
||||||
|
RemoteAddr: request.RemoteAddr,
|
||||||
|
Headers: copyMap(request.Header),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type httpRequest struct {
|
||||||
|
Method string
|
||||||
|
Url string
|
||||||
|
Proto string
|
||||||
|
ContentLength int64
|
||||||
|
Host string
|
||||||
|
Form map[string][]string
|
||||||
|
PostForm map[string][]string
|
||||||
|
RemoteAddr string
|
||||||
|
Headers map[string][]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyMap(src map[string][]string) map[string][]string {
|
||||||
|
dst := make(map[string][]string)
|
||||||
|
for k, v := range src {
|
||||||
|
dst[k] = v
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
@@ -3,6 +3,7 @@ package login
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/dop251/goja"
|
"github.com/dop251/goja"
|
||||||
"github.com/zitadel/oidc/v2/pkg/oidc"
|
"github.com/zitadel/oidc/v2/pkg/oidc"
|
||||||
@@ -15,8 +16,17 @@ import (
|
|||||||
iam_model "github.com/zitadel/zitadel/internal/iam/model"
|
iam_model "github.com/zitadel/zitadel/internal/iam/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (l *Login) customExternalUserMapping(ctx context.Context, user *domain.ExternalUser, tokens *oidc.Tokens, req *domain.AuthRequest, config *iam_model.IDPConfigView) (*domain.ExternalUser, error) {
|
func (l *Login) runPostExternalAuthenticationActions(
|
||||||
resourceOwner := req.RequestedOrgID
|
user *domain.ExternalUser,
|
||||||
|
tokens *oidc.Tokens,
|
||||||
|
authRequest *domain.AuthRequest,
|
||||||
|
httpRequest *http.Request,
|
||||||
|
config *iam_model.IDPConfigView,
|
||||||
|
authenticationError error,
|
||||||
|
) (*domain.ExternalUser, error) {
|
||||||
|
ctx := httpRequest.Context()
|
||||||
|
|
||||||
|
resourceOwner := authRequest.RequestedOrgID
|
||||||
if resourceOwner == "" {
|
if resourceOwner == "" {
|
||||||
resourceOwner = config.AggregateID
|
resourceOwner = config.AggregateID
|
||||||
}
|
}
|
||||||
@@ -69,6 +79,11 @@ func (l *Login) customExternalUserMapping(ctx context.Context, user *domain.Exte
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
authErrStr := "none"
|
||||||
|
if authenticationError != nil {
|
||||||
|
authErrStr = authenticationError.Error()
|
||||||
|
}
|
||||||
|
|
||||||
for _, a := range triggerActions {
|
for _, a := range triggerActions {
|
||||||
actionCtx, cancel := context.WithTimeout(ctx, a.Timeout())
|
actionCtx, cancel := context.WithTimeout(ctx, a.Timeout())
|
||||||
|
|
||||||
@@ -77,7 +92,9 @@ func (l *Login) customExternalUserMapping(ctx context.Context, user *domain.Exte
|
|||||||
actions.SetFields("externalUser", func(c *actions.FieldConfig) interface{} {
|
actions.SetFields("externalUser", func(c *actions.FieldConfig) interface{} {
|
||||||
return object.UserFromExternalUser(c, user)
|
return object.UserFromExternalUser(c, user)
|
||||||
}),
|
}),
|
||||||
actions.SetFields("authRequest", object.AuthRequestField(req)),
|
actions.SetFields("authRequest", object.AuthRequestField(authRequest)),
|
||||||
|
actions.SetFields("httpRequest", object.HTTPRequestField(httpRequest)),
|
||||||
|
actions.SetFields("authError", authErrStr),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -109,10 +126,17 @@ const (
|
|||||||
authMethodPasswordless authMethod = "passwordless"
|
authMethodPasswordless authMethod = "passwordless"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (l *Login) triggerPostLocalAuthentication(ctx context.Context, req *domain.AuthRequest, authMethod authMethod, authenticationError error) ([]*domain.Metadata, error) {
|
func (l *Login) runPostInternalAuthenticationActions(
|
||||||
resourceOwner := req.RequestedOrgID
|
authRequest *domain.AuthRequest,
|
||||||
|
httpRequest *http.Request,
|
||||||
|
authMethod authMethod,
|
||||||
|
authenticationError error,
|
||||||
|
) ([]*domain.Metadata, error) {
|
||||||
|
ctx := httpRequest.Context()
|
||||||
|
|
||||||
|
resourceOwner := authRequest.RequestedOrgID
|
||||||
if resourceOwner == "" {
|
if resourceOwner == "" {
|
||||||
resourceOwner = req.UserOrgID
|
resourceOwner = authRequest.UserOrgID
|
||||||
}
|
}
|
||||||
|
|
||||||
triggerActions, err := l.query.GetActiveActionsByFlowAndTriggerType(ctx, domain.FlowTypeInternalAuthentication, domain.TriggerTypePostAuthentication, resourceOwner, false)
|
triggerActions, err := l.query.GetActiveActionsByFlowAndTriggerType(ctx, domain.FlowTypeInternalAuthentication, domain.TriggerTypePostAuthentication, resourceOwner, false)
|
||||||
@@ -136,12 +160,12 @@ func (l *Login) triggerPostLocalAuthentication(ctx context.Context, req *domain.
|
|||||||
if authenticationError != nil {
|
if authenticationError != nil {
|
||||||
authErrStr = authenticationError.Error()
|
authErrStr = authenticationError.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxFields := actions.SetContextFields(
|
ctxFields := actions.SetContextFields(
|
||||||
actions.SetFields("v1",
|
actions.SetFields("v1",
|
||||||
actions.SetFields("authMethod", authMethod),
|
actions.SetFields("authMethod", authMethod),
|
||||||
actions.SetFields("authError", authErrStr),
|
actions.SetFields("authError", authErrStr),
|
||||||
actions.SetFields("authRequest", object.AuthRequestField(req)),
|
actions.SetFields("authRequest", object.AuthRequestField(authRequest)),
|
||||||
|
actions.SetFields("httpRequest", object.HTTPRequestField(httpRequest)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -161,7 +185,16 @@ func (l *Login) triggerPostLocalAuthentication(ctx context.Context, req *domain.
|
|||||||
return object.MetadataListToDomain(metadataList), 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) {
|
func (l *Login) runPreCreationActions(
|
||||||
|
authRequest *domain.AuthRequest,
|
||||||
|
httpRequest *http.Request,
|
||||||
|
user *domain.Human,
|
||||||
|
metadata []*domain.Metadata,
|
||||||
|
resourceOwner string,
|
||||||
|
flowType domain.FlowType,
|
||||||
|
) (*domain.Human, []*domain.Metadata, error) {
|
||||||
|
ctx := httpRequest.Context()
|
||||||
|
|
||||||
triggerActions, err := l.query.GetActiveActionsByFlowAndTriggerType(ctx, flowType, domain.TriggerTypePreCreation, resourceOwner, false)
|
triggerActions, err := l.query.GetActiveActionsByFlowAndTriggerType(ctx, flowType, domain.TriggerTypePreCreation, resourceOwner, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@@ -231,6 +264,7 @@ func (l *Login) customUserToLoginUserMapping(ctx context.Context, authRequest *d
|
|||||||
return object.UserFromHuman(c, user)
|
return object.UserFromHuman(c, user)
|
||||||
}),
|
}),
|
||||||
actions.SetFields("authRequest", object.AuthRequestField(authRequest)),
|
actions.SetFields("authRequest", object.AuthRequestField(authRequest)),
|
||||||
|
actions.SetFields("httpRequest", object.HTTPRequestField(httpRequest)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -250,7 +284,15 @@ func (l *Login) customUserToLoginUserMapping(ctx context.Context, authRequest *d
|
|||||||
return user, object.MetadataListToDomain(metadataList), err
|
return user, object.MetadataListToDomain(metadataList), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Login) customGrants(ctx context.Context, userID string, authRequest *domain.AuthRequest, resourceOwner string, flowType domain.FlowType) ([]*domain.UserGrant, error) {
|
func (l *Login) runPostCreationActions(
|
||||||
|
userID string,
|
||||||
|
authRequest *domain.AuthRequest,
|
||||||
|
httpRequest *http.Request,
|
||||||
|
resourceOwner string,
|
||||||
|
flowType domain.FlowType,
|
||||||
|
) ([]*domain.UserGrant, error) {
|
||||||
|
ctx := httpRequest.Context()
|
||||||
|
|
||||||
triggerActions, err := l.query.GetActiveActionsByFlowAndTriggerType(ctx, flowType, domain.TriggerTypePostCreation, resourceOwner, false)
|
triggerActions, err := l.query.GetActiveActionsByFlowAndTriggerType(ctx, flowType, domain.TriggerTypePostCreation, resourceOwner, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -280,6 +322,7 @@ func (l *Login) customGrants(ctx context.Context, userID string, authRequest *do
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
actions.SetFields("authRequest", object.AuthRequestField(authRequest)),
|
actions.SetFields("authRequest", object.AuthRequestField(authRequest)),
|
||||||
|
actions.SetFields("httpRequest", object.HTTPRequestField(httpRequest)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/zitadel/logging"
|
||||||
"github.com/zitadel/oidc/v2/pkg/client/rp"
|
"github.com/zitadel/oidc/v2/pkg/client/rp"
|
||||||
"github.com/zitadel/oidc/v2/pkg/oidc"
|
"github.com/zitadel/oidc/v2/pkg/oidc"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
@@ -155,18 +156,35 @@ func (l *Login) handleExternalLoginCallback(w http.ResponseWriter, r *http.Reque
|
|||||||
if idpConfig.IsOIDC {
|
if idpConfig.IsOIDC {
|
||||||
provider, err := l.getRPConfig(r.Context(), idpConfig, EndpointExternalLoginCallback)
|
provider, err := l.getRPConfig(r.Context(), idpConfig, EndpointExternalLoginCallback)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
emtpyTokens := &oidc.Tokens{Token: &oauth2.Token{}}
|
||||||
|
if _, actionErr := l.runPostExternalAuthenticationActions(&domain.ExternalUser{}, emtpyTokens, authReq, r, idpConfig, err); actionErr != nil {
|
||||||
|
logging.WithError(err).Error("both external user authentication and action post authentication failed")
|
||||||
|
}
|
||||||
|
|
||||||
l.renderLogin(w, r, authReq, err)
|
l.renderLogin(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tokens, err := rp.CodeExchange(r.Context(), data.Code, provider)
|
tokens, err := rp.CodeExchange(r.Context(), data.Code, provider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
emtpyTokens := &oidc.Tokens{Token: &oauth2.Token{}}
|
||||||
|
if _, actionErr := l.runPostExternalAuthenticationActions(&domain.ExternalUser{}, emtpyTokens, authReq, r, idpConfig, err); actionErr != nil {
|
||||||
|
logging.WithError(err).Error("both external user authentication and action post authentication failed")
|
||||||
|
}
|
||||||
|
|
||||||
l.renderLogin(w, r, authReq, err)
|
l.renderLogin(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
l.handleExternalUserAuthenticated(w, r, authReq, idpConfig, userAgentID, tokens)
|
l.handleExternalUserAuthenticated(w, r, authReq, idpConfig, userAgentID, tokens)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
l.renderError(w, r, authReq, errors.ThrowPreconditionFailed(nil, "RP-asff2", "Errors.ExternalIDP.IDPTypeNotImplemented"))
|
|
||||||
|
err = errors.ThrowPreconditionFailed(nil, "RP-asff2", "Errors.ExternalIDP.IDPTypeNotImplemented")
|
||||||
|
emtpyTokens := &oidc.Tokens{Token: &oauth2.Token{}}
|
||||||
|
if _, actionErr := l.runPostExternalAuthenticationActions(&domain.ExternalUser{}, emtpyTokens, authReq, r, idpConfig, err); actionErr != nil {
|
||||||
|
logging.WithError(err).Error("both external user authentication and action post authentication failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
l.renderError(w, r, authReq, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Login) getRPConfig(ctx context.Context, idpConfig *iam_model.IDPConfigView, callbackEndpoint string) (rp.RelyingParty, error) {
|
func (l *Login) getRPConfig(ctx context.Context, idpConfig *iam_model.IDPConfigView, callbackEndpoint string) (rp.RelyingParty, error) {
|
||||||
@@ -195,7 +213,7 @@ func (l *Login) getRPConfig(ctx context.Context, idpConfig *iam_model.IDPConfigV
|
|||||||
|
|
||||||
func (l *Login) handleExternalUserAuthenticated(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, idpConfig *iam_model.IDPConfigView, userAgentID string, tokens *oidc.Tokens) {
|
func (l *Login) handleExternalUserAuthenticated(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, idpConfig *iam_model.IDPConfigView, userAgentID string, tokens *oidc.Tokens) {
|
||||||
externalUser := l.mapTokenToLoginUser(tokens, idpConfig)
|
externalUser := l.mapTokenToLoginUser(tokens, idpConfig)
|
||||||
externalUser, err := l.customExternalUserMapping(r.Context(), externalUser, tokens, authReq, idpConfig)
|
externalUser, err := l.runPostExternalAuthenticationActions(externalUser, tokens, authReq, r, idpConfig, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderError(w, r, authReq, err)
|
l.renderError(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
@@ -383,7 +401,7 @@ func (l *Login) handleAutoRegister(w http.ResponseWriter, r *http.Request, authR
|
|||||||
|
|
||||||
user, externalIDP, metadata := l.mapExternalUserToLoginUser(orgIamPolicy, linkingUser, idpConfig)
|
user, externalIDP, metadata := l.mapExternalUserToLoginUser(orgIamPolicy, linkingUser, idpConfig)
|
||||||
|
|
||||||
user, metadata, err = l.customUserToLoginUserMapping(r.Context(), authReq, user, metadata, resourceOwner, domain.FlowTypeExternalAuthentication)
|
user, metadata, err = l.runPreCreationActions(authReq, r, user, metadata, resourceOwner, domain.FlowTypeExternalAuthentication)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderExternalNotFoundOption(w, r, authReq, orgIamPolicy, nil, nil, err)
|
l.renderExternalNotFoundOption(w, r, authReq, orgIamPolicy, nil, nil, err)
|
||||||
return
|
return
|
||||||
@@ -398,7 +416,7 @@ func (l *Login) handleAutoRegister(w http.ResponseWriter, r *http.Request, authR
|
|||||||
l.renderError(w, r, authReq, err)
|
l.renderError(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userGrants, err := l.customGrants(r.Context(), authReq.UserID, authReq, resourceOwner, domain.FlowTypeExternalAuthentication)
|
userGrants, err := l.runPostCreationActions(authReq.UserID, authReq, r, resourceOwner, domain.FlowTypeExternalAuthentication)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderError(w, r, authReq, err)
|
l.renderError(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
|
@@ -121,7 +121,7 @@ func (l *Login) handleExternalUserRegister(w http.ResponseWriter, r *http.Reques
|
|||||||
resourceOwner = authReq.RequestedOrgID
|
resourceOwner = authReq.RequestedOrgID
|
||||||
}
|
}
|
||||||
externalUser, externalIDP := l.mapTokenToLoginHumanAndExternalIDP(tokens, idpConfig)
|
externalUser, externalIDP := l.mapTokenToLoginHumanAndExternalIDP(tokens, idpConfig)
|
||||||
externalUser, err := l.customExternalUserMapping(r.Context(), externalUser, tokens, authReq, idpConfig)
|
externalUser, err := l.runPostExternalAuthenticationActions(externalUser, tokens, authReq, r, idpConfig, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegisterOption(w, r, authReq, err)
|
l.renderRegisterOption(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
@@ -161,7 +161,7 @@ func (l *Login) registerExternalUser(w http.ResponseWriter, r *http.Request, aut
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, externalIDP, metadata := l.mapExternalUserToLoginUser(orgIamPolicy, externalUser, idpConfig)
|
user, externalIDP, metadata := l.mapExternalUserToLoginUser(orgIamPolicy, externalUser, idpConfig)
|
||||||
user, metadata, err = l.customUserToLoginUserMapping(r.Context(), authReq, user, metadata, resourceOwner, domain.FlowTypeExternalAuthentication)
|
user, metadata, err = l.runPreCreationActions(authReq, r, user, metadata, resourceOwner, domain.FlowTypeExternalAuthentication)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegisterOption(w, r, authReq, err)
|
l.renderRegisterOption(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
@@ -177,7 +177,7 @@ func (l *Login) registerExternalUser(w http.ResponseWriter, r *http.Request, aut
|
|||||||
l.renderError(w, r, authReq, err)
|
l.renderError(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userGrants, err := l.customGrants(r.Context(), authReq.UserID, authReq, resourceOwner, domain.FlowTypeExternalAuthentication)
|
userGrants, err := l.runPostCreationActions(authReq.UserID, authReq, r, resourceOwner, domain.FlowTypeExternalAuthentication)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderError(w, r, authReq, err)
|
l.renderError(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
|
@@ -67,17 +67,25 @@ func (l *Login) handleJWTRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (l *Login) handleJWTExtraction(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, idpConfig *iam_model.IDPConfigView) {
|
func (l *Login) handleJWTExtraction(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, idpConfig *iam_model.IDPConfigView) {
|
||||||
token, err := getToken(r, idpConfig.JWTHeaderName)
|
token, err := getToken(r, idpConfig.JWTHeaderName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
emtpyTokens := &oidc.Tokens{Token: &oauth2.Token{}}
|
||||||
|
if _, actionErr := l.runPostExternalAuthenticationActions(&domain.ExternalUser{}, emtpyTokens, authReq, r, idpConfig, err); actionErr != nil {
|
||||||
|
logging.WithError(err).Error("both external user authentication and action post authentication failed")
|
||||||
|
}
|
||||||
|
|
||||||
l.renderError(w, r, authReq, err)
|
l.renderError(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tokenClaims, err := validateToken(r.Context(), token, idpConfig)
|
tokenClaims, err := validateToken(r.Context(), token, idpConfig)
|
||||||
|
tokens := &oidc.Tokens{IDToken: token, IDTokenClaims: tokenClaims, Token: &oauth2.Token{}}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if _, actionErr := l.runPostExternalAuthenticationActions(&domain.ExternalUser{}, tokens, authReq, r, idpConfig, err); actionErr != nil {
|
||||||
|
logging.WithError(err).Error("both external user authentication and action post authentication failed")
|
||||||
|
}
|
||||||
l.renderError(w, r, authReq, err)
|
l.renderError(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tokens := &oidc.Tokens{IDToken: token, IDTokenClaims: tokenClaims, Token: &oauth2.Token{}}
|
|
||||||
externalUser := l.mapTokenToLoginUser(tokens, idpConfig)
|
externalUser := l.mapTokenToLoginUser(tokens, idpConfig)
|
||||||
externalUser, err = l.customExternalUserMapping(r.Context(), externalUser, tokens, authReq, idpConfig)
|
externalUser, err = l.runPostExternalAuthenticationActions(externalUser, tokens, authReq, r, idpConfig, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderError(w, r, authReq, err)
|
l.renderError(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
@@ -129,7 +137,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, externalIDP, metadata := l.mapExternalUserToLoginUser(orgIamPolicy, authReq.LinkingUsers[len(authReq.LinkingUsers)-1], idpConfig)
|
||||||
user, metadata, err = l.customUserToLoginUserMapping(r.Context(), authReq, user, metadata, resourceOwner, domain.FlowTypeExternalAuthentication)
|
user, metadata, err = l.runPreCreationActions(authReq, r, user, metadata, resourceOwner, domain.FlowTypeExternalAuthentication)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderError(w, r, authReq, err)
|
l.renderError(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
@@ -144,7 +152,7 @@ func (l *Login) jwtExtractionUserNotFound(w http.ResponseWriter, r *http.Request
|
|||||||
l.renderError(w, r, authReq, err)
|
l.renderError(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userGrants, err := l.customGrants(r.Context(), authReq.UserID, authReq, resourceOwner, domain.FlowTypeExternalAuthentication)
|
userGrants, err := l.runPostCreationActions(authReq.UserID, authReq, r, resourceOwner, domain.FlowTypeExternalAuthentication)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderError(w, r, authReq, err)
|
l.renderError(w, r, authReq, err)
|
||||||
return
|
return
|
||||||
|
@@ -37,7 +37,7 @@ func (l *Login) handleMFAVerify(w http.ResponseWriter, r *http.Request) {
|
|||||||
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
|
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))
|
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)
|
metadata, actionErr := l.runPostInternalAuthenticationActions(authReq, r, authMethodOTP, err)
|
||||||
if err == nil && actionErr == nil && len(metadata) > 0 {
|
if err == nil && actionErr == nil && len(metadata) > 0 {
|
||||||
_, err = l.command.BulkSetUserMetadata(r.Context(), authReq.UserID, authReq.UserOrgID, metadata...)
|
_, err = l.command.BulkSetUserMetadata(r.Context(), authReq.UserID, authReq.UserOrgID, metadata...)
|
||||||
} else if actionErr != nil && err == nil {
|
} else if actionErr != nil && err == nil {
|
||||||
|
@@ -72,7 +72,7 @@ func (l *Login) handleU2FVerification(w http.ResponseWriter, r *http.Request) {
|
|||||||
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
|
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))
|
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)
|
metadata, actionErr := l.runPostInternalAuthenticationActions(authReq, r, authMethodU2F, err)
|
||||||
if err == nil && actionErr == nil && len(metadata) > 0 {
|
if err == nil && actionErr == nil && len(metadata) > 0 {
|
||||||
_, err = l.command.BulkSetUserMetadata(r.Context(), authReq.UserID, authReq.UserOrgID, metadata...)
|
_, err = l.command.BulkSetUserMetadata(r.Context(), authReq.UserID, authReq.UserOrgID, metadata...)
|
||||||
} else if actionErr != nil && err == nil {
|
} else if actionErr != nil && err == nil {
|
||||||
|
@@ -40,7 +40,7 @@ func (l *Login) handlePasswordCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
err = l.authRepo.VerifyPassword(setContext(r.Context(), authReq.UserOrgID), authReq.ID, authReq.UserID, authReq.UserOrgID, data.Password, authReq.AgentID, domain.BrowserInfoFromRequest(r))
|
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)
|
metadata, actionErr := l.runPostInternalAuthenticationActions(authReq, r, authMethodPassword, err)
|
||||||
if err == nil && actionErr == nil && len(metadata) > 0 {
|
if err == nil && actionErr == nil && len(metadata) > 0 {
|
||||||
_, err = l.command.BulkSetUserMetadata(r.Context(), authReq.UserID, authReq.UserOrgID, metadata...)
|
_, err = l.command.BulkSetUserMetadata(r.Context(), authReq.UserID, authReq.UserOrgID, metadata...)
|
||||||
} else if actionErr != nil && err == nil {
|
} else if actionErr != nil && err == nil {
|
||||||
|
@@ -64,7 +64,7 @@ func (l *Login) handlePasswordlessVerification(w http.ResponseWriter, r *http.Re
|
|||||||
}
|
}
|
||||||
err = l.authRepo.VerifyPasswordless(setContext(r.Context(), authReq.UserOrgID), authReq.UserID, authReq.UserOrgID, authReq.ID, authReq.AgentID, credData, domain.BrowserInfoFromRequest(r))
|
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)
|
metadata, actionErr := l.runPostInternalAuthenticationActions(authReq, r, authMethodPasswordless, err)
|
||||||
if err == nil && actionErr == nil && len(metadata) > 0 {
|
if err == nil && actionErr == nil && len(metadata) > 0 {
|
||||||
_, err = l.command.BulkSetUserMetadata(r.Context(), authReq.UserID, authReq.UserOrgID, metadata...)
|
_, err = l.command.BulkSetUserMetadata(r.Context(), authReq.UserID, authReq.UserOrgID, metadata...)
|
||||||
} else if actionErr != nil && err == nil {
|
} else if actionErr != nil && err == nil {
|
||||||
|
@@ -91,7 +91,7 @@ func (l *Login) handleRegisterCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
// without breaking existing actions.
|
// without breaking existing actions.
|
||||||
// Also, if that field is needed, we probably also should provide it
|
// Also, if that field is needed, we probably also should provide it
|
||||||
// for ExternalAuthentication.
|
// for ExternalAuthentication.
|
||||||
user, metadatas, err := l.customUserToLoginUserMapping(r.Context(), authRequest, data.toHumanDomain(), make([]*domain.Metadata, 0), resourceOwner, domain.FlowTypeInternalAuthentication)
|
user, metadatas, err := l.runPreCreationActions(authRequest, r, data.toHumanDomain(), make([]*domain.Metadata, 0), resourceOwner, domain.FlowTypeInternalAuthentication)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegister(w, r, authRequest, data, err)
|
l.renderRegister(w, r, authRequest, data, err)
|
||||||
return
|
return
|
||||||
@@ -112,7 +112,7 @@ func (l *Login) handleRegisterCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
userGrants, err := l.customGrants(r.Context(), user.AggregateID, authRequest, resourceOwner, domain.FlowTypeInternalAuthentication)
|
userGrants, err := l.runPostCreationActions(user.AggregateID, authRequest, r, resourceOwner, domain.FlowTypeInternalAuthentication)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderError(w, r, authRequest, err)
|
l.renderError(w, r, authRequest, err)
|
||||||
return
|
return
|
||||||
|
Reference in New Issue
Block a user