Skip to content

Commit 82bc9ce

Browse files
kelkarajayaeneasrzepatrik
authored
feat: adding device information to the session (#2715)
Closes #2091 See https://github.com/ory-corp/cloud/issues/3011 Co-authored-by: hackerman <[email protected]> Co-authored-by: Patrik <[email protected]>
1 parent f002649 commit 82bc9ce

38 files changed

+599
-143
lines changed

corpx/faker.go

+22
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import (
66
"reflect"
77
"time"
88

9+
"github.com/ory/kratos/session"
10+
"github.com/ory/x/stringsx"
11+
912
"github.com/bxcodec/faker/v3"
1013

1114
"github.com/ory/kratos/identity"
@@ -25,6 +28,18 @@ func RegisterFakes() {
2528

2629
_ = faker.SetRandomMapAndSliceSize(4)
2730

31+
if err := faker.AddProvider("ptr_geo_location", func(v reflect.Value) (interface{}, error) {
32+
return stringsx.GetPointer("Munich, Germany"), nil
33+
}); err != nil {
34+
panic(err)
35+
}
36+
37+
if err := faker.AddProvider("ptr_ipv4", func(v reflect.Value) (interface{}, error) {
38+
return stringsx.GetPointer(faker.IPv4()), nil
39+
}); err != nil {
40+
panic(err)
41+
}
42+
2843
if err := faker.AddProvider("birthdate", func(v reflect.Value) (interface{}, error) {
2944
return time.Now().Add(time.Duration(rand.Int())).Round(time.Second).UTC(), nil
3045
}); err != nil {
@@ -124,4 +139,11 @@ func RegisterFakes() {
124139
}); err != nil {
125140
panic(err)
126141
}
142+
143+
if err := faker.AddProvider("session_device", func(v reflect.Value) (interface{}, error) {
144+
var d session.Device
145+
return &d, faker.FakeData(&d)
146+
}); err != nil {
147+
panic(err)
148+
}
127149
}

internal/testhelpers/handler_mock.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func MockSetSession(t *testing.T, reg mockDeps, conf *config.Config) httprouter.
3939

4040
func MockSetSessionWithIdentity(t *testing.T, reg mockDeps, conf *config.Config, i *identity.Identity) httprouter.Handle {
4141
return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
42-
activeSession, _ := session.NewActiveSession(r.Context(), i, conf, time.Now().UTC(), identity.CredentialsTypePassword, identity.AuthenticatorAssuranceLevel1)
42+
activeSession, _ := session.NewActiveSession(r, i, conf, time.Now().UTC(), identity.CredentialsTypePassword, identity.AuthenticatorAssuranceLevel1)
4343
if aal := r.URL.Query().Get("set_aal"); len(aal) > 0 {
4444
activeSession.AuthenticatorAssuranceLevel = identity.AuthenticatorAssuranceLevel(aal)
4545
}

internal/testhelpers/identity.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package testhelpers
22

33
import (
4-
"context"
54
"testing"
65
"time"
76

7+
"github.com/ory/kratos/x"
8+
89
"github.com/stretchr/testify/require"
910

1011
"github.com/ory/kratos/driver"
@@ -14,11 +15,11 @@ import (
1415
)
1516

1617
func CreateSession(t *testing.T, reg driver.Registry) *session.Session {
17-
ctx := context.Background()
18+
req := x.NewTestHTTPRequest(t, "GET", "/sessions/whoami", nil)
1819
i := identity.NewIdentity(config.DefaultIdentityTraitsSchemaID)
19-
require.NoError(t, reg.PrivilegedIdentityPool().CreateIdentity(ctx, i))
20-
sess, err := session.NewActiveSession(ctx, i, reg.Config(), time.Now().UTC(), identity.CredentialsTypePassword, identity.AuthenticatorAssuranceLevel1)
20+
require.NoError(t, reg.PrivilegedIdentityPool().CreateIdentity(req.Context(), i))
21+
sess, err := session.NewActiveSession(req, i, reg.Config(), time.Now().UTC(), identity.CredentialsTypePassword, identity.AuthenticatorAssuranceLevel1)
2122
require.NoError(t, err)
22-
require.NoError(t, reg.SessionPersister().UpsertSession(ctx, sess))
23+
require.NoError(t, reg.SessionPersister().UpsertSession(req.Context(), sess))
2324
return sess
2425
}

internal/testhelpers/session.go

+12-10
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ func NewHTTPClientWithSessionToken(t *testing.T, reg *driver.RegistryDefault, se
137137
}
138138

139139
func NewHTTPClientWithArbitrarySessionToken(t *testing.T, reg *driver.RegistryDefault) *http.Client {
140-
ctx := context.Background()
141-
s, err := session.NewActiveSession(ctx,
140+
req := x.NewTestHTTPRequest(t, "GET", "/sessions/whoami", nil)
141+
s, err := session.NewActiveSession(req,
142142
&identity.Identity{ID: x.NewUUID(), State: identity.StateActive},
143143
NewSessionLifespanProvider(time.Hour),
144144
time.Now(),
@@ -151,8 +151,8 @@ func NewHTTPClientWithArbitrarySessionToken(t *testing.T, reg *driver.RegistryDe
151151
}
152152

153153
func NewHTTPClientWithArbitrarySessionCookie(t *testing.T, reg *driver.RegistryDefault) *http.Client {
154-
ctx := context.Background()
155-
s, err := session.NewActiveSession(ctx,
154+
req := x.NewTestHTTPRequest(t, "GET", "/sessions/whoami", nil)
155+
s, err := session.NewActiveSession(req,
156156
&identity.Identity{ID: x.NewUUID(), State: identity.StateActive},
157157
NewSessionLifespanProvider(time.Hour),
158158
time.Now(),
@@ -165,8 +165,8 @@ func NewHTTPClientWithArbitrarySessionCookie(t *testing.T, reg *driver.RegistryD
165165
}
166166

167167
func NewNoRedirectHTTPClientWithArbitrarySessionCookie(t *testing.T, reg *driver.RegistryDefault) *http.Client {
168-
ctx := context.Background()
169-
s, err := session.NewActiveSession(ctx,
168+
req := x.NewTestHTTPRequest(t, "GET", "/sessions/whoami", nil)
169+
s, err := session.NewActiveSession(req,
170170
&identity.Identity{ID: x.NewUUID(), State: identity.StateActive},
171171
NewSessionLifespanProvider(time.Hour),
172172
time.Now(),
@@ -179,8 +179,9 @@ func NewNoRedirectHTTPClientWithArbitrarySessionCookie(t *testing.T, reg *driver
179179
}
180180

181181
func NewHTTPClientWithIdentitySessionCookie(t *testing.T, reg *driver.RegistryDefault, id *identity.Identity) *http.Client {
182-
ctx := context.Background()
183-
s, err := session.NewActiveSession(ctx, id,
182+
req := x.NewTestHTTPRequest(t, "GET", "/sessions/whoami", nil)
183+
s, err := session.NewActiveSession(req,
184+
id,
184185
NewSessionLifespanProvider(time.Hour),
185186
time.Now(),
186187
identity.CredentialsTypePassword,
@@ -192,8 +193,9 @@ func NewHTTPClientWithIdentitySessionCookie(t *testing.T, reg *driver.RegistryDe
192193
}
193194

194195
func NewHTTPClientWithIdentitySessionToken(t *testing.T, reg *driver.RegistryDefault, id *identity.Identity) *http.Client {
195-
ctx := context.Background()
196-
s, err := session.NewActiveSession(ctx, id,
196+
req := x.NewTestHTTPRequest(t, "GET", "/sessions/whoami", nil)
197+
s, err := session.NewActiveSession(req,
198+
id,
197199
NewSessionLifespanProvider(time.Hour),
198200
time.Now(),
199201
identity.CredentialsTypePassword,

persistence/sql/migratest/fixtures/session/7458af86-c1d8-401c-978a-8da89133f78b.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@
3939
"metadata_public": null,
4040
"created_at": "2013-10-07T08:23:19Z",
4141
"updated_at": "2013-10-07T08:23:19Z"
42-
}
42+
},
43+
"devices": []
4344
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"id": "7458af86-c1d8-401c-978a-8da89133f98b",
3+
"active": true,
4+
"expires_at": "2013-10-07T08:23:19Z",
5+
"authenticated_at": "2013-10-07T08:23:19Z",
6+
"authenticator_assurance_level": "aal2",
7+
"authentication_methods": [
8+
{
9+
"method": "password",
10+
"aal": "",
11+
"completed_at": "0001-01-01T00:00:00Z"
12+
},
13+
{
14+
"method": "totp",
15+
"aal": "",
16+
"completed_at": "0001-01-01T00:00:00Z"
17+
}
18+
],
19+
"issued_at": "2013-10-07T08:23:19Z",
20+
"identity": {
21+
"id": "5ff66179-c240-4703-b0d8-494592cefff5",
22+
"schema_id": "default",
23+
"schema_url": "https://www.ory.sh/schemas/ZGVmYXVsdA",
24+
"state": "active",
25+
"traits": {
26+
"email": "[email protected]"
27+
},
28+
"verifiable_addresses": [
29+
{
30+
"id": "45e867e9-2745-4f16-8dd4-84334a252b61",
31+
"value": "[email protected]",
32+
"verified": false,
33+
"via": "email",
34+
"status": "pending",
35+
"created_at": "2013-10-07T08:23:19Z",
36+
"updated_at": "2013-10-07T08:23:19Z"
37+
}
38+
],
39+
"metadata_public": null,
40+
"created_at": "2013-10-07T08:23:19Z",
41+
"updated_at": "2013-10-07T08:23:19Z"
42+
},
43+
"devices": [
44+
{
45+
"id": "884f556e-eb3a-4b9f-bee3-11763642c6c0",
46+
"ip_address": "54.155.246.232",
47+
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
48+
"location": "Munich, Germany"
49+
}
50+
]
51+
}

persistence/sql/migratest/fixtures/session/8571e374-38f2-4f46-8ad3-b9d914e174d3.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@
3434
"metadata_public": null,
3535
"created_at": "2013-10-07T08:23:19Z",
3636
"updated_at": "2013-10-07T08:23:19Z"
37-
}
37+
},
38+
"devices": []
3839
}

persistence/sql/migratest/fixtures/session/dcde5aaa-f789-4d3d-ae1f-76da8d57e67c.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@
3434
"metadata_public": null,
3535
"created_at": "2013-10-07T08:23:19Z",
3636
"updated_at": "2013-10-07T08:23:19Z"
37-
}
37+
},
38+
"devices": []
3839
}

persistence/sql/migratest/fixtures/session/f38cdebe-e567-42c9-a562-1bd4dee40998.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@
3434
"metadata_public": null,
3535
"created_at": "2013-10-07T08:23:19Z",
3636
"updated_at": "2013-10-07T08:23:19Z"
37-
}
37+
},
38+
"devices": []
3839
}

persistence/sql/migratest/migration_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ func TestMigrations(t *testing.T) {
191191
var found []string
192192
for _, id := range ids {
193193
found = append(found, id.ID.String())
194-
actual, err := d.SessionPersister().GetSession(context.Background(), id.ID)
194+
actual, err := d.SessionPersister().GetSession(context.Background(), id.ID, session.ExpandEverything)
195195
require.NoErrorf(t, err, "Trying to get session: %s", id.ID)
196196
require.NotEmpty(t, actual.LogoutToken, "check if migrations have generated a logout token for existing sessions")
197197
CompareWithFixture(t, actual, "session", id.ID.String())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
INSERT INTO sessions (id, nid, issued_at, expires_at, authenticated_at, created_at, updated_at, token, identity_id,
2+
active, logout_token, aal, authentication_methods)
3+
VALUES ('7458af86-c1d8-401c-978a-8da89133f98b', '884f556e-eb3a-4b9f-bee3-11345642c6c0', '2013-10-07 08:23:19',
4+
'2013-10-07 08:23:19', '2013-10-07 08:23:19', '2013-10-07 08:23:19', '2013-10-07 08:23:19',
5+
'eVwBt7UAAAAVwBt7XAMw', '5ff66179-c240-4703-b0d8-494592cefff5', true, '123eVwBt7UAAAeVwBt7XAMw', 'aal2',
6+
'[{"method":"password"},{"method":"totp"}]');
7+
8+
INSERT INTO session_devices (id, nid, session_id, ip_address, user_agent, location, created_at, updated_at)
9+
VALUES ('884f556e-eb3a-4b9f-bee3-11763642c6c0', '884f556e-eb3a-4b9f-bee3-11345642c6c0',
10+
'7458af86-c1d8-401c-978a-8da89133f98b', '54.155.246.232',
11+
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36',
12+
'Munich, Germany', '2022-08-07 08:23:19', '2022-08-09 08:35:19');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROP TABLE "session_devices";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROP TABLE session_devices;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CREATE TABLE `session_devices`
2+
(
3+
`id` char(36) NOT NULL,
4+
PRIMARY KEY (`id`),
5+
`ip_address` VARCHAR(50) DEFAULT '',
6+
`user_agent` VARCHAR(512) DEFAULT '',
7+
`location` VARCHAR(512) DEFAULT '',
8+
`session_id` char(36) NOT NULL,
9+
`nid` char(36) NOT NULL,
10+
`created_at` DATETIME NOT NULL,
11+
`updated_at` DATETIME NOT NULL,
12+
FOREIGN KEY (`session_id`) REFERENCES `sessions` (`id`) ON DELETE cascade,
13+
FOREIGN KEY (`nid`) REFERENCES `networks` (`id`) ON DELETE cascade,
14+
CONSTRAINT unique_session_device UNIQUE (nid, session_id, ip_address, user_agent)
15+
) ENGINE = InnoDB;
16+
CREATE INDEX `session_devices_id_nid_idx` ON `session_devices` (`id`, `nid`);
17+
CREATE INDEX `session_devices_session_id_nid_idx` ON `session_devices` (`session_id`, `nid`);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CREATE TABLE "session_devices"
2+
(
3+
"id" UUID PRIMARY KEY NOT NULL,
4+
"ip_address" VARCHAR(50) DEFAULT '',
5+
"user_agent" VARCHAR(512) DEFAULT '',
6+
"location" VARCHAR(512) DEFAULT '',
7+
"nid" UUID NOT NULL,
8+
"session_id" UUID NOT NULL,
9+
"created_at" timestamp NOT NULL,
10+
"updated_at" timestamp NOT NULL,
11+
CONSTRAINT "session_metadata_sessions_id_fk" FOREIGN KEY ("session_id") REFERENCES "sessions" ("id") ON DELETE cascade,
12+
CONSTRAINT "session_metadata_nid_fk" FOREIGN KEY ("nid") REFERENCES "networks" ("id") ON DELETE cascade,
13+
CONSTRAINT unique_session_device UNIQUE (nid, session_id, ip_address, user_agent)
14+
);
15+
CREATE INDEX "session_devices_id_nid_idx" ON "session_devices" (id, nid);
16+
CREATE INDEX "session_devices_session_id_nid_idx" ON "session_devices" (session_id, nid);

0 commit comments

Comments
 (0)