mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-14 09:55:12 +00:00
feat: actions (#2377)
* feat(actions): begin api * feat(actions): begin api * api and projections * fix: handle multiple statements for a single event in projections * export func type * fix test * update to new reduce interface * flows in login * feat: jwt idp * feat: command side * feat: add tests * actions and flows * fill idp views with jwt idps and return apis * add jwtEndpoint to jwt idp * begin jwt request handling * add feature * merge * merge * handle jwt idp * cleanup * bug fixes * autoregister * get token from specific header name * fix: proto * fixes * i18n * begin tests * fix and log http proxy * remove docker cache * fixes * usergrants in actions api * tests adn cleanup * cleanup * fix add user grant * set login context * i18n Co-authored-by: fabi <[email protected]>
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/oidc/pkg/client/rp"
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
http_util "github.com/caos/zitadel/internal/api/http"
|
||||
@@ -74,28 +75,24 @@ func (l *Login) handleJWTExtraction(w http.ResponseWriter, r *http.Request, auth
|
||||
}
|
||||
tokens := &oidc.Tokens{IDToken: token, IDTokenClaims: tokenClaims}
|
||||
externalUser := l.mapTokenToLoginUser(tokens, idpConfig)
|
||||
externalUser, err = l.customExternalUserMapping(externalUser, tokens, authReq, idpConfig)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
metadata := externalUser.Metadatas
|
||||
err = l.authRepo.CheckExternalUserLogin(r.Context(), authReq.ID, authReq.AgentID, externalUser, domain.BrowserInfoFromRequest(r))
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
err = nil
|
||||
}
|
||||
if !idpConfig.AutoRegister {
|
||||
l.renderExternalNotFoundOption(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
l.jwtExtractionUserNotFound(w, r, authReq, idpConfig, tokens, err)
|
||||
return
|
||||
}
|
||||
if len(metadata) > 0 {
|
||||
authReq, err = l.authRepo.AuthRequestByID(r.Context(), authReq.ID, authReq.AgentID)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
resourceOwner := l.getOrgID(authReq)
|
||||
orgIamPolicy, err := l.getOrgIamPolicy(r, resourceOwner)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
user, externalIDP := l.mapExternalUserToLoginUser(orgIamPolicy, authReq.LinkingUsers[len(authReq.LinkingUsers)-1], idpConfig)
|
||||
err = l.authRepo.AutoRegisterExternalUser(setContext(r.Context(), resourceOwner), user, externalIDP, nil, authReq.ID, authReq.AgentID, resourceOwner, domain.BrowserInfoFromRequest(r))
|
||||
_, err = l.command.BulkSetUserMetadata(setContext(r.Context(), authReq.UserOrgID), authReq.UserID, authReq.UserOrgID, metadata...)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
@@ -109,6 +106,72 @@ func (l *Login) handleJWTExtraction(w http.ResponseWriter, r *http.Request, auth
|
||||
http.Redirect(w, r, redirect, http.StatusFound)
|
||||
}
|
||||
|
||||
func (l *Login) jwtExtractionUserNotFound(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, idpConfig *iam_model.IDPConfigView, tokens *oidc.Tokens, err error) {
|
||||
if errors.IsNotFound(err) {
|
||||
err = nil
|
||||
}
|
||||
if !idpConfig.AutoRegister {
|
||||
l.renderExternalNotFoundOption(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
authReq, err = l.authRepo.AuthRequestByID(r.Context(), authReq.ID, authReq.AgentID)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
resourceOwner := l.getOrgID(authReq)
|
||||
orgIamPolicy, err := l.getOrgIamPolicy(r, resourceOwner)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
user, externalIDP, metadata := l.mapExternalUserToLoginUser(orgIamPolicy, authReq.LinkingUsers[len(authReq.LinkingUsers)-1], idpConfig)
|
||||
user, metadata, err = l.customExternalUserToLoginUserMapping(user, tokens, authReq, idpConfig, metadata)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
err = l.authRepo.AutoRegisterExternalUser(setContext(r.Context(), resourceOwner), user, externalIDP, nil, authReq.ID, authReq.AgentID, resourceOwner, metadata, domain.BrowserInfoFromRequest(r))
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
authReq, err = l.authRepo.AuthRequestByID(r.Context(), authReq.ID, authReq.AgentID)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
userGrants, err := l.customGrants(authReq.UserID, tokens, authReq, idpConfig)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
err = l.appendUserGrants(r.Context(), userGrants, resourceOwner)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
redirect, err := l.redirectToJWTCallback(authReq)
|
||||
if err != nil {
|
||||
l.renderError(w, r, nil, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, redirect, http.StatusFound)
|
||||
}
|
||||
|
||||
func (l *Login) appendUserGrants(ctx context.Context, userGrants []*domain.UserGrant, resourceOwner string) error {
|
||||
if len(userGrants) == 0 {
|
||||
return nil
|
||||
}
|
||||
for _, grant := range userGrants {
|
||||
_, err := l.command.AddUserGrant(setContext(ctx, resourceOwner), grant, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Login) redirectToJWTCallback(authReq *domain.AuthRequest) (string, error) {
|
||||
redirect, err := url.Parse(l.baseURL + EndpointJWTCallback)
|
||||
if err != nil {
|
||||
@@ -160,6 +223,7 @@ func (l *Login) handleJWTCallback(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func validateToken(ctx context.Context, token string, config *iam_model.IDPConfigView) (oidc.IDTokenClaims, error) {
|
||||
logging.Log("LOGIN-ADf42").Debug("begin token validation")
|
||||
offset := 3 * time.Second
|
||||
maxAge := time.Hour
|
||||
claims := oidc.EmptyIDTokenClaims()
|
||||
@@ -172,6 +236,7 @@ func validateToken(ctx context.Context, token string, config *iam_model.IDPConfi
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logging.Log("LOGIN-Dfg22").Debug("begin signature validation")
|
||||
keySet := rp.NewRemoteKeySet(http.DefaultClient, config.JWTKeysEndpoint)
|
||||
if err = oidc.CheckSignature(ctx, token, payload, claims, nil, keySet); err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user