mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 09:37:45 +00:00
feat(api/v2): store user agent details in the session (#6711)
This change adds the ability to set and get user agent data, such as fingerprint, IP, request headers and a description to the session. All fields are optional. Closes #6028
This commit is contained in:
@@ -6,10 +6,13 @@ import (
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
@@ -17,57 +20,61 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
expectedSessionQuery = regexp.QuoteMeta(`SELECT projections.sessions5.id,` +
|
||||
` projections.sessions5.creation_date,` +
|
||||
` projections.sessions5.change_date,` +
|
||||
` projections.sessions5.sequence,` +
|
||||
` projections.sessions5.state,` +
|
||||
` projections.sessions5.resource_owner,` +
|
||||
` projections.sessions5.creator,` +
|
||||
` projections.sessions5.user_id,` +
|
||||
` projections.sessions5.user_checked_at,` +
|
||||
expectedSessionQuery = regexp.QuoteMeta(`SELECT projections.sessions6.id,` +
|
||||
` projections.sessions6.creation_date,` +
|
||||
` projections.sessions6.change_date,` +
|
||||
` projections.sessions6.sequence,` +
|
||||
` projections.sessions6.state,` +
|
||||
` projections.sessions6.resource_owner,` +
|
||||
` projections.sessions6.creator,` +
|
||||
` projections.sessions6.user_id,` +
|
||||
` projections.sessions6.user_checked_at,` +
|
||||
` projections.login_names2.login_name,` +
|
||||
` projections.users8_humans.display_name,` +
|
||||
` projections.users8.resource_owner,` +
|
||||
` projections.sessions5.password_checked_at,` +
|
||||
` projections.sessions5.intent_checked_at,` +
|
||||
` projections.sessions5.webauthn_checked_at,` +
|
||||
` projections.sessions5.webauthn_user_verified,` +
|
||||
` projections.sessions5.totp_checked_at,` +
|
||||
` projections.sessions5.otp_sms_checked_at,` +
|
||||
` projections.sessions5.otp_email_checked_at,` +
|
||||
` projections.sessions5.metadata,` +
|
||||
` projections.sessions5.token_id` +
|
||||
` FROM projections.sessions5` +
|
||||
` LEFT JOIN projections.login_names2 ON projections.sessions5.user_id = projections.login_names2.user_id AND projections.sessions5.instance_id = projections.login_names2.instance_id` +
|
||||
` LEFT JOIN projections.users8_humans ON projections.sessions5.user_id = projections.users8_humans.user_id AND projections.sessions5.instance_id = projections.users8_humans.instance_id` +
|
||||
` LEFT JOIN projections.users8 ON projections.sessions5.user_id = projections.users8.id AND projections.sessions5.instance_id = projections.users8.instance_id` +
|
||||
` projections.sessions6.password_checked_at,` +
|
||||
` projections.sessions6.intent_checked_at,` +
|
||||
` projections.sessions6.webauthn_checked_at,` +
|
||||
` projections.sessions6.webauthn_user_verified,` +
|
||||
` projections.sessions6.totp_checked_at,` +
|
||||
` projections.sessions6.otp_sms_checked_at,` +
|
||||
` projections.sessions6.otp_email_checked_at,` +
|
||||
` projections.sessions6.metadata,` +
|
||||
` projections.sessions6.token_id,` +
|
||||
` projections.sessions6.user_agent_fingerprint_id,` +
|
||||
` projections.sessions6.user_agent_ip,` +
|
||||
` projections.sessions6.user_agent_description,` +
|
||||
` projections.sessions6.user_agent_header` +
|
||||
` FROM projections.sessions6` +
|
||||
` LEFT JOIN projections.login_names2 ON projections.sessions6.user_id = projections.login_names2.user_id AND projections.sessions6.instance_id = projections.login_names2.instance_id` +
|
||||
` LEFT JOIN projections.users8_humans ON projections.sessions6.user_id = projections.users8_humans.user_id AND projections.sessions6.instance_id = projections.users8_humans.instance_id` +
|
||||
` LEFT JOIN projections.users8 ON projections.sessions6.user_id = projections.users8.id AND projections.sessions6.instance_id = projections.users8.instance_id` +
|
||||
` AS OF SYSTEM TIME '-1 ms'`)
|
||||
expectedSessionsQuery = regexp.QuoteMeta(`SELECT projections.sessions5.id,` +
|
||||
` projections.sessions5.creation_date,` +
|
||||
` projections.sessions5.change_date,` +
|
||||
` projections.sessions5.sequence,` +
|
||||
` projections.sessions5.state,` +
|
||||
` projections.sessions5.resource_owner,` +
|
||||
` projections.sessions5.creator,` +
|
||||
` projections.sessions5.user_id,` +
|
||||
` projections.sessions5.user_checked_at,` +
|
||||
expectedSessionsQuery = regexp.QuoteMeta(`SELECT projections.sessions6.id,` +
|
||||
` projections.sessions6.creation_date,` +
|
||||
` projections.sessions6.change_date,` +
|
||||
` projections.sessions6.sequence,` +
|
||||
` projections.sessions6.state,` +
|
||||
` projections.sessions6.resource_owner,` +
|
||||
` projections.sessions6.creator,` +
|
||||
` projections.sessions6.user_id,` +
|
||||
` projections.sessions6.user_checked_at,` +
|
||||
` projections.login_names2.login_name,` +
|
||||
` projections.users8_humans.display_name,` +
|
||||
` projections.users8.resource_owner,` +
|
||||
` projections.sessions5.password_checked_at,` +
|
||||
` projections.sessions5.intent_checked_at,` +
|
||||
` projections.sessions5.webauthn_checked_at,` +
|
||||
` projections.sessions5.webauthn_user_verified,` +
|
||||
` projections.sessions5.totp_checked_at,` +
|
||||
` projections.sessions5.otp_sms_checked_at,` +
|
||||
` projections.sessions5.otp_email_checked_at,` +
|
||||
` projections.sessions5.metadata,` +
|
||||
` projections.sessions6.password_checked_at,` +
|
||||
` projections.sessions6.intent_checked_at,` +
|
||||
` projections.sessions6.webauthn_checked_at,` +
|
||||
` projections.sessions6.webauthn_user_verified,` +
|
||||
` projections.sessions6.totp_checked_at,` +
|
||||
` projections.sessions6.otp_sms_checked_at,` +
|
||||
` projections.sessions6.otp_email_checked_at,` +
|
||||
` projections.sessions6.metadata,` +
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM projections.sessions5` +
|
||||
` LEFT JOIN projections.login_names2 ON projections.sessions5.user_id = projections.login_names2.user_id AND projections.sessions5.instance_id = projections.login_names2.instance_id` +
|
||||
` LEFT JOIN projections.users8_humans ON projections.sessions5.user_id = projections.users8_humans.user_id AND projections.sessions5.instance_id = projections.users8_humans.instance_id` +
|
||||
` LEFT JOIN projections.users8 ON projections.sessions5.user_id = projections.users8.id AND projections.sessions5.instance_id = projections.users8.instance_id` +
|
||||
` FROM projections.sessions6` +
|
||||
` LEFT JOIN projections.login_names2 ON projections.sessions6.user_id = projections.login_names2.user_id AND projections.sessions6.instance_id = projections.login_names2.instance_id` +
|
||||
` LEFT JOIN projections.users8_humans ON projections.sessions6.user_id = projections.users8_humans.user_id AND projections.sessions6.instance_id = projections.users8_humans.instance_id` +
|
||||
` LEFT JOIN projections.users8 ON projections.sessions6.user_id = projections.users8.id AND projections.sessions6.instance_id = projections.users8.instance_id` +
|
||||
` AS OF SYSTEM TIME '-1 ms'`)
|
||||
|
||||
sessionCols = []string{
|
||||
@@ -92,6 +99,10 @@ var (
|
||||
"otp_email_checked_at",
|
||||
"metadata",
|
||||
"token",
|
||||
"user_agent_fingerprint_id",
|
||||
"user_agent_ip",
|
||||
"user_agent_description",
|
||||
"user_agent_header",
|
||||
}
|
||||
|
||||
sessionsCols = []string{
|
||||
@@ -443,6 +454,10 @@ func Test_SessionPrepare(t *testing.T) {
|
||||
testNow,
|
||||
[]byte(`{"key": "dmFsdWU="}`),
|
||||
"tokenID",
|
||||
"fingerPrintID",
|
||||
"1.2.3.4",
|
||||
"agentDescription",
|
||||
[]byte(`{"foo":["foo","bar"]}`),
|
||||
},
|
||||
),
|
||||
},
|
||||
@@ -483,6 +498,12 @@ func Test_SessionPrepare(t *testing.T) {
|
||||
Metadata: map[string][]byte{
|
||||
"key": []byte("value"),
|
||||
},
|
||||
UserAgent: domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fingerPrintID"),
|
||||
IP: net.IPv4(1, 2, 3, 4),
|
||||
Description: gu.Ptr("agentDescription"),
|
||||
Header: http.Header{"foo": []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
Reference in New Issue
Block a user