No description
  • Go 90.8%
  • TypeScript 8%
  • Shell 0.5%
  • JavaScript 0.2%
  • Makefile 0.2%
  • Other 0.1%
Find a file
Robert Czechowski 5a4e39edb5 Update Readme
2026-07-01 01:57:19 +02:00
.docker feat(kratos): add Landlock filesystem sandbox 2026-05-15 10:05:42 +00:00
.github chore(deps): update actions/checkout action to v7 2026-06-25 10:21:34 +00:00
.reports feat: return field name in generated node text label 2025-09-30 12:06:10 +00:00
.schema fix: unify NullDuration validation pattern across API specs and SDKs 2026-06-24 11:24:57 +00:00
.schemastore autogen: prepare for OSS release - v26.2.0 2026-03-20 11:01:06 +00:00
.vscode feat: migrate SQLite driver from mattn/go-sqlite3 to modernc.org/sqlite and remove CGO dep 2026-03-27 08:52:09 +00:00
cipher chore: upgrade herodot to fix information leaks and data races in error handling 2026-04-14 11:38:09 +00:00
cmd feat(kratos): support external_id in identity CLI commands 2026-06-22 23:27:24 +00:00
continuity fix: restore continuity container for native OIDC flows with incomplete data 2026-04-22 15:05:07 +00:00
contrib/quickstart fix: change return urls in quickstarts (#3928) 2024-05-21 17:19:05 +02:00
corpx chore: bump to Go 1.26 massive cleanup in ory/x 2026-02-19 18:55:07 +00:00
courier feat: add support for verify_new_address & notify_previous_addresses kratos hooks 2026-06-17 13:15:29 +00:00
coverage feat: passwordless browser login and registration via code to email (#3378) 2023-08-29 15:43:03 +02:00
docs chore: update OSS ory.sh to ory.com 2026-01-28 21:41:00 +00:00
driver feat(kratos): align self-service flows with browser identity best practices 2026-06-16 13:38:05 +00:00
embedx feat(kratos): align self-service flows with browser identity best practices 2026-06-16 13:38:05 +00:00
examples/go chore: rename ./internal to ./pkg to make all functions visible 2026-02-11 12:36:02 +00:00
gen/oidc/v1 feat: rework host-rewrite mechanism 2026-05-19 13:18:11 +00:00
hash fix(kratos): bound cost parameters of imported password hashes 2026-05-08 05:53:54 +00:00
hydra chore: upgrade herodot to fix information leaks and data races in error handling 2026-04-14 11:38:09 +00:00
identity test: refactor OIDC tests to minimize side-effects 2026-06-16 15:43:32 +00:00
oryx chore: simplify migrationbox internals for testdata 2026-06-23 18:20:25 +00:00
otp fix: update year 2023-01-03 08:22:16 +01:00
persistence chore(kratos): optimize session revocation by avoiding unnecessary retries 2026-06-19 09:46:35 +00:00
pkg fix: unify NullDuration validation pattern across API specs and SDKs 2026-06-24 11:24:57 +00:00
proto/oidc/v1 feat: rework host-rewrite mechanism 2026-05-19 13:18:11 +00:00
request fix(kratos): export webhook HTTP client spans and close upstream response bodies 2026-06-15 09:50:42 +00:00
schema feat: allow relaxed deviceauthn attestations in dev env 2026-06-17 16:00:05 +00:00
script chore: update to dockertest v4 2026-03-20 08:49:38 +00:00
selfservice Add impossible-travel detection as post-login hook 2026-07-01 01:57:19 +02:00
session chore(kratos): optimize session revocation by avoiding unnecessary retries 2026-06-19 09:46:35 +00:00
spec fix: unify NullDuration validation pattern across API specs and SDKs 2026-06-24 11:24:57 +00:00
test fix(kratos): restrict OIDC login_hint forwarding to prevent client swap 2026-06-16 08:14:23 +00:00
text Add impossible-travel detection as post-login hook 2026-07-01 01:57:19 +02:00
ui feat(kratos): align self-service flows with browser identity best practices 2026-06-16 13:38:05 +00:00
x fix: support multiple display-name traits in identity schemas 2026-06-23 10:00:03 +00:00
.dockerignore fix: resolve pkger issues 2020-09-03 15:21:29 +02:00
.editorconfig feat: add cypress e2e tests (#334) 2020-05-01 17:44:01 +02:00
.gitignore feat: add tests for two step login (#3959) 2024-07-11 16:08:34 +02:00
.golangci.yml chore: tighten SSRF client detection with forbidgo 2026-04-15 16:16:23 +00:00
.goreleaser.yml chore: update kratos goreleaser config 2025-10-16 09:38:21 +00:00
.grype.yaml feat: add a policy callback to customize OIDC credential linking (#4302) 2025-02-11 16:11:46 +01:00
.mailmap chore: list contributors in file (#2878) 2022-11-10 21:42:35 +01:00
.nancy-ignore ci: remove nancy false positives from .nancy-ignore (#725) 2020-10-02 08:38:53 +02:00
.nvmrc feat: allow passing transient data from registration to webhook (#3104) 2023-02-21 17:05:23 +01:00
.orycli.yml chore: unset email and name after release hook (#3026) 2023-01-16 13:33:43 +01:00
.prettierignore fix: failing CI in OSS repos 2025-08-22 11:17:05 +00:00
.reference-ignore chore: update repository templates (#731) 2020-10-02 18:19:00 +02:00
AUTHORS chore: list contributors in file (#2878) 2022-11-10 21:42:35 +01:00
buf.gen.yaml feat: client-side PKCE take 3 (#4078) 2024-09-12 09:47:22 +02:00
buf.yaml feat: client-side PKCE take 3 (#4078) 2024-09-12 09:47:22 +02:00
CHANGELOG.md autogen: prepare for OSS release - v26.2.0 2026-03-20 11:01:06 +00:00
CODE_OF_CONDUCT.md chore: update OSS ory.sh to ory.com 2026-01-28 21:41:00 +00:00
codecov.yml chore: rename ./internal to ./pkg to make all functions visible 2026-02-11 12:36:02 +00:00
CONTRIBUTING.md feat: migrate SQLite driver from mattn/go-sqlite3 to modernc.org/sqlite and remove CGO dep 2026-03-27 08:52:09 +00:00
DEVELOP.md feat: migrate SQLite driver from mattn/go-sqlite3 to modernc.org/sqlite and remove CGO dep 2026-03-27 08:52:09 +00:00
go.mod chore: improve generated code structure and modernize tooling 2026-06-11 17:05:12 +00:00
go.sum chore: improve generated code structure and modernize tooling 2026-06-11 17:05:12 +00:00
install.sh fix: always retry curl invocations to surmount transient third-party failures 2025-11-20 08:19:02 +00:00
LICENSE docs: update repository templates 2020-05-26 15:16:36 +02:00
main.go feat: pooled process-isolated Jsonnet VM 2024-01-24 13:49:49 +01:00
Makefile feat: identity region API 2026-05-04 09:41:32 +00:00
openapitools.json chore: upgrade sdk generator (#4327) 2025-03-24 10:18:30 +01:00
package-lock.json fix(deps): patch Dependabot security alerts (shell-quote, grpc-js, nestjs) 2026-06-12 07:38:44 +00:00
package.json fix(deps): patch Dependabot security alerts (shell-quote, grpc-js, nestjs) 2026-06-12 07:38:44 +00:00
quickstart-crdb.yml chore: bump to CRDB v25.4 2025-12-18 11:42:02 +00:00
quickstart-debug.yml fix: add debug quickstart yml (#780) 2020-10-20 09:40:55 +02:00
quickstart-latest.yml fix: dockerfile clean up 2021-12-16 10:24:58 +01:00
quickstart-mysql.yml feat: client-side PKCE take 3 (#4078) 2024-09-12 09:47:22 +02:00
quickstart-oathkeeper.yml fix: quickstart demos (#2940) 2023-01-04 11:26:02 +01:00
quickstart-postgres.yml feat: client-side PKCE take 3 (#4078) 2024-09-12 09:47:22 +02:00
quickstart-selinux.yml feat: add selinux compatible quickstart config (#889) 2020-12-09 10:15:28 +01:00
quickstart-standalone.yml fix: docker-compose standalone definition 2022-01-14 22:45:43 +01:00
quickstart-tracing.yml chore: update OSS ory.sh to ory.com 2026-01-28 21:41:00 +00:00
quickstart-webauthn.yml fix: use correct names in WebAuthN dialogs (#3215) 2023-04-06 11:46:34 +02:00
quickstart.yml feat(kratos): add Landlock filesystem sandbox 2026-05-15 10:05:42 +00:00
README.md Update Readme 2026-07-01 01:57:19 +02:00
SECURITY.md chore: update OSS ory.sh to ory.com 2026-01-28 21:41:00 +00:00

Impossible Travel Detection

This implements a very simple variant of an impossible travel detection

Implementation Overview

The impossible travel detection is implemented as a PostLoginHook in selfservice/hook/impossible_travel.go.

It uses the IP address currently used for the login (extracted from the request) and compares it to IP addresses of the devices belonging to the most recent created sessions. The IP addresses are passed onto getLocationForIpAddress which could do API calls to any geolocalisation service (but in this implementation is just mocked to return three static locations depending on the given IP address).

For two locations, a distance is calculated using simple linear algebra and trigonometry (MinDistanceKm). In combination with the devices updated_at timestamps and the configured maximum travel speed (currently just fixed to 1000 km/h), we can calculate whether the login looks like the user has been traveling impossibly fast.

If the login looks like the user has been traveling impossibly fast an error is returned to the users. (See notes below.)

Tests in selfservice/hook/impossible_travel_test.go test the functionality of the hook similarly to the tests in selfservice/hook/require_verified_address_test.go. Also the MinDistanceKm function is tested.

Assumptions

  • Session objects are only created and persisted after a successful login. If unsuccessful logins can lead to Session objects being persisted, we would need to filter for sessions belonging to actually successful logins, because otherwise an attacker might make it impossible for a valid user to login be creating unsuccessful logins far away from their location. The fact, that our ExecuteLoginPostHook get's a Session object gives a hint that this might actually be the case.

  • A sessions created_at and it's devices last usage timestamps are strongly correlated. If they might not be, it might be better to not use the most recently created sessions, but the most recently used sessions. However ListSessionsByIdentity only returns the most recently created sessions. So we could either fetch more sessions and sort them by their last usage value or add a new query functions to get the sessions ordered by their last usage.

Whats missing

  • The setting that impossible travel detection should be applied ond a maximal travel speed should be configurable. This can probably be done by adding the corresponding configuration values to driver/config/config.go and using these values in the impossible travel detection hook.

  • It is probably much better, to not have a single getLocationForIpAddress function, but to allow for different implementations to be used. This would allow to use different APIs for geolocalisation and have a mocked implementation for testing purposes. This would probably be done by creating a GeoLocalisationProvider interface, which could then be injected into the impossible travel hook in the same way that the PersistenceProvider is currently injected.

  • In the implementation, I'm currently using the devices' created_at timestamp instead of the updated_at timestamps. Using updated_at is much more sensible, but because the tests use reg.SessionPersister().UpsertSession() to insert the sessions into the database and this function updates the devices' updated_at timestamps, the tests are currently broken for updated_at. One fix for this would be to manually update the device's updated_at timestamp after inserting the session into the database.

Other Notes

  • I have calculated all distances in km, all durations in hours and thus all speeds in km/h, as they are the most natural to me. But depending on the conventions, this could of course also be done in miles and mph or (and this is what I would probably prefer in real production code) in SI units (i.e. meters, seconds and m/s), however this is probably not the way you want users to configure this, so you would have to convert between user provided units (km/h or mph) to SI units (m/s). (This would also simplify variable names a lot.)

  • Currently the error message that the maximum travel speed has been exceeded is shown to the user. Because this happens when we suspect illigitimate access, we probably do not want to let the attacker know WHY their loginattempt has been unsuccessful. Instead we should show the a more generic error message.