ory / kratos

The most scalable and customizable identity server on the market. Replace your Homegrown, Auth0, Okta, Firebase with better UX and DX. Has all the tablestakes: Passkeys, Social Sign In, Multi-Factor Auth, SMS, SAML, TOTP, and more. Written in Go, cloud native, headless, API-first. Available as a service on Ory Network and for self-hosters.
https://www.ory.sh/?utm_source=github&utm_medium=banner&utm_campaign=kratos
Apache License 2.0
11.24k stars 963 forks source link

Store additional metadata with sessions #2091

Closed joekrill closed 2 years ago

joekrill commented 2 years ago

Preflight checklist

Describe your problem

There isn't a great way to distinguish between multiple sessions beyond the date it was created (and perhaps the authentication method). Once #655 (Admin/Selfservice session management #655 ) is implemented, we should be able to show user's a list of their sessions and allow them to revoke individual sessions. Most implementations will show additional information about a session, like the IP address and user agent/browser that was used. But Kratos currently does not store this information alongside each session.

For example this is what Gmail shows me when I view a list of active sessions:

Screen Shot 2021-12-30 at 12 45 12 PM

Describe your ideal solution

Ideally when a session is created (or extended?) at least the IP address and User Agent would be captured and stored. The IP address could add some complications because of proxies and request forwarding.

Perhaps there is just a metadata field that can be populated using jsonnet? Maybe a hook could allow customizing what sort of metadata is stored?

It would also be ideal if we could provide a physical location. Something like the IP2Location databases could be utilized. I'm not sure if this is something that would be out of scope for Kratos, though. It could certainly be handled outside of that.

Workarounds or alternatives

It might be possible to use a web hook that then stores this information externally, since a web hook can include the request headers. But it doesn't seem that you can ascertain a particular session ID from the payload of a webhook -- only the current identity is available? So I'm not sure this is a real great workaround.

Version

0.8.2-alpha.1

Additional Context

No response

aeneasr commented 2 years ago

Thank you for this great write-up! I think all the points made are very valid. From an implementation standpoint, I would really like for us to have a standardized way and avoid JsonNet and other dynamic configurations. Those often make systems quite slow (JsonNet is really not that fast unfortunately).

IMO we should keep track of devices and locations. So user agents, IPs, and (if possible) the geo2ip locations. And I think we should try and track all IPs associated with a session, not just the one which was used to sign in! So we might need an array of devices and locations, when they were observed, etc. So maybe something along the lines of:

type IP {
  IP net.IP
  Location ...
  SeenAt []time.Time
}

type Device struct {
  IPs []IP
  UserAgent []string
  SeenAt []time.Time
}

Or something similar! I think we should first try to nail what metadata we can and want to collect, and then how to track changes over time. Once we have that, we can easily push a PR for this :)

kelkarajay commented 2 years ago

Discussion about the implementation in progress is here - https://github.com/ory/kratos/pull/2715#issuecomment-1243533789