diff --git a/src/openforms/authentication/contrib/org_oidc/tests/data/vcr_cassettes/EmployeeAuthContextTests/EmployeeAuthContextTests.test_record_auth_context_employee.yaml b/src/openforms/authentication/contrib/org_oidc/tests/data/vcr_cassettes/EmployeeAuthContextTests/EmployeeAuthContextTests.test_record_auth_context_employee.yaml
new file mode 100644
index 0000000000..d2e5215997
--- /dev/null
+++ b/src/openforms/authentication/contrib/org_oidc/tests/data/vcr_cassettes/EmployeeAuthContextTests/EmployeeAuthContextTests.test_record_auth_context_employee.yaml
@@ -0,0 +1,371 @@
+interactions:
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate, br
+ Connection:
+ - keep-alive
+ User-Agent:
+ - python-requests/2.32.2
+ method: GET
+ uri: http://localhost:8080/realms/test/protocol/openid-connect/auth
+ response:
+ body:
+ string: "\n\n\n
\n \n
+ \ \n \n\n \n Sign
+ in to test\n \n \n \n \n \n \n\n\n\n\n\n\n"
+ headers:
+ Content-Language:
+ - en
+ Content-Security-Policy:
+ - frame-src 'self'; frame-ancestors 'self'; object-src 'none';
+ Content-Type:
+ - text/html;charset=utf-8
+ Referrer-Policy:
+ - no-referrer
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Robots-Tag:
+ - none
+ X-XSS-Protection:
+ - 1; mode=block
+ content-length:
+ - '1573'
+ status:
+ code: 400
+ message: Bad Request
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate, br
+ Connection:
+ - keep-alive
+ User-Agent:
+ - python-requests/2.32.2
+ method: GET
+ uri: http://localhost:8080/realms/test/protocol/openid-connect/auth?response_type=code&scope=openid+email+profile&client_id=testid&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauth%2Foidc%2Fcallback%2F&state=not-a-random-string&nonce=not-a-random-string
+ response:
+ body:
+ string: "\n\n\n\n \n
+ \ \n \n\n \n Sign
+ in to test\n \n \n \n \n \n \n \n\n\n\n\n
+ \ \n
\n
+ \ \n
\n
+ \
\n\n\n
\n \n\n\n\n\n\n
+ \
\n
\n\n
\n
\n\n\n"
+ headers:
+ Cache-Control:
+ - no-store, must-revalidate, max-age=0
+ Content-Language:
+ - en
+ Content-Security-Policy:
+ - frame-src 'self'; frame-ancestors 'self'; object-src 'none';
+ Content-Type:
+ - text/html;charset=utf-8
+ Referrer-Policy:
+ - no-referrer
+ Set-Cookie:
+ - AUTH_SESSION_ID=31517045-df97-49bf-9cc0-a0319ef8581c; Version=1; Path=/realms/test/;
+ SameSite=None; Secure; HttpOnly
+ - AUTH_SESSION_ID_LEGACY=31517045-df97-49bf-9cc0-a0319ef8581c; Version=1; Path=/realms/test/;
+ HttpOnly
+ - KC_RESTART=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlNzE1ZTA1MS02Y2RiLTQ4Y2MtYjRmNC1mMDcyMmM4MWY5ZDMifQ.eyJjaWQiOiJ0ZXN0aWQiLCJwdHkiOiJvcGVuaWQtY29ubmVjdCIsInJ1cmkiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXV0aC9vaWRjL2NhbGxiYWNrLyIsImFjdCI6IkFVVEhFTlRJQ0FURSIsIm5vdGVzIjp7InNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QiLCJyZXNwb25zZV90eXBlIjoiY29kZSIsInJlZGlyZWN0X3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODAwMC9hdXRoL29pZGMvY2FsbGJhY2svIiwic3RhdGUiOiJub3QtYS1yYW5kb20tc3RyaW5nIiwibm9uY2UiOiJub3QtYS1yYW5kb20tc3RyaW5nIn19.JgTcEfxWNkHibdVueNmt0tAWYaglXIfpbGI7LFh-PK8;
+ Version=1; Path=/realms/test/; HttpOnly
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Robots-Tag:
+ - none
+ X-XSS-Protection:
+ - 1; mode=block
+ content-length:
+ - '4466'
+ status:
+ code: 200
+ message: OK
+- request:
+ body: username=admin&password=admin&credentialId=&login=Sign+In
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate, br
+ Connection:
+ - keep-alive
+ Content-Length:
+ - '57'
+ Content-Type:
+ - application/x-www-form-urlencoded
+ Cookie:
+ - AUTH_SESSION_ID_LEGACY=31517045-df97-49bf-9cc0-a0319ef8581c; KC_RESTART=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlNzE1ZTA1MS02Y2RiLTQ4Y2MtYjRmNC1mMDcyMmM4MWY5ZDMifQ.eyJjaWQiOiJ0ZXN0aWQiLCJwdHkiOiJvcGVuaWQtY29ubmVjdCIsInJ1cmkiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXV0aC9vaWRjL2NhbGxiYWNrLyIsImFjdCI6IkFVVEhFTlRJQ0FURSIsIm5vdGVzIjp7InNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QiLCJyZXNwb25zZV90eXBlIjoiY29kZSIsInJlZGlyZWN0X3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODAwMC9hdXRoL29pZGMvY2FsbGJhY2svIiwic3RhdGUiOiJub3QtYS1yYW5kb20tc3RyaW5nIiwibm9uY2UiOiJub3QtYS1yYW5kb20tc3RyaW5nIn19.JgTcEfxWNkHibdVueNmt0tAWYaglXIfpbGI7LFh-PK8
+ User-Agent:
+ - python-requests/2.32.2
+ method: POST
+ uri: http://localhost:8080/realms/test/login-actions/authenticate?session_code=VMR3tVgzIZ_PDyE7-Kkpa3HPwTzl9bqbPjVTyECDang&execution=2bb88e44-ebf4-415d-8ac8-a5a340a55587&client_id=testid&tab_id=EtsdHKLstRc
+ response:
+ body:
+ string: ''
+ headers:
+ Cache-Control:
+ - no-store, must-revalidate, max-age=0
+ Content-Security-Policy:
+ - frame-src 'self'; frame-ancestors 'self'; object-src 'none';
+ Location:
+ - http://localhost:8000/auth/oidc/callback/?state=not-a-random-string&session_state=31517045-df97-49bf-9cc0-a0319ef8581c&iss=http%3A%2F%2Flocalhost%3A8080%2Frealms%2Ftest&code=74c7babe-8501-432a-abd0-dd6b87cd27f0.31517045-df97-49bf-9cc0-a0319ef8581c.adf4ad83-4550-4619-9231-73bd8d700f45
+ Referrer-Policy:
+ - no-referrer
+ Set-Cookie:
+ - KEYCLOAK_LOCALE=; Version=1; Comment=Expiring cookie; Expires=Thu, 01-Jan-1970
+ 00:00:10 GMT; Max-Age=0; Path=/realms/test/; HttpOnly
+ - KC_RESTART=; Version=1; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0;
+ Path=/realms/test/; HttpOnly
+ - KC_AUTH_STATE=; Version=1; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0;
+ Path=/realms/test/
+ - KEYCLOAK_IDENTITY=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlNzE1ZTA1MS02Y2RiLTQ4Y2MtYjRmNC1mMDcyMmM4MWY5ZDMifQ.eyJleHAiOjE3MzQ2NDQ3ODAsImlhdCI6MTczNDYwODc4MCwianRpIjoiMTk0ZmQ1MmItYTM4My00YjQ4LTk5MGQtYWI4NGY1MDMwODk4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy90ZXN0Iiwic3ViIjoiNmRiMmRiODctZGUzMS00ZTMwLTlmMjUtY2VmZTVkYThiMTU0IiwidHlwIjoiU2VyaWFsaXplZC1JRCIsInNlc3Npb25fc3RhdGUiOiIzMTUxNzA0NS1kZjk3LTQ5YmYtOWNjMC1hMDMxOWVmODU4MWMiLCJzaWQiOiIzMTUxNzA0NS1kZjk3LTQ5YmYtOWNjMC1hMDMxOWVmODU4MWMiLCJzdGF0ZV9jaGVja2VyIjoiU0ozaE5pV2phUzNSQ2FzWnQxY2NDd2x4M1N0eldORVQwTzdKZGNSZUppSSJ9.Lw29zGDSVPizpo8upphH0qy3ZlJWKS_wSHlPHl3CwnM;
+ Version=1; Path=/realms/test/; SameSite=None; Secure; HttpOnly
+ - KEYCLOAK_IDENTITY_LEGACY=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlNzE1ZTA1MS02Y2RiLTQ4Y2MtYjRmNC1mMDcyMmM4MWY5ZDMifQ.eyJleHAiOjE3MzQ2NDQ3ODAsImlhdCI6MTczNDYwODc4MCwianRpIjoiMTk0ZmQ1MmItYTM4My00YjQ4LTk5MGQtYWI4NGY1MDMwODk4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy90ZXN0Iiwic3ViIjoiNmRiMmRiODctZGUzMS00ZTMwLTlmMjUtY2VmZTVkYThiMTU0IiwidHlwIjoiU2VyaWFsaXplZC1JRCIsInNlc3Npb25fc3RhdGUiOiIzMTUxNzA0NS1kZjk3LTQ5YmYtOWNjMC1hMDMxOWVmODU4MWMiLCJzaWQiOiIzMTUxNzA0NS1kZjk3LTQ5YmYtOWNjMC1hMDMxOWVmODU4MWMiLCJzdGF0ZV9jaGVja2VyIjoiU0ozaE5pV2phUzNSQ2FzWnQxY2NDd2x4M1N0eldORVQwTzdKZGNSZUppSSJ9.Lw29zGDSVPizpo8upphH0qy3ZlJWKS_wSHlPHl3CwnM;
+ Version=1; Path=/realms/test/; HttpOnly
+ - KEYCLOAK_SESSION=test/6db2db87-de31-4e30-9f25-cefe5da8b154/31517045-df97-49bf-9cc0-a0319ef8581c;
+ Version=1; Expires=Thu, 19-Dec-2024 21:46:20 GMT; Max-Age=36000; Path=/realms/test/;
+ SameSite=None; Secure
+ - KEYCLOAK_SESSION_LEGACY=test/6db2db87-de31-4e30-9f25-cefe5da8b154/31517045-df97-49bf-9cc0-a0319ef8581c;
+ Version=1; Expires=Thu, 19-Dec-2024 21:46:20 GMT; Max-Age=36000; Path=/realms/test/
+ - KEYCLOAK_REMEMBER_ME=; Version=1; Comment=Expiring cookie; Expires=Thu, 01-Jan-1970
+ 00:00:10 GMT; Max-Age=0; Path=/realms/test/; HttpOnly
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Robots-Tag:
+ - none
+ X-XSS-Protection:
+ - 1; mode=block
+ content-length:
+ - '0'
+ status:
+ code: 302
+ message: Found
+- request:
+ body: client_id=testid&client_secret=7DB3KUAAizYCcmZufpHRVOcD0TOkNO3I&grant_type=authorization_code&code=74c7babe-8501-432a-abd0-dd6b87cd27f0.31517045-df97-49bf-9cc0-a0319ef8581c.adf4ad83-4550-4619-9231-73bd8d700f45&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauth%2Foidc%2Fcallback%2F
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate, br
+ Connection:
+ - keep-alive
+ Content-Length:
+ - '280'
+ Content-Type:
+ - application/x-www-form-urlencoded
+ User-Agent:
+ - python-requests/2.32.2
+ method: POST
+ uri: http://localhost:8080/realms/test/protocol/openid-connect/token
+ response:
+ body:
+ string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0VU5RQWN2VWN2LURGVU94XzRPMWd0MTNPZEpTb3RxRUtQWnVyczJ2UVc4In0.eyJleHAiOjE3MzQ2MDkwODAsImlhdCI6MTczNDYwODc4MCwiYXV0aF90aW1lIjoxNzM0NjA4NzgwLCJqdGkiOiI1NDdmNzQ2Mi0zODBkLTQyMjUtOGMxMy04MWIwYWVjODA0YjkiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiNmRiMmRiODctZGUzMS00ZTMwLTlmMjUtY2VmZTVkYThiMTU0IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGVzdGlkIiwibm9uY2UiOiJub3QtYS1yYW5kb20tc3RyaW5nIiwic2Vzc2lvbl9zdGF0ZSI6IjMxNTE3MDQ1LWRmOTctNDliZi05Y2MwLWEwMzE5ZWY4NTgxYyIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovLzEyNy4wLjAuMTo4MDAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLXRlc3QiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSBrdmsgZ3JvdXBzIGJzbiIsInNpZCI6IjMxNTE3MDQ1LWRmOTctNDliZi05Y2MwLWEwMzE5ZWY4NTgxYyIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJncm91cHMiOlsiUmVnaXN0cmVlcmRlcnMiLCJkZWZhdWx0LXJvbGVzLXRlc3QiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl0sInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIiwiZW1haWwiOiJhZG1pbkBleGFtcGxlLmNvbSJ9.c8QnGwJ7jOFQb3D502aZS1ch0o1uWS4EQ8YSuxUrvMH5nZPNxQicaWu3NoLB5iuc2Zc9WV6sdj_r6mZOwEjy_7TkPg4Fis422oyjlwvUH7fjhhL8TfCYv1WoC-v4vBxUWrhBo7iQZ7joVuWn0P_ISWOSHyu6_T5WJCdzh4GgIZWsEnNAfqrsPBsNpIkp1z_ts6j3KQrfI888EDq5q_YNUU7eqs9v3V72-ifOMHYbxTdAxqovX_yeugMQxeJZtrJSyFTfBRWY0Jhu4vFQRiOGjFXvztE_erloi9wYvZ-iKNHGjcjHpFp5qZrWbW0MaAYrrTX4Zew_VAH2z3MIHgzPWw","expires_in":300,"refresh_expires_in":1800,"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlNzE1ZTA1MS02Y2RiLTQ4Y2MtYjRmNC1mMDcyMmM4MWY5ZDMifQ.eyJleHAiOjE3MzQ2MTA1ODAsImlhdCI6MTczNDYwODc4MCwianRpIjoiNDFhNzE2OTItNjE0Yi00MWY5LWE1YmUtNWUwMjdlMWExYmEyIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy90ZXN0IiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy90ZXN0Iiwic3ViIjoiNmRiMmRiODctZGUzMS00ZTMwLTlmMjUtY2VmZTVkYThiMTU0IiwidHlwIjoiUmVmcmVzaCIsImF6cCI6InRlc3RpZCIsIm5vbmNlIjoibm90LWEtcmFuZG9tLXN0cmluZyIsInNlc3Npb25fc3RhdGUiOiIzMTUxNzA0NS1kZjk3LTQ5YmYtOWNjMC1hMDMxOWVmODU4MWMiLCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIGt2ayBncm91cHMgYnNuIiwic2lkIjoiMzE1MTcwNDUtZGY5Ny00OWJmLTljYzAtYTAzMTllZjg1ODFjIn0.21dtdNGB9rLr78kAAtuyZcenqoJL0OA0ktmAxR0Fejk","token_type":"Bearer","id_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0VU5RQWN2VWN2LURGVU94XzRPMWd0MTNPZEpTb3RxRUtQWnVyczJ2UVc4In0.eyJleHAiOjE3MzQ2MDkwODAsImlhdCI6MTczNDYwODc4MCwiYXV0aF90aW1lIjoxNzM0NjA4NzgwLCJqdGkiOiJhMDY2NGZhMy01ZTA2LTRjODAtOWRjOS0wYmQ3OWNkNmYxNDYiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QiLCJhdWQiOiJ0ZXN0aWQiLCJzdWIiOiI2ZGIyZGI4Ny1kZTMxLTRlMzAtOWYyNS1jZWZlNWRhOGIxNTQiLCJ0eXAiOiJJRCIsImF6cCI6InRlc3RpZCIsIm5vbmNlIjoibm90LWEtcmFuZG9tLXN0cmluZyIsInNlc3Npb25fc3RhdGUiOiIzMTUxNzA0NS1kZjk3LTQ5YmYtOWNjMC1hMDMxOWVmODU4MWMiLCJhdF9oYXNoIjoialF4WDU2M0x5OWhzcUZSUWJWS09XUSIsImFjciI6IjEiLCJzaWQiOiIzMTUxNzA0NS1kZjk3LTQ5YmYtOWNjMC1hMDMxOWVmODU4MWMiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZ3JvdXBzIjpbIlJlZ2lzdHJlZXJkZXJzIiwiZGVmYXVsdC1yb2xlcy10ZXN0Iiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5jb20ifQ.XugQu25tpBEZNtGBekFBQfmnGUa4VOWDGoBEsXiDsYVh9wY-ieHXbB10zvl9JZfjBlFUuz8kPXGEv396Sj1igGOtwUsN0zQ8bjaCK6avrAJBEMKfEpuf1PcH9svKkPTRTJ7PtsjHVmNDAiKB4HCsNK4TGe7lOSUnE-VkiPSi6y_rvsP0H3Gulcgci5SsTisF2wFfyo67KmAlefF_UlxNQ6bQijdG7W915GMyt8AWheuIQxzfnsXfxX3eymWAXJvh-yhtnCrTqLc-OBFas-XV4MwvLYElZEUO2qQwlQ9UWyyBOLnt9IeU6A39t0Lqj70cpxklOT0Hs77MF0Rc5hZQpQ","not-before-policy":0,"session_state":"31517045-df97-49bf-9cc0-a0319ef8581c","scope":"openid
+ email profile kvk groups bsn"}'
+ headers:
+ Cache-Control:
+ - no-store
+ Content-Type:
+ - application/json
+ Pragma:
+ - no-cache
+ Referrer-Policy:
+ - no-referrer
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-XSS-Protection:
+ - 1; mode=block
+ content-length:
+ - '3698'
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate, br
+ Connection:
+ - keep-alive
+ User-Agent:
+ - python-requests/2.32.2
+ method: GET
+ uri: http://localhost:8080/realms/test/protocol/openid-connect/certs
+ response:
+ body:
+ string: '{"keys":[{"kid":"4UNQAcvUcv-DFUOx_4O1gt13OdJSotqEKPZurs2vQW8","kty":"RSA","alg":"RS256","use":"sig","n":"2DOZ0qHie73SuFVR7civrl6r82YUiAghfzaMowjCg0o06AF--2lIS7vNV_PbsVVznPAAMqVrNG-8CcevEzvVZMQD9nH4DI7xlOxK0lrYu8rmMeSfOvXVbBVsWBZe0jnGNukZqjwmRE5__ttJdxPfIBT5-2L6mguQbDfhSUEEdIW7y7UfOXvqLqEcBtoIEB-ORKDTUIQwGZM5mSCy-cY3cHvvZfZVgaUUy5NvujPRXTMje4n_hG0KfEV-40G9qC2_Xvx4EooJzBZ6FSThiWhCpwhIvzcQqB6M9lHW7nU6wADhYPNCa2OKWvphwZ_zbrF4B9dmS6Zli5rBvbox9Hh45w","e":"AQAB","x5c":["MIIClzCCAX8CBgGNeYaMLTANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0ZXN0MB4XDTI0MDIwNTEzNDYxN1oXDTM0MDIwNTEzNDc1N1owDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANgzmdKh4nu90rhVUe3Ir65eq/NmFIgIIX82jKMIwoNKNOgBfvtpSEu7zVfz27FVc5zwADKlazRvvAnHrxM71WTEA/Zx+AyO8ZTsStJa2LvK5jHknzr11WwVbFgWXtI5xjbpGao8JkROf/7bSXcT3yAU+fti+poLkGw34UlBBHSFu8u1Hzl76i6hHAbaCBAfjkSg01CEMBmTOZkgsvnGN3B772X2VYGlFMuTb7oz0V0zI3uJ/4RtCnxFfuNBvagtv178eBKKCcwWehUk4YloQqcISL83EKgejPZR1u51OsAA4WDzQmtjilr6YcGf826xeAfXZkumZYuawb26MfR4eOcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAsnQG/Yi2g1XTCJn74hWv9MjxVAaZb4gBAc2AWm5VgAjhFEM9h6x6m1mQkq7JM4rIdAj8jw55Ok9CBVBIqq4G4cME3eUvVytkj2lC9zcRoAivjjZF2HPg7zNPa2TTR50asmHPRokppV6gewO/C+o5as+4P2zqDXBh61aRd/9kdQfkg14LBbH5/dYccAuvUqlTYC4IEPCvVmBNC1xsMjf0vohvoSjm9vL2bfqG/RJH0ScdCjOd5d2zju4/e2oVdluWm+vzKBQplc7tVMuKpn6LcLmVHiGNAl+EBIZH+WVLlTx0D1+kbHZsfLYG53lQg2LsvurRbWyF/a5fVM/oLTn5ag=="],"x5t":"H5xfs1pRtvX0HyVTskx7eTXx88U","x5t#S256":"XurVtKAIEyc4w9HCGOhnjoRHnYu4d9HCn_5YHmkScJg"},{"kid":"TV3Tl5jIY1nrJLSb53UKEubLR5gYiq9slq1SsDDg1HU","kty":"RSA","alg":"RSA-OAEP","use":"enc","n":"pNvU3ecpVHbJT4bCOEpw6cnV1yi65tB3I0bRF2ilLVOY944QRAGnjBBECPIzNbgqavghYp1j75F2nq6_ny1CYfoaxTV2iDpRUw8_f7sliYbl8FrLLat0S25ItlZrg5TEJHObvOqlG2_nXoeH36MRWwNhms2uCqfhn5VgtenIzpQIBolnM7zzGp21NvdJ1C_ZAUzkXC-l3oQ-BXTtpEVM4h2KpYh4gfZJWCbYij5d1e1YApKD6V61_Cs3Oa2OY7CAUyq5kgAWJZFDB6CpzIr226u3bV7F9RbrQu3Ybc_Lv33EwykscLznKWZY2Mbs3Iz_rFNv3sVX_vHpH4DHWlKu7Q","e":"AQAB","x5c":["MIIClzCCAX8CBgGNeYaMlzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0ZXN0MB4XDTI0MDIwNTEzNDYxN1oXDTM0MDIwNTEzNDc1N1owDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKTb1N3nKVR2yU+GwjhKcOnJ1dcouubQdyNG0RdopS1TmPeOEEQBp4wQRAjyMzW4Kmr4IWKdY++Rdp6uv58tQmH6GsU1dog6UVMPP3+7JYmG5fBayy2rdEtuSLZWa4OUxCRzm7zqpRtv516Hh9+jEVsDYZrNrgqn4Z+VYLXpyM6UCAaJZzO88xqdtTb3SdQv2QFM5Fwvpd6EPgV07aRFTOIdiqWIeIH2SVgm2Io+XdXtWAKSg+letfwrNzmtjmOwgFMquZIAFiWRQwegqcyK9turt21exfUW60Lt2G3Py799xMMpLHC85ylmWNjG7NyM/6xTb97FV/7x6R+Ax1pSru0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAQGJHeTYSMvp0yndbIn7DLohO9lom5nRrx/bLyb7TiRfogyJEF6rQZ66CAkQFk5eMF878fsHTuMVjtmXVBnhojhVmK91HwjsNQu/8xR6QMXNKJQMvHR245vwUGxlWRw/36ObM1D7QjCd/q+FonpBEY4m5Y6Uz1U0HR2Cbh0E2afVlPLeV+F0LKrlyVMdIaWBGWftCGIKDAHaG/PD66zbAKtxerv2fBIDq100WHPhd57BZxX+2aGJp1IaRDgkxV0E/CjEy3+Knd8xbAgUSW0Tl6OTC75exIvlbzeluEBe0wlapAb7WvBKYsipSW8G8Ey7tjoolDT4AU82EaKUPstiMnA=="],"x5t":"AlfHDI0FOPQpt3RBAILt0dtW1yw","x5t#S256":"a7bhm8-JsnfY7bL_m8Yl72hgmp5516VZlFcVloKzk08"}]}'
+ headers:
+ Cache-Control:
+ - no-cache
+ Content-Type:
+ - application/json;charset=UTF-8
+ Referrer-Policy:
+ - no-referrer
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-XSS-Protection:
+ - 1; mode=block
+ content-length:
+ - '2909'
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate, br
+ Authorization:
+ - Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0VU5RQWN2VWN2LURGVU94XzRPMWd0MTNPZEpTb3RxRUtQWnVyczJ2UVc4In0.eyJleHAiOjE3MzQ2MDkwODAsImlhdCI6MTczNDYwODc4MCwiYXV0aF90aW1lIjoxNzM0NjA4NzgwLCJqdGkiOiI1NDdmNzQ2Mi0zODBkLTQyMjUtOGMxMy04MWIwYWVjODA0YjkiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiNmRiMmRiODctZGUzMS00ZTMwLTlmMjUtY2VmZTVkYThiMTU0IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoidGVzdGlkIiwibm9uY2UiOiJub3QtYS1yYW5kb20tc3RyaW5nIiwic2Vzc2lvbl9zdGF0ZSI6IjMxNTE3MDQ1LWRmOTctNDliZi05Y2MwLWEwMzE5ZWY4NTgxYyIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovLzEyNy4wLjAuMTo4MDAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLXRlc3QiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSBrdmsgZ3JvdXBzIGJzbiIsInNpZCI6IjMxNTE3MDQ1LWRmOTctNDliZi05Y2MwLWEwMzE5ZWY4NTgxYyIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJncm91cHMiOlsiUmVnaXN0cmVlcmRlcnMiLCJkZWZhdWx0LXJvbGVzLXRlc3QiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl0sInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIiwiZW1haWwiOiJhZG1pbkBleGFtcGxlLmNvbSJ9.c8QnGwJ7jOFQb3D502aZS1ch0o1uWS4EQ8YSuxUrvMH5nZPNxQicaWu3NoLB5iuc2Zc9WV6sdj_r6mZOwEjy_7TkPg4Fis422oyjlwvUH7fjhhL8TfCYv1WoC-v4vBxUWrhBo7iQZ7joVuWn0P_ISWOSHyu6_T5WJCdzh4GgIZWsEnNAfqrsPBsNpIkp1z_ts6j3KQrfI888EDq5q_YNUU7eqs9v3V72-ifOMHYbxTdAxqovX_yeugMQxeJZtrJSyFTfBRWY0Jhu4vFQRiOGjFXvztE_erloi9wYvZ-iKNHGjcjHpFp5qZrWbW0MaAYrrTX4Zew_VAH2z3MIHgzPWw
+ Connection:
+ - keep-alive
+ User-Agent:
+ - python-requests/2.32.2
+ method: GET
+ uri: http://localhost:8080/realms/test/protocol/openid-connect/userinfo
+ response:
+ body:
+ string: eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI0VU5RQWN2VWN2LURGVU94XzRPMWd0MTNPZEpTb3RxRUtQWnVyczJ2UVc4In0.eyJzdWIiOiI2ZGIyZGI4Ny1kZTMxLTRlMzAtOWYyNS1jZWZlNWRhOGIxNTQiLCJhdWQiOiJ0ZXN0aWQiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy90ZXN0IiwiZ3JvdXBzIjpbIlJlZ2lzdHJlZXJkZXJzIiwiZGVmYXVsdC1yb2xlcy10ZXN0Iiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5jb20ifQ.vx4dCJ-Y-PEzjy8p7CNPB3yy0TyV_QugOHRbiV6UY3qHtZUnZqSsJD991QUostcYECuyTHefqfRtdCbvSJcPWI4ucosY65vshUMBtQeahsFOgNwWp2BvCkALJmEya4H_gh63vVlVZ2ZOSpWpah6eV2PNhiiYWD-Y9qEuLMzwngNvp5hna30BiRKAEsStB7izjE5pGECqkQm7pxCeZWHU81Lbh5fSo_2XvcGZ1Z-tf6DN95Oz4ers9YrG6dKSuh-HciY1zhv7mcee_tlJaeKjITue6r06163oKdjsYKRpiR4bLQ9256KafoxmU6O0IIlpkQhmtXrmaFSg0XyBYU8qcQ
+ headers:
+ Cache-Control:
+ - no-cache
+ Content-Type:
+ - application/jwt
+ Referrer-Policy:
+ - no-referrer
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains
+ X-Content-Type-Options:
+ - nosniff
+ X-XSS-Protection:
+ - 1; mode=block
+ content-length:
+ - '813'
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate, br
+ Connection:
+ - keep-alive
+ User-Agent:
+ - python-requests/2.32.2
+ method: GET
+ uri: http://localhost:8080/realms/test/protocol/openid-connect/certs
+ response:
+ body:
+ string: '{"keys":[{"kid":"4UNQAcvUcv-DFUOx_4O1gt13OdJSotqEKPZurs2vQW8","kty":"RSA","alg":"RS256","use":"sig","n":"2DOZ0qHie73SuFVR7civrl6r82YUiAghfzaMowjCg0o06AF--2lIS7vNV_PbsVVznPAAMqVrNG-8CcevEzvVZMQD9nH4DI7xlOxK0lrYu8rmMeSfOvXVbBVsWBZe0jnGNukZqjwmRE5__ttJdxPfIBT5-2L6mguQbDfhSUEEdIW7y7UfOXvqLqEcBtoIEB-ORKDTUIQwGZM5mSCy-cY3cHvvZfZVgaUUy5NvujPRXTMje4n_hG0KfEV-40G9qC2_Xvx4EooJzBZ6FSThiWhCpwhIvzcQqB6M9lHW7nU6wADhYPNCa2OKWvphwZ_zbrF4B9dmS6Zli5rBvbox9Hh45w","e":"AQAB","x5c":["MIIClzCCAX8CBgGNeYaMLTANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0ZXN0MB4XDTI0MDIwNTEzNDYxN1oXDTM0MDIwNTEzNDc1N1owDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANgzmdKh4nu90rhVUe3Ir65eq/NmFIgIIX82jKMIwoNKNOgBfvtpSEu7zVfz27FVc5zwADKlazRvvAnHrxM71WTEA/Zx+AyO8ZTsStJa2LvK5jHknzr11WwVbFgWXtI5xjbpGao8JkROf/7bSXcT3yAU+fti+poLkGw34UlBBHSFu8u1Hzl76i6hHAbaCBAfjkSg01CEMBmTOZkgsvnGN3B772X2VYGlFMuTb7oz0V0zI3uJ/4RtCnxFfuNBvagtv178eBKKCcwWehUk4YloQqcISL83EKgejPZR1u51OsAA4WDzQmtjilr6YcGf826xeAfXZkumZYuawb26MfR4eOcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAsnQG/Yi2g1XTCJn74hWv9MjxVAaZb4gBAc2AWm5VgAjhFEM9h6x6m1mQkq7JM4rIdAj8jw55Ok9CBVBIqq4G4cME3eUvVytkj2lC9zcRoAivjjZF2HPg7zNPa2TTR50asmHPRokppV6gewO/C+o5as+4P2zqDXBh61aRd/9kdQfkg14LBbH5/dYccAuvUqlTYC4IEPCvVmBNC1xsMjf0vohvoSjm9vL2bfqG/RJH0ScdCjOd5d2zju4/e2oVdluWm+vzKBQplc7tVMuKpn6LcLmVHiGNAl+EBIZH+WVLlTx0D1+kbHZsfLYG53lQg2LsvurRbWyF/a5fVM/oLTn5ag=="],"x5t":"H5xfs1pRtvX0HyVTskx7eTXx88U","x5t#S256":"XurVtKAIEyc4w9HCGOhnjoRHnYu4d9HCn_5YHmkScJg"},{"kid":"TV3Tl5jIY1nrJLSb53UKEubLR5gYiq9slq1SsDDg1HU","kty":"RSA","alg":"RSA-OAEP","use":"enc","n":"pNvU3ecpVHbJT4bCOEpw6cnV1yi65tB3I0bRF2ilLVOY944QRAGnjBBECPIzNbgqavghYp1j75F2nq6_ny1CYfoaxTV2iDpRUw8_f7sliYbl8FrLLat0S25ItlZrg5TEJHObvOqlG2_nXoeH36MRWwNhms2uCqfhn5VgtenIzpQIBolnM7zzGp21NvdJ1C_ZAUzkXC-l3oQ-BXTtpEVM4h2KpYh4gfZJWCbYij5d1e1YApKD6V61_Cs3Oa2OY7CAUyq5kgAWJZFDB6CpzIr226u3bV7F9RbrQu3Ybc_Lv33EwykscLznKWZY2Mbs3Iz_rFNv3sVX_vHpH4DHWlKu7Q","e":"AQAB","x5c":["MIIClzCCAX8CBgGNeYaMlzANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0ZXN0MB4XDTI0MDIwNTEzNDYxN1oXDTM0MDIwNTEzNDc1N1owDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKTb1N3nKVR2yU+GwjhKcOnJ1dcouubQdyNG0RdopS1TmPeOEEQBp4wQRAjyMzW4Kmr4IWKdY++Rdp6uv58tQmH6GsU1dog6UVMPP3+7JYmG5fBayy2rdEtuSLZWa4OUxCRzm7zqpRtv516Hh9+jEVsDYZrNrgqn4Z+VYLXpyM6UCAaJZzO88xqdtTb3SdQv2QFM5Fwvpd6EPgV07aRFTOIdiqWIeIH2SVgm2Io+XdXtWAKSg+letfwrNzmtjmOwgFMquZIAFiWRQwegqcyK9turt21exfUW60Lt2G3Py799xMMpLHC85ylmWNjG7NyM/6xTb97FV/7x6R+Ax1pSru0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAQGJHeTYSMvp0yndbIn7DLohO9lom5nRrx/bLyb7TiRfogyJEF6rQZ66CAkQFk5eMF878fsHTuMVjtmXVBnhojhVmK91HwjsNQu/8xR6QMXNKJQMvHR245vwUGxlWRw/36ObM1D7QjCd/q+FonpBEY4m5Y6Uz1U0HR2Cbh0E2afVlPLeV+F0LKrlyVMdIaWBGWftCGIKDAHaG/PD66zbAKtxerv2fBIDq100WHPhd57BZxX+2aGJp1IaRDgkxV0E/CjEy3+Knd8xbAgUSW0Tl6OTC75exIvlbzeluEBe0wlapAb7WvBKYsipSW8G8Ey7tjoolDT4AU82EaKUPstiMnA=="],"x5t":"AlfHDI0FOPQpt3RBAILt0dtW1yw","x5t#S256":"a7bhm8-JsnfY7bL_m8Yl72hgmp5516VZlFcVloKzk08"}]}'
+ headers:
+ Cache-Control:
+ - no-cache
+ Content-Type:
+ - application/json;charset=UTF-8
+ Referrer-Policy:
+ - no-referrer
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-XSS-Protection:
+ - 1; mode=block
+ content-length:
+ - '2909'
+ status:
+ code: 200
+ message: OK
+version: 1
diff --git a/src/openforms/authentication/contrib/org_oidc/tests/test_auth_context_data.py b/src/openforms/authentication/contrib/org_oidc/tests/test_auth_context_data.py
new file mode 100644
index 0000000000..a7ea4860c2
--- /dev/null
+++ b/src/openforms/authentication/contrib/org_oidc/tests/test_auth_context_data.py
@@ -0,0 +1,81 @@
+"""
+Test the authentication flow for a form.
+
+These tests use VCR. When re-recording, making sure to:
+
+.. code-block:: bash
+
+ cd docker
+ docker compose -f docker-compose.keycloak.yml up
+
+to bring up a Keycloak instance.
+"""
+
+from django.test import override_settings
+from django.urls import reverse
+
+from django_webtest import DjangoTestApp
+
+from openforms.authentication.tests.utils import URLsHelper
+from openforms.forms.tests.factories import FormFactory
+from openforms.submissions.models import Submission
+from openforms.utils.tests.keycloak import keycloak_login
+
+from .base import IntegrationTestsBase, mock_org_oidc_config
+
+
+class PerformLoginMixin:
+ app: DjangoTestApp
+ extra_environ: dict
+
+ def _login_and_start_form(self, plugin: str, *, username: str, password: str):
+ host = f"http://{self.extra_environ['HTTP_HOST']}"
+ form = FormFactory.create(authentication_backends=[plugin])
+ url_helper = URLsHelper(form=form, host=host)
+ start_url = url_helper.get_auth_start(plugin_id=plugin)
+ start_response = self.app.get(start_url)
+ # simulate login to Keycloak
+ redirect_uri = keycloak_login(
+ start_response["Location"],
+ username=username,
+ password=password,
+ host=host,
+ )
+ # complete the login flow on our end
+ callback_response = self.app.get(redirect_uri, auto_follow=True)
+ assert callback_response.status_code == 200
+ # start submission
+ create_response = self.app.post_json(
+ reverse("api:submission-list"),
+ {
+ "form": url_helper.api_resource,
+ "formUrl": url_helper.frontend_start,
+ },
+ )
+ assert create_response.status_code == 201
+
+
+@override_settings(ALLOWED_HOSTS=["*"])
+class EmployeeAuthContextTests(PerformLoginMixin, IntegrationTestsBase):
+ csrf_checks = False
+ extra_environ = {
+ "HTTP_HOST": "localhost:8000",
+ }
+
+ @mock_org_oidc_config()
+ def test_record_auth_context_employee(self):
+ self._login_and_start_form("org-oidc", username="admin", password="admin")
+
+ submission = Submission.objects.get()
+ self.assertTrue(submission.is_authenticated)
+ auth_context = submission.auth_info.to_auth_context_data()
+
+ self.assertEqual(auth_context["source"], "custom")
+ self.assertEqual(auth_context["levelOfAssurance"], "unknown")
+ self.assertEqual(
+ auth_context["authorizee"]["legalSubject"],
+ {
+ "identifierType": "opaque",
+ "identifier": "admin",
+ },
+ )
diff --git a/src/openforms/authentication/models.py b/src/openforms/authentication/models.py
index 01caec5270..7e601c419c 100644
--- a/src/openforms/authentication/models.py
+++ b/src/openforms/authentication/models.py
@@ -20,6 +20,7 @@
DigiDMachtigenContext,
EHerkenningContext,
EHerkenningMachtigenContext,
+ EmployeeContext,
)
logger = logging.getLogger(__name__)
@@ -264,6 +265,7 @@ def to_auth_context_data(
| DigiDMachtigenContext
| EHerkenningContext
| EHerkenningMachtigenContext
+ | EmployeeContext
):
if self.attribute_hashed:
logger.debug(
@@ -357,6 +359,25 @@ def to_auth_context_data(
"branchNumber"
] = branch_number
return ehm_context
+
+ # Employee login
+ # ---
+ # Experimental feature that is different from the defined authentication context.
+ # This will have to be re-worked and re-thought-out, and will most definitely change.
+ # This fixes the issue of #4863
+ case (AuthAttribute.employee_id, ""):
+ employee_context: EmployeeContext = {
+ "source": "custom",
+ "levelOfAssurance": "unknown",
+ "authorizee": {
+ "legalSubject": {
+ "identifierType": "opaque",
+ "identifier": self.value,
+ }
+ },
+ }
+ return employee_context
+
case _: # pragma: no cover
raise RuntimeError(f"Unknown attribute: {self.attribute}")
diff --git a/src/openforms/authentication/types.py b/src/openforms/authentication/types.py
index 4057a2667e..bd3e7a3e32 100644
--- a/src/openforms/authentication/types.py
+++ b/src/openforms/authentication/types.py
@@ -82,3 +82,19 @@ class EHMandate(TypedDict):
class EHerkenningMachtigenContext(EHerkenningContext):
representee: EHRepresenteeEntity
mandate: EHMandate
+
+
+class EmployeeLegalSubject(TypedDict):
+ identifierType: Literal["opaque"]
+ identifier: str
+
+
+class EmployeeAuthorizee(TypedDict):
+ legalSubject: EmployeeLegalSubject
+
+
+# This type definition is highly experimental, and will most definitely change
+class EmployeeContext(TypedDict):
+ source: Literal["custom"]
+ levelOfAssurance: Literal["unknown"]
+ authorizee: EmployeeAuthorizee