mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 00:47:33 +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:
@@ -2,15 +2,18 @@ package session
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
@@ -23,7 +26,7 @@ func Test_sessionsToPb(t *testing.T) {
|
||||
past := now.Add(-time.Hour)
|
||||
|
||||
sessions := []*query.Session{
|
||||
{ // no factor
|
||||
{ // no factor, with user agent
|
||||
ID: "999",
|
||||
CreationDate: now,
|
||||
ChangeDate: now,
|
||||
@@ -32,6 +35,12 @@ func Test_sessionsToPb(t *testing.T) {
|
||||
ResourceOwner: "me",
|
||||
Creator: "he",
|
||||
Metadata: map[string][]byte{"hello": []byte("world")},
|
||||
UserAgent: domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fingerprintID"),
|
||||
Description: gu.Ptr("description"),
|
||||
IP: net.IPv4(1, 2, 3, 4),
|
||||
Header: http.Header{"foo": []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
{ // user factor
|
||||
ID: "999",
|
||||
@@ -114,13 +123,21 @@ func Test_sessionsToPb(t *testing.T) {
|
||||
}
|
||||
|
||||
want := []*session.Session{
|
||||
{ // no factor
|
||||
{ // no factor, with user agent
|
||||
Id: "999",
|
||||
CreationDate: timestamppb.New(now),
|
||||
ChangeDate: timestamppb.New(now),
|
||||
Sequence: 123,
|
||||
Factors: nil,
|
||||
Metadata: map[string][]byte{"hello": []byte("world")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("fingerprintID"),
|
||||
Description: gu.Ptr("description"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{ // user factor
|
||||
Id: "999",
|
||||
@@ -208,6 +225,71 @@ func Test_sessionsToPb(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_userAgentToPb(t *testing.T) {
|
||||
type args struct {
|
||||
ua domain.UserAgent
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *session.UserAgent
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
args: args{domain.UserAgent{}},
|
||||
},
|
||||
{
|
||||
name: "fingerprint id and description",
|
||||
args: args{domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fingerPrintID"),
|
||||
Description: gu.Ptr("description"),
|
||||
}},
|
||||
want: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("fingerPrintID"),
|
||||
Description: gu.Ptr("description"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with ip",
|
||||
args: args{domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fingerPrintID"),
|
||||
Description: gu.Ptr("description"),
|
||||
IP: net.IPv4(1, 2, 3, 4),
|
||||
}},
|
||||
want: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("fingerPrintID"),
|
||||
Description: gu.Ptr("description"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with header",
|
||||
args: args{domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fingerPrintID"),
|
||||
Description: gu.Ptr("description"),
|
||||
Header: http.Header{
|
||||
"foo": []string{"foo", "bar"},
|
||||
"hello": []string{"world"},
|
||||
},
|
||||
}},
|
||||
want: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("fingerPrintID"),
|
||||
Description: gu.Ptr("description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
"hello": {Values: []string{"world"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := userAgentToPb(tt.args.ua)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func mustNewTextQuery(t testing.TB, column query.Column, value string, compare query.TextComparison) query.SearchQuery {
|
||||
q, err := query.NewTextQuery(column, value, compare)
|
||||
require.NoError(t, err)
|
||||
@@ -510,3 +592,73 @@ func Test_userVerificationRequirementToDomain(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_userAgentToCommand(t *testing.T) {
|
||||
type args struct {
|
||||
userAgent *session.UserAgent
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *domain.UserAgent
|
||||
}{
|
||||
{
|
||||
name: "nil",
|
||||
args: args{nil},
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "all fields",
|
||||
args: args{&session.UserAgent{
|
||||
FingerprintId: gu.Ptr("fp1"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"hello": {
|
||||
Values: []string{"foo", "bar"},
|
||||
},
|
||||
},
|
||||
}},
|
||||
want: &domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: http.Header{
|
||||
"hello": []string{"foo", "bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid ip",
|
||||
args: args{&session.UserAgent{
|
||||
FingerprintId: gu.Ptr("fp1"),
|
||||
Ip: gu.Ptr("oops"),
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"hello": {
|
||||
Values: []string{"foo", "bar"},
|
||||
},
|
||||
},
|
||||
}},
|
||||
want: &domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fp1"),
|
||||
IP: nil,
|
||||
Description: gu.Ptr("firefox"),
|
||||
Header: http.Header{
|
||||
"hello": []string{"foo", "bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "nil fields",
|
||||
args: args{&session.UserAgent{}},
|
||||
want: &domain.UserAgent{},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := userAgentToCommand(tt.args.userAgent)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user