mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
test(auth): pin the SSO callback before moving its sign-in resolution
This commit is contained in:
1 parent
91a5464aa3
commit
d76497ec13
26 files changed
+3010
No files matched your search
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?error=oidc_disabled",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": null,
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [],
|
||||
"sessions": [],
|
||||
"audit": [],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?error=oidc_denied",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "idp_denied",
|
||||
"idpError": "access_denied"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [],
|
||||
"sessions": [],
|
||||
"audit": [],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "healthlog://oidc-callback?error=oidc_denied",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "idp_denied",
|
||||
"idpError": "other"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [],
|
||||
"sessions": [],
|
||||
"audit": [],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?error=oidc_state",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": null,
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [],
|
||||
"sessions": [],
|
||||
"audit": [],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?error=oidc_state",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": null,
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [],
|
||||
"sessions": [],
|
||||
"audit": [],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?error=oidc_state",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "csrf"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [],
|
||||
"sessions": [],
|
||||
"audit": [],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?error=oidc_failed",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "exchange_or_verify_failed"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": {
|
||||
"type": "Error",
|
||||
"message": "invalid_grant"
|
||||
}
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [],
|
||||
"sessions": [],
|
||||
"audit": [],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?error=oidc_failed",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": null,
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [],
|
||||
"sessions": [],
|
||||
"audit": [],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/insights",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": null,
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [
|
||||
{
|
||||
"effect": "recordSignInDevice",
|
||||
"args": [
|
||||
{
|
||||
"userId": "<id:1>",
|
||||
"ip": "unknown",
|
||||
"userAgent": null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": null,
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [
|
||||
{
|
||||
"effect": "recordSignInDevice",
|
||||
"args": [
|
||||
{
|
||||
"userId": "<id:1>",
|
||||
"ip": "unknown",
|
||||
"userAgent": null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": null,
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [
|
||||
{
|
||||
"effect": "recordSignInDevice",
|
||||
"args": [
|
||||
{
|
||||
"userId": "<id:1>",
|
||||
"ip": "unknown",
|
||||
"userAgent": null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "duplicate_callback_authenticated"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?error=oidc_no_email",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "no_email"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?error=oidc_email_unverified",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "email_unverified"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": null,
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [
|
||||
{
|
||||
"effect": "recordSignInDevice",
|
||||
"args": [
|
||||
{
|
||||
"userId": "<id:1>",
|
||||
"ip": "unknown",
|
||||
"userAgent": null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
},
|
||||
{
|
||||
"username": "userinfo",
|
||||
"email": "userinfo@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-userinfo"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?error=oidc_identity_conflict",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "identity_conflict"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "linked-elsewhere",
|
||||
"email": "conflict@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://other.example.test",
|
||||
"oidcSub": "other-sub"
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
},
|
||||
{
|
||||
"username": "userinfo",
|
||||
"email": "userinfo@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-userinfo"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.oidc.link_conflict",
|
||||
"user": {
|
||||
"username": "linked-elsewhere"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?error=oidc_link_required",
|
||||
"setCookies": [
|
||||
"hl_oidc_link=<value>; Path=/api/auth; Expires=<date>; Max-Age=600; HttpOnly; SameSite=lax",
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "link_confirmation_required"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "linked-elsewhere",
|
||||
"email": "conflict@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://other.example.test",
|
||||
"oidcSub": "other-sub"
|
||||
},
|
||||
{
|
||||
"username": "local-only",
|
||||
"email": "local@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": null,
|
||||
"oidcSub": null
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
},
|
||||
{
|
||||
"username": "userinfo",
|
||||
"email": "userinfo@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-userinfo"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.oidc.link_conflict",
|
||||
"user": {
|
||||
"username": "linked-elsewhere"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "healthlog://oidc-callback?error=oidc_link_required",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "link_confirmation_required"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "linked-elsewhere",
|
||||
"email": "conflict@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://other.example.test",
|
||||
"oidcSub": "other-sub"
|
||||
},
|
||||
{
|
||||
"username": "local-only",
|
||||
"email": "local@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": null,
|
||||
"oidcSub": null
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
},
|
||||
{
|
||||
"username": "userinfo",
|
||||
"email": "userinfo@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-userinfo"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.oidc.link_conflict",
|
||||
"user": {
|
||||
"username": "linked-elsewhere"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?error=oidc_registration_disabled",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "registration_disabled"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "linked-elsewhere",
|
||||
"email": "conflict@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://other.example.test",
|
||||
"oidcSub": "other-sub"
|
||||
},
|
||||
{
|
||||
"username": "local-only",
|
||||
"email": "local@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": null,
|
||||
"oidcSub": null
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
},
|
||||
{
|
||||
"username": "userinfo",
|
||||
"email": "userinfo@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-userinfo"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.oidc.link_conflict",
|
||||
"user": {
|
||||
"username": "linked-elsewhere"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 0,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/login?next=%2Fmedications",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>",
|
||||
"oidc_mfa_handoff=<value>; Path=/auth/login; Expires=<date>; Max-Age=300; SameSite=lax"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.mfa.challenge"
|
||||
},
|
||||
"meta": {
|
||||
"mfa_required": true
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "linked-elsewhere",
|
||||
"email": "conflict@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://other.example.test",
|
||||
"oidcSub": "other-sub"
|
||||
},
|
||||
{
|
||||
"username": "local-only",
|
||||
"email": "local@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": null,
|
||||
"oidcSub": null
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
},
|
||||
{
|
||||
"username": "userinfo",
|
||||
"email": "userinfo@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-userinfo"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.mfa.challenge",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_conflict",
|
||||
"user": {
|
||||
"username": "linked-elsewhere"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 1,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "healthlog://oidc-callback?mfa_ticket=<value>&methods=totp%2Crecovery",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.mfa.challenge"
|
||||
},
|
||||
"meta": {
|
||||
"mfa_required": true
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "linked-elsewhere",
|
||||
"email": "conflict@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://other.example.test",
|
||||
"oidcSub": "other-sub"
|
||||
},
|
||||
{
|
||||
"username": "local-only",
|
||||
"email": "local@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": null,
|
||||
"oidcSub": null
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
},
|
||||
{
|
||||
"username": "userinfo",
|
||||
"email": "userinfo@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-userinfo"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.mfa.challenge",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.mfa.challenge",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_conflict",
|
||||
"user": {
|
||||
"username": "linked-elsewhere"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 2,
|
||||
"handoffs": 0
|
||||
}
|
||||
}
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "healthlog://oidc-callback?code=<value>",
|
||||
"setCookies": [
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.native.handoff_minted"
|
||||
},
|
||||
"meta": null,
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "linked-elsewhere",
|
||||
"email": "conflict@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://other.example.test",
|
||||
"oidcSub": "other-sub"
|
||||
},
|
||||
{
|
||||
"username": "local-only",
|
||||
"email": "local@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": null,
|
||||
"oidcSub": null
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
},
|
||||
{
|
||||
"username": "userinfo",
|
||||
"email": "userinfo@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-userinfo"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.mfa.challenge",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.mfa.challenge",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_conflict",
|
||||
"user": {
|
||||
"username": "linked-elsewhere"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.native.handoff_minted",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 2,
|
||||
"handoffs": 1
|
||||
}
|
||||
}
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/claim?error=claim_signed_in",
|
||||
"setCookies": [
|
||||
"hl_claim=; Path=/api/auth/oidc; Expires=<date>",
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "claim_signed_in"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "linked-elsewhere",
|
||||
"email": "conflict@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://other.example.test",
|
||||
"oidcSub": "other-sub"
|
||||
},
|
||||
{
|
||||
"username": "local-only",
|
||||
"email": "local@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": null,
|
||||
"oidcSub": null
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
},
|
||||
{
|
||||
"username": "userinfo",
|
||||
"email": "userinfo@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-userinfo"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.mfa.challenge",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.mfa.challenge",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_conflict",
|
||||
"user": {
|
||||
"username": "linked-elsewhere"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.native.handoff_minted",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 2,
|
||||
"handoffs": 1
|
||||
}
|
||||
}
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/claim?error=claim_expired",
|
||||
"setCookies": [
|
||||
"hl_claim=; Path=/api/auth/oidc; Expires=<date>",
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": {
|
||||
"reason": "claim_expired"
|
||||
},
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "linked-elsewhere",
|
||||
"email": "conflict@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://other.example.test",
|
||||
"oidcSub": "other-sub"
|
||||
},
|
||||
{
|
||||
"username": "local-only",
|
||||
"email": "local@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": null,
|
||||
"oidcSub": null
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
},
|
||||
{
|
||||
"username": "userinfo",
|
||||
"email": "userinfo@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-userinfo"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.mfa.challenge",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.mfa.challenge",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_conflict",
|
||||
"user": {
|
||||
"username": "linked-elsewhere"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.native.handoff_minted",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 2,
|
||||
"handoffs": 1
|
||||
}
|
||||
}
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
{
|
||||
"status": 307,
|
||||
"location": "http://localhost:3000/auth/claim?error=oidc_state",
|
||||
"setCookies": [
|
||||
"hl_claim=; Path=/api/auth/oidc; Expires=<date>",
|
||||
"oidc_auth_state=; Path=/api/auth/oidc; Expires=<date>"
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"status": 307,
|
||||
"action": {
|
||||
"name": "auth.oidc.callback"
|
||||
},
|
||||
"meta": null,
|
||||
"warnings": null,
|
||||
"error": null
|
||||
}
|
||||
],
|
||||
"effects": [],
|
||||
"stored": {
|
||||
"users": [
|
||||
{
|
||||
"username": "First",
|
||||
"email": "first.new@example.test",
|
||||
"role": "ADMIN",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-first"
|
||||
},
|
||||
{
|
||||
"username": "linked-elsewhere",
|
||||
"email": "conflict@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://other.example.test",
|
||||
"oidcSub": "other-sub"
|
||||
},
|
||||
{
|
||||
"username": "local-only",
|
||||
"email": "local@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": null,
|
||||
"oidcSub": null
|
||||
},
|
||||
{
|
||||
"username": "second",
|
||||
"email": "second@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-second"
|
||||
},
|
||||
{
|
||||
"username": "userinfo",
|
||||
"email": "userinfo@example.test",
|
||||
"role": "USER",
|
||||
"timezone": "Europe/Berlin",
|
||||
"oidcIssuer": "https://id.example.test",
|
||||
"oidcSub": "sub-userinfo"
|
||||
}
|
||||
],
|
||||
"sessions": [
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "First"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "second"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
},
|
||||
{
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
},
|
||||
"mfaVerifiedAt": null
|
||||
}
|
||||
],
|
||||
"audit": [
|
||||
{
|
||||
"action": "auth.mfa.challenge",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.mfa.challenge",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_conflict",
|
||||
"user": {
|
||||
"username": "linked-elsewhere"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.link_pending",
|
||||
"user": {
|
||||
"username": "local-only"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.login",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.native.handoff_minted",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "userinfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "auth.oidc.provisioned",
|
||||
"user": {
|
||||
"username": "First"
|
||||
}
|
||||
}
|
||||
],
|
||||
"challenges": 2,
|
||||
"handoffs": 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,395 @@
|
||||
/**
|
||||
* Parity for `GET /api/auth/oidc/callback` while its sign-in resolution moves
|
||||
* into `src/lib/auth/`.
|
||||
*
|
||||
* The provider is replaced at the four calls that would leave the process
|
||||
* (discovery, code exchange, ID-token verification, userinfo); everything
|
||||
* else is real: the sealed state cookie, sessions, MFA challenges, native
|
||||
* handoffs, the pending-link cookie, the audit ledger. The walk covers each
|
||||
* outcome the route tells apart: SSO switched off, a provider refusal, a
|
||||
* broken round trip, a missing state blob with and without a live session,
|
||||
* a forged state, a failed exchange, an exchange with no ID token,
|
||||
* first-login provisioning (the first account becomes admin), a returning
|
||||
* identity whose verified email changed, the userinfo fallback, the email
|
||||
* refusals, a link conflict, a pending link on the web and on the phone,
|
||||
* closed registration, the second factor on the web and on the phone, the
|
||||
* native handoff, and the two claim refusals. After each request the
|
||||
* snapshot holds the redirect, the cookies it set, the wide event, the
|
||||
* recorded sign-in device tail and the accounts, sessions and ledger rows.
|
||||
*/
|
||||
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { GET } from "@/app/api/auth/oidc/callback/route";
|
||||
import { encrypt } from "@/lib/crypto";
|
||||
import { OIDC_STATE_COOKIE } from "@/lib/auth/oidc-cookie";
|
||||
import { SESSION_COOKIE_NAME } from "@/lib/auth/session";
|
||||
|
||||
import { anonymous, callRoute } from "../../../kit/call-route";
|
||||
import { makeSession, makeUser } from "../../../kit/factories";
|
||||
import {
|
||||
effectRecorder,
|
||||
eventFacts,
|
||||
expectParity,
|
||||
stable,
|
||||
wideEventRecorder,
|
||||
} from "../../../kit/parity";
|
||||
import { getPrismaClient, truncateAllTables } from "../../setup";
|
||||
|
||||
vi.mock("@/lib/logging/transports", async (importOriginal) => {
|
||||
const actual =
|
||||
await importOriginal<typeof import("@/lib/logging/transports")>();
|
||||
const { wideEventRecorder: recorder } = await import("../../../kit/parity");
|
||||
return {
|
||||
...actual,
|
||||
emitIfSampled: (event: (typeof recorder.events)[number]) => {
|
||||
recorder.events.push(event);
|
||||
},
|
||||
};
|
||||
});
|
||||
vi.mock("@/lib/auth/login-alert", async (importOriginal) => {
|
||||
const actual =
|
||||
await importOriginal<typeof import("@/lib/auth/login-alert")>();
|
||||
const { effectRecorder } = await import("../../../kit/parity");
|
||||
return {
|
||||
...actual,
|
||||
recordSignInDevice: async (...args: unknown[]) => {
|
||||
effectRecorder.record("recordSignInDevice", args);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
/** What the fake provider answers for the next callback. */
|
||||
const idp = vi.hoisted(() => ({
|
||||
exchange: "ok" as "ok" | "no_id_token" | "throws",
|
||||
accessToken: false,
|
||||
identity: {
|
||||
sub: "sub-1",
|
||||
email: null as string | null,
|
||||
emailVerified: undefined as boolean | undefined,
|
||||
},
|
||||
userinfo: {
|
||||
email: null as string | null,
|
||||
emailVerified: undefined as boolean | undefined,
|
||||
},
|
||||
}));
|
||||
const ISSUER = "https://id.example.test";
|
||||
vi.mock("@/lib/auth/oidc", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("@/lib/auth/oidc")>();
|
||||
return {
|
||||
...actual,
|
||||
discoverOidcMetadata: async () => ({
|
||||
issuer: "https://id.example.test",
|
||||
authorization_endpoint: "https://id.example.test/authorize",
|
||||
token_endpoint: "https://id.example.test/token",
|
||||
jwks_uri: "https://id.example.test/jwks",
|
||||
}),
|
||||
exchangeCodeForTokens: async () => {
|
||||
if (idp.exchange === "throws") throw new Error("invalid_grant");
|
||||
return {
|
||||
...(idp.exchange === "ok" ? { id_token: "id-token" } : {}),
|
||||
...(idp.accessToken ? { access_token: "access-token" } : {}),
|
||||
token_type: "Bearer",
|
||||
};
|
||||
},
|
||||
verifyIdToken: async () => ({ ...idp.identity, name: null }),
|
||||
fetchUserinfoEmail: async () => ({ ...idp.userinfo }),
|
||||
};
|
||||
});
|
||||
|
||||
const prisma = getPrismaClient();
|
||||
const NOW = new Date("2026-10-15T12:00:00.000Z");
|
||||
const APP = "http://localhost:3000";
|
||||
const SAVED_ENV = { ...process.env };
|
||||
|
||||
interface State {
|
||||
native?: true;
|
||||
appCodeChallenge?: string;
|
||||
intent?: "claim";
|
||||
claimBinding?: string;
|
||||
next?: string;
|
||||
/** Send a different `state` in the query than the blob carries. */
|
||||
forged?: true;
|
||||
}
|
||||
|
||||
function stateCookie(state: State): string {
|
||||
return encrypt(
|
||||
JSON.stringify({
|
||||
state: "state-1",
|
||||
nonce: "nonce-1",
|
||||
codeVerifier: "verifier-1",
|
||||
next: state.next ?? "/",
|
||||
...(state.native
|
||||
? { native: true, appCodeChallenge: state.appCodeChallenge }
|
||||
: {}),
|
||||
...(state.intent
|
||||
? { intent: state.intent, claimBinding: state.claimBinding }
|
||||
: {}),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/** The redirect target with its one-time values replaced. */
|
||||
function location(headers: Headers): string | null {
|
||||
const raw = headers.get("location");
|
||||
if (!raw) return null;
|
||||
return raw.replace(
|
||||
/([?&](?:code|mfa_ticket)=)[^&]+/g,
|
||||
(_, key: string) => `${key}<value>`,
|
||||
);
|
||||
}
|
||||
|
||||
/** The cookies the response set or cleared, by name and attributes. */
|
||||
function setCookies(headers: Headers): string[] {
|
||||
return headers
|
||||
.getSetCookie()
|
||||
.map((c) =>
|
||||
c.replace(
|
||||
/^([^=]+)=([^;]*)/,
|
||||
(_, n: string, v: string) => `${n}=${v ? "<value>" : ""}`,
|
||||
),
|
||||
)
|
||||
.map((c) => c.replace(/Expires=[^;]+/i, "Expires=<date>"))
|
||||
.sort();
|
||||
}
|
||||
|
||||
async function stored() {
|
||||
const [users, sessions, audit, challenges, handoffs] = await Promise.all([
|
||||
prisma.user.findMany({
|
||||
orderBy: { username: "asc" },
|
||||
select: {
|
||||
username: true,
|
||||
email: true,
|
||||
role: true,
|
||||
timezone: true,
|
||||
oidcIssuer: true,
|
||||
oidcSub: true,
|
||||
},
|
||||
}),
|
||||
prisma.session.findMany({
|
||||
orderBy: [{ createdAt: "asc" }, { userId: "asc" }],
|
||||
select: {
|
||||
user: { select: { username: true } },
|
||||
mfaVerifiedAt: true,
|
||||
},
|
||||
}),
|
||||
prisma.auditLog.findMany({
|
||||
orderBy: [{ createdAt: "asc" }, { action: "asc" }],
|
||||
select: { action: true, user: { select: { username: true } } },
|
||||
}),
|
||||
prisma.mfaChallenge.count(),
|
||||
prisma.oidcNativeHandoff.count(),
|
||||
]);
|
||||
return { users, sessions, audit, challenges, handoffs };
|
||||
}
|
||||
|
||||
async function step(
|
||||
name: string,
|
||||
options: {
|
||||
query?: Record<string, string>;
|
||||
state?: State | null;
|
||||
cookies?: Record<string, string>;
|
||||
},
|
||||
): Promise<void> {
|
||||
await prisma.rateLimit.deleteMany({});
|
||||
wideEventRecorder.take();
|
||||
effectRecorder.take();
|
||||
const query =
|
||||
options.query ??
|
||||
({
|
||||
code: "code-1",
|
||||
state: options.state?.forged ? "state-x" : "state-1",
|
||||
} as Record<string, string>);
|
||||
const cookies: Record<string, string> = {
|
||||
...(options.state
|
||||
? { [OIDC_STATE_COOKIE]: stateCookie(options.state) }
|
||||
: {}),
|
||||
...options.cookies,
|
||||
};
|
||||
const res = await callRoute(GET, {
|
||||
method: "GET",
|
||||
route: "/api/auth/oidc/callback",
|
||||
query,
|
||||
headers: {
|
||||
cookie: Object.entries(cookies)
|
||||
.map(([k, v]) => `${k}=${v}`)
|
||||
.join("; "),
|
||||
},
|
||||
auth: anonymous,
|
||||
contract: {
|
||||
skip: "a browser redirect target, not part of the published API",
|
||||
},
|
||||
});
|
||||
const events = wideEventRecorder.take();
|
||||
expect(events.length).toBeGreaterThan(0);
|
||||
await expectParity(
|
||||
`oidc-callback.${name}`,
|
||||
stable(
|
||||
{
|
||||
status: res.status,
|
||||
location: location(res.headers),
|
||||
setCookies: setCookies(res.headers),
|
||||
events: events.map(eventFacts),
|
||||
effects: effectRecorder.take(),
|
||||
stored: await stored(),
|
||||
},
|
||||
{ since: NOW },
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function identity(
|
||||
sub: string,
|
||||
email: string | null,
|
||||
emailVerified: boolean | undefined,
|
||||
): void {
|
||||
idp.exchange = "ok";
|
||||
idp.accessToken = false;
|
||||
idp.identity = { sub, email, emailVerified };
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
vi.useFakeTimers({ toFake: ["Date"], now: NOW });
|
||||
await truncateAllTables(prisma);
|
||||
process.env.APP_URL = APP;
|
||||
process.env.NEXT_PUBLIC_APP_URL = APP;
|
||||
delete process.env.OIDC_ISSUER_URL;
|
||||
delete process.env.OIDC_ONLY;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
vi.useRealTimers();
|
||||
for (const key of [
|
||||
"APP_URL",
|
||||
"NEXT_PUBLIC_APP_URL",
|
||||
"OIDC_ISSUER_URL",
|
||||
"OIDC_CLIENT_ID",
|
||||
"OIDC_CLIENT_SECRET",
|
||||
]) {
|
||||
if (SAVED_ENV[key] === undefined) delete process.env[key];
|
||||
else process.env[key] = SAVED_ENV[key];
|
||||
}
|
||||
});
|
||||
|
||||
describe("GET /api/auth/oidc/callback parity", () => {
|
||||
it("01 SSO switched off", async () => {
|
||||
await step("01-disabled", { state: {} });
|
||||
process.env.OIDC_ISSUER_URL = ISSUER;
|
||||
process.env.OIDC_CLIENT_ID = "healthlog-test";
|
||||
process.env.OIDC_CLIENT_SECRET = "client-secret";
|
||||
});
|
||||
|
||||
it("02 the round-trip refusals", async () => {
|
||||
await step("02-idp-denied", {
|
||||
query: { error: "access_denied", state: "state-1" },
|
||||
state: {},
|
||||
});
|
||||
await step("03-idp-denied-unknown-code", {
|
||||
query: { error: "something_else" },
|
||||
state: { native: true, appCodeChallenge: "challenge-1" },
|
||||
});
|
||||
await step("04-no-code", { query: { state: "state-1" }, state: {} });
|
||||
await step("05-no-state-blob", { state: null });
|
||||
await step("06-forged-state", { state: { forged: true } });
|
||||
idp.exchange = "throws";
|
||||
await step("07-exchange-failed", { state: {} });
|
||||
idp.exchange = "no_id_token";
|
||||
await step("08-no-id-token", { state: {} });
|
||||
});
|
||||
|
||||
it("09 the first login provisions an admin", async () => {
|
||||
identity("sub-first", "First@Example.test", true);
|
||||
await step("09-provision-first", { state: { next: "/insights" } });
|
||||
identity("sub-second", "second@example.test", true);
|
||||
await step("10-provision-second", { state: {} });
|
||||
});
|
||||
|
||||
it("11 a returning identity, and a duplicate callback", async () => {
|
||||
identity("sub-first", "first.new@example.test", true);
|
||||
await step("11-returning-email-refresh", { state: {} });
|
||||
const first = await prisma.user.findFirstOrThrow({
|
||||
where: { oidcSub: "sub-first" },
|
||||
});
|
||||
const session = await makeSession(first);
|
||||
await step("12-duplicate-with-session", {
|
||||
state: null,
|
||||
cookies: { [SESSION_COOKIE_NAME]: session.cookie },
|
||||
});
|
||||
});
|
||||
|
||||
it("13 the email refusals and the userinfo fallback", async () => {
|
||||
identity("sub-noemail", null, undefined);
|
||||
await step("13-no-email", { state: {} });
|
||||
identity("sub-unverified", "unverified@example.test", false);
|
||||
await step("14-email-unverified", { state: {} });
|
||||
identity("sub-userinfo", null, undefined);
|
||||
idp.accessToken = true;
|
||||
idp.userinfo = { email: "userinfo@example.test", emailVerified: true };
|
||||
await step("15-userinfo-provision", { state: {} });
|
||||
});
|
||||
|
||||
it("16 an account already holding the email", async () => {
|
||||
await makeUser({
|
||||
username: "linked-elsewhere",
|
||||
email: "conflict@example.test",
|
||||
oidcIssuer: "https://other.example.test",
|
||||
oidcSub: "other-sub",
|
||||
});
|
||||
identity("sub-conflict", "conflict@example.test", true);
|
||||
await step("16-link-conflict", { state: {} });
|
||||
await makeUser({ username: "local-only", email: "local@example.test" });
|
||||
identity("sub-local", "local@example.test", true);
|
||||
await step("17-link-pending-web", { state: {} });
|
||||
await step("18-link-pending-native", {
|
||||
state: { native: true, appCodeChallenge: "challenge-1" },
|
||||
});
|
||||
});
|
||||
|
||||
it("19 closed registration", async () => {
|
||||
await prisma.appSettings.upsert({
|
||||
where: { id: "singleton" },
|
||||
create: { id: "singleton", registrationEnabled: false },
|
||||
update: { registrationEnabled: false },
|
||||
});
|
||||
identity("sub-late", "late@example.test", true);
|
||||
await step("19-registration-closed", { state: {} });
|
||||
await prisma.appSettings.update({
|
||||
where: { id: "singleton" },
|
||||
data: { registrationEnabled: true },
|
||||
});
|
||||
});
|
||||
|
||||
it("20 the second factor and the native handoff", async () => {
|
||||
await prisma.user.updateMany({
|
||||
where: { oidcSub: "sub-second" },
|
||||
data: { totpConfirmedAt: new Date("2026-09-01T00:00:00.000Z") },
|
||||
});
|
||||
identity("sub-second", "second@example.test", true);
|
||||
await step("20-mfa-web", { state: { next: "/medications" } });
|
||||
await step("21-mfa-native", {
|
||||
state: { native: true, appCodeChallenge: "challenge-1" },
|
||||
});
|
||||
identity("sub-userinfo", "userinfo@example.test", true);
|
||||
await step("22-native-handoff", {
|
||||
state: { native: true, appCodeChallenge: "challenge-2" },
|
||||
});
|
||||
});
|
||||
|
||||
it("23 the claim refusals", async () => {
|
||||
const someone = await prisma.user.findFirstOrThrow({
|
||||
where: { oidcSub: "sub-first" },
|
||||
});
|
||||
const session = await makeSession(someone);
|
||||
identity("sub-claimer", "claimer@example.test", true);
|
||||
await step("23-claim-signed-in", {
|
||||
state: { intent: "claim", claimBinding: "binding-1" },
|
||||
cookies: { [SESSION_COOKIE_NAME]: session.cookie },
|
||||
});
|
||||
await step("24-claim-no-cookie", {
|
||||
state: { intent: "claim", claimBinding: "binding-1" },
|
||||
});
|
||||
await step("25-claim-no-code", {
|
||||
query: { state: "state-1" },
|
||||
state: { intent: "claim", claimBinding: "binding-1" },
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user