diff --git a/app/controlplane/internal/service/auth.go b/app/controlplane/internal/service/auth.go index e677d153c..cab134287 100644 --- a/app/controlplane/internal/service/auth.go +++ b/app/controlplane/internal/service/auth.go @@ -317,6 +317,7 @@ func callbackHandler(svc *AuthService, w http.ResponseWriter, r *http.Request) * FirstName: &claims.GivenName, LastName: &claims.FamilyName, SSOGroups: claims.Groups, + Source: "oidc", }) if err != nil { return newOauthResp(http.StatusInternalServerError, fmt.Errorf("failed to find or create user: %w", err), false) diff --git a/app/controlplane/pkg/auditor/events/testdata/users/user_logs_in.json b/app/controlplane/pkg/auditor/events/testdata/users/user_logs_in.json index 817657661..c35e4bb54 100644 --- a/app/controlplane/pkg/auditor/events/testdata/users/user_logs_in.json +++ b/app/controlplane/pkg/auditor/events/testdata/users/user_logs_in.json @@ -11,7 +11,8 @@ "Info": { "user_id": "1089bb36-e27b-428b-8009-d015c8737c54", "email": "john@cyberdyne.io", + "source": "oidc", "LoggedIn": "2024-01-01T00:00:00Z" }, - "Digest": "sha256:9a2d11d9423700c50b7a9b1d6e40b3327b3fa3afe4e33f72d1c8b20d733717bd" + "Digest": "sha256:7b4b4d0f771dc72191d794a4db780b84762e48c2912d3b5f69691bda0841f6a8" } \ No newline at end of file diff --git a/app/controlplane/pkg/auditor/events/testdata/users/user_signs_up.json b/app/controlplane/pkg/auditor/events/testdata/users/user_signs_up.json index 85e9fed61..94817f95c 100644 --- a/app/controlplane/pkg/auditor/events/testdata/users/user_signs_up.json +++ b/app/controlplane/pkg/auditor/events/testdata/users/user_signs_up.json @@ -10,7 +10,8 @@ "Description": "John Connor has signed up", "Info": { "user_id": "1089bb36-e27b-428b-8009-d015c8737c54", - "email": "john@cyberdyne.io" + "email": "john@cyberdyne.io", + "source": "oidc" }, - "Digest": "sha256:d4d9f5e46478c99fef178ac4cc2cc9e01001063ccff9353d038632480ade6786" + "Digest": "sha256:6f55a8b133568683a867ef22ca27d25750cd18e5675fefe08044068ef9c17560" } \ No newline at end of file diff --git a/app/controlplane/pkg/auditor/events/user.go b/app/controlplane/pkg/auditor/events/user.go index fc892e3b2..bb501a4cb 100644 --- a/app/controlplane/pkg/auditor/events/user.go +++ b/app/controlplane/pkg/auditor/events/user.go @@ -1,5 +1,5 @@ // -// Copyright 2024-2025 The Chainloop Authors. +// Copyright 2024-2026 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -37,11 +37,12 @@ const ( UserRoleChangedActionType string = "RoleChanged" ) -// UserBase is the base struct for policy events +// UserBase is the base struct for user audit events type UserBase struct { UserID *uuid.UUID `json:"user_id,omitempty"` Email string `json:"email,omitempty"` SSOGroups []string `json:"sso_groups,omitempty"` + Source string `json:"source,omitempty"` } func (p *UserBase) RequiresActor() bool { diff --git a/app/controlplane/pkg/auditor/events/user_test.go b/app/controlplane/pkg/auditor/events/user_test.go index 28ba7a44e..3c13e78dd 100644 --- a/app/controlplane/pkg/auditor/events/user_test.go +++ b/app/controlplane/pkg/auditor/events/user_test.go @@ -1,5 +1,5 @@ // -// Copyright 2024-2025 The Chainloop Authors. +// Copyright 2024-2026 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -49,6 +49,7 @@ func TestUserEvents(t *testing.T) { UserBase: &events.UserBase{ UserID: uuidPtr(userUUID), Email: testEmail, + Source: "oidc", }, }, expected: "testdata/users/user_signs_up.json", @@ -59,6 +60,7 @@ func TestUserEvents(t *testing.T) { UserBase: &events.UserBase{ UserID: uuidPtr(userUUID), Email: testEmail, + Source: "oidc", }, LoggedIn: time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC), }, diff --git a/app/controlplane/pkg/biz/user.go b/app/controlplane/pkg/biz/user.go index 8a81e6b11..357f49fdc 100644 --- a/app/controlplane/pkg/biz/user.go +++ b/app/controlplane/pkg/biz/user.go @@ -1,5 +1,5 @@ // -// Copyright 2024-2025 The Chainloop Authors. +// Copyright 2024-2026 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -141,6 +141,8 @@ type UpsertByEmailOpts struct { FirstName *string LastName *string SSOGroups []string + // Source indicates the authentication method used (e.g., "oidc", "saml") + Source string } // UpsertByEmail finds or creates a user by email. By default, it will auto-onboard the user @@ -171,6 +173,7 @@ func (uc *UserUseCase) UpsertByEmail(ctx context.Context, email string, opts *Up UserID: ToPtr(uuid.MustParse(u.ID)), Email: u.Email, SSOGroups: opts.SSOGroups, + Source: opts.Source, }, }, nil) } else { @@ -181,6 +184,7 @@ func (uc *UserUseCase) UpsertByEmail(ctx context.Context, email string, opts *Up UserID: ToPtr(uuid.MustParse(u.ID)), Email: u.Email, SSOGroups: opts.SSOGroups, + Source: opts.Source, }, LoggedIn: time.Now(), }, nil)