Skip to content

Commit

Permalink
Merge pull request #1367 from teamhanko/feat/1361-webhooks-incl-3rd-p…
Browse files Browse the repository at this point in the history
…arty-signinup

feat(webhooks): add webhooks trigger to thirdparty auth
  • Loading branch information
shentschel authored Feb 28, 2024
2 parents 66b70d4 + 93cc77d commit 552a8af
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 14 deletions.
4 changes: 2 additions & 2 deletions backend/handler/public_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ func NewPublicRouter(cfg *config.Config, persister persistence.Persister, promet
thirdPartyHandler := NewThirdPartyHandler(cfg, persister, sessionManager, auditLogger)
thirdparty := g.Group("thirdparty")
thirdparty.GET("/auth", thirdPartyHandler.Auth)
thirdparty.GET("/callback", thirdPartyHandler.Callback)
thirdparty.POST("/callback", thirdPartyHandler.CallbackPost)
thirdparty.GET("/callback", thirdPartyHandler.Callback, webhookMiddlware)
thirdparty.POST("/callback", thirdPartyHandler.CallbackPost, webhookMiddlware)

tokenHandler := NewTokenHandler(cfg, persister, sessionManager, auditLogger)
g.POST("/token", tokenHandler.Validate)
Expand Down
9 changes: 9 additions & 0 deletions backend/handler/thirdparty.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import (
auditlog "github.com/teamhanko/hanko/backend/audit_log"
"github.com/teamhanko/hanko/backend/config"
"github.com/teamhanko/hanko/backend/dto"
"github.com/teamhanko/hanko/backend/dto/admin"
"github.com/teamhanko/hanko/backend/persistence"
"github.com/teamhanko/hanko/backend/persistence/models"
"github.com/teamhanko/hanko/backend/session"
"github.com/teamhanko/hanko/backend/thirdparty"
"github.com/teamhanko/hanko/backend/utils"
webhookUtils "github.com/teamhanko/hanko/backend/webhooks/utils"
"golang.org/x/oauth2"
"net/http"
"net/url"
Expand Down Expand Up @@ -191,6 +193,13 @@ func (h *ThirdPartyHandler) Callback(c echo.Context) error {
return h.redirectError(c, thirdparty.ErrorServer("could not create audit log").WithCause(err), h.cfg.ThirdParty.ErrorRedirectURL)
}

if accountLinkingResult.WebhookEvent != nil {
err = webhookUtils.TriggerWebhooks(c, *accountLinkingResult.WebhookEvent, admin.FromUserModel(*accountLinkingResult.User))
if err != nil {
c.Logger().Warn(err)
}
}

return c.Redirect(http.StatusTemporaryRedirect, successRedirectTo.String())
}

Expand Down
38 changes: 26 additions & 12 deletions backend/thirdparty/linking.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ import (
"github.com/teamhanko/hanko/backend/config"
"github.com/teamhanko/hanko/backend/persistence"
"github.com/teamhanko/hanko/backend/persistence/models"
"github.com/teamhanko/hanko/backend/webhooks/events"
)

type AccountLinkingResult struct {
Type models.AuditLogType
User *models.User
Type models.AuditLogType
User *models.User
WebhookEvent *events.Event
}

const (
getIdentityFailure = "could not get identity"
)

func LinkAccount(tx *pop.Connection, cfg *config.Config, p persistence.Persister, userData *UserData, providerName string) (*AccountLinkingResult, error) {
if cfg.Emails.RequireVerification && !userData.Metadata.EmailVerified {
return nil, ErrorUnverifiedProviderEmail("third party provider email must be verified")
Expand All @@ -26,7 +32,7 @@ func LinkAccount(tx *pop.Connection, cfg *config.Config, p persistence.Persister
if identity == nil {
user, err := p.GetUserPersisterWithConnection(tx).GetByEmailAddress(userData.Metadata.Email)
if err != nil {
return nil, ErrorServer("could not get identity").WithCause(err)
return nil, ErrorServer(getIdentityFailure).WithCause(err)
}

if user == nil {
Expand All @@ -47,22 +53,24 @@ func link(tx *pop.Connection, cfg *config.Config, p persistence.Persister, userD
email := user.GetEmailByAddress(userData.Metadata.Email)
identity, err := models.NewIdentity(providerName, userData.ToMap(), email.ID)
if err != nil {
return nil, ErrorServer("could not create identity").WithCause(err)
return nil, ErrorServer(getIdentityFailure).WithCause(err)
}

err = p.GetIdentityPersisterWithConnection(tx).Create(*identity)
if err != nil {
return nil, ErrorServer("could not create identity").WithCause(err)
return nil, ErrorServer(getIdentityFailure).WithCause(err)
}

return &AccountLinkingResult{
Type: models.AuditLogThirdPartyLinkingSucceeded,
User: user,
Type: models.AuditLogThirdPartyLinkingSucceeded,
User: user,
WebhookEvent: nil,
}, nil
}

func signIn(tx *pop.Connection, cfg *config.Config, p persistence.Persister, userData *UserData, identity *models.Identity) (*AccountLinkingResult, error) {
var linkingResult *AccountLinkingResult
var webhookEvent events.Event

userPersister := p.GetUserPersisterWithConnection(tx)
emailPersister := p.GetEmailPersisterWithConnection(tx)
Expand All @@ -89,6 +97,7 @@ func signIn(tx *pop.Connection, cfg *config.Config, p persistence.Persister, use
}

identity.EmailID = email.ID
webhookEvent = events.UserUpdate
} else if email.UserID.String() != identity.Email.UserID.String() {
// The email is assigned to a different user, and so the identity is linked to multiple users. There
// is not much we can do here but return an error.
Expand Down Expand Up @@ -119,13 +128,14 @@ func signIn(tx *pop.Connection, cfg *config.Config, p persistence.Persister, use
}

identity.EmailID = email.ID
webhookEvent = events.EmailCreate
}
}

identity.Data = userData.ToMap()
terr = identityPersister.Update(*identity)
if terr != nil {
return nil, ErrorServer("could not get identity").WithCause(terr)
return nil, ErrorServer(getIdentityFailure).WithCause(terr)
}

user, terr := userPersister.Get(*identity.Email.UserID)
Expand All @@ -134,8 +144,9 @@ func signIn(tx *pop.Connection, cfg *config.Config, p persistence.Persister, use
}

linkingResult = &AccountLinkingResult{
Type: models.AuditLogThirdPartySignInSucceeded,
User: user,
Type: models.AuditLogThirdPartySignInSucceeded,
User: user,
WebhookEvent: &webhookEvent,
}

return linkingResult, nil
Expand Down Expand Up @@ -173,6 +184,7 @@ func signUp(tx *pop.Connection, cfg *config.Config, p persistence.Persister, use
if terr != nil {
return nil, ErrorServer("could not update email").WithCause(terr)
}

} else {
// No email exists, create a new one using the provider user data email
email = models.NewEmail(&user.ID, userData.Metadata.Email)
Expand Down Expand Up @@ -204,9 +216,11 @@ func signUp(tx *pop.Connection, cfg *config.Config, p persistence.Persister, use
return nil, ErrorServer("could not get user").WithCause(terr)
}

evt := events.UserCreate
linkingResult = &AccountLinkingResult{
Type: models.AuditLogThirdPartySignUpSucceeded,
User: u,
Type: models.AuditLogThirdPartySignUpSucceeded,
User: u,
WebhookEvent: &evt,
}

return linkingResult, nil
Expand Down

0 comments on commit 552a8af

Please sign in to comment.