@cratis/arc 22.45.0 → 22.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/dist/cjs/identity/IdentityProvider.d.ts +11 -2
  2. package/dist/cjs/identity/IdentityProvider.d.ts.map +1 -1
  3. package/dist/cjs/identity/IdentityProvider.js +118 -44
  4. package/dist/cjs/identity/IdentityProvider.js.map +1 -1
  5. package/dist/cjs/identity/deserializeIdentityDetails.d.ts.map +1 -1
  6. package/dist/cjs/identity/deserializeIdentityDetails.js +1 -2
  7. package/dist/cjs/identity/deserializeIdentityDetails.js.map +1 -1
  8. package/dist/esm/identity/IdentityProvider.d.ts +11 -2
  9. package/dist/esm/identity/IdentityProvider.d.ts.map +1 -1
  10. package/dist/esm/identity/IdentityProvider.js +118 -44
  11. package/dist/esm/identity/IdentityProvider.js.map +1 -1
  12. package/dist/esm/identity/deserializeIdentityDetails.d.ts.map +1 -1
  13. package/dist/esm/identity/deserializeIdentityDetails.js +1 -2
  14. package/dist/esm/identity/deserializeIdentityDetails.js.map +1 -1
  15. package/dist/esm/identity/for_IdentityProvider/given/a_browser_with_a_legacy_identity.d.ts +11 -0
  16. package/dist/esm/identity/for_IdentityProvider/given/a_browser_with_a_legacy_identity.d.ts.map +1 -0
  17. package/dist/esm/identity/for_IdentityProvider/given/a_browser_with_a_legacy_identity.js +42 -0
  18. package/dist/esm/identity/for_IdentityProvider/given/a_browser_with_a_legacy_identity.js.map +1 -0
  19. package/dist/esm/identity/for_IdentityProvider/given/a_cookie_first_backend.d.ts +7 -0
  20. package/dist/esm/identity/for_IdentityProvider/given/a_cookie_first_backend.d.ts.map +1 -0
  21. package/dist/esm/identity/for_IdentityProvider/given/a_cookie_first_backend.js +19 -0
  22. package/dist/esm/identity/for_IdentityProvider/given/a_cookie_first_backend.js.map +1 -0
  23. package/dist/esm/identity/for_IdentityProvider/given/a_secure_browser_with_a_legacy_identity.d.ts +5 -0
  24. package/dist/esm/identity/for_IdentityProvider/given/a_secure_browser_with_a_legacy_identity.d.ts.map +1 -0
  25. package/dist/esm/identity/for_IdentityProvider/given/a_secure_browser_with_a_legacy_identity.js +5 -0
  26. package/dist/esm/identity/for_IdentityProvider/given/a_secure_browser_with_a_legacy_identity.js.map +1 -0
  27. package/dist/esm/identity/for_IdentityProvider/given/an_identity_provider.d.ts +1 -0
  28. package/dist/esm/identity/for_IdentityProvider/given/an_identity_provider.d.ts.map +1 -1
  29. package/dist/esm/identity/for_IdentityProvider/given/an_identity_provider.js +11 -0
  30. package/dist/esm/identity/for_IdentityProvider/given/an_identity_provider.js.map +1 -1
  31. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache/after_a_legacy_refresh.d.ts +2 -0
  32. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache/after_a_legacy_refresh.d.ts.map +1 -0
  33. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache/after_a_legacy_refresh.js +15 -0
  34. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache/after_a_legacy_refresh.js.map +1 -0
  35. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache.d.ts +2 -0
  36. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache.d.ts.map +1 -0
  37. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache.js +17 -0
  38. package/dist/esm/identity/for_IdentityProvider/when_clearing_cache.js.map +1 -0
  39. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_reloading_a_legacy_refresh.d.ts +2 -0
  40. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_reloading_a_legacy_refresh.d.ts.map +1 -0
  41. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_reloading_a_legacy_refresh.js +18 -0
  42. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_reloading_a_legacy_refresh.js.map +1 -0
  43. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_the_server_did_not_resolve_an_identity.d.ts +2 -0
  44. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_the_server_did_not_resolve_an_identity.d.ts.map +1 -0
  45. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_the_server_did_not_resolve_an_identity.js +20 -0
  46. package/dist/esm/identity/for_IdentityProvider/when_getting_current/after_the_server_did_not_resolve_an_identity.js.map +1 -0
  47. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_has_no_identity_endpoint.d.ts +2 -0
  48. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_has_no_identity_endpoint.d.ts.map +1 -0
  49. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_has_no_identity_endpoint.js +24 -0
  50. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_has_no_identity_endpoint.js.map +1 -0
  51. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_rejects_the_caller_with_a_forged_identity_cookie.d.ts +2 -0
  52. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_rejects_the_caller_with_a_forged_identity_cookie.d.ts.map +1 -0
  53. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_rejects_the_caller_with_a_forged_identity_cookie.js +16 -0
  54. package/dist/esm/identity/for_IdentityProvider/when_getting_current/and_the_server_rejects_the_caller_with_a_forged_identity_cookie.js.map +1 -0
  55. package/dist/esm/identity/for_IdentityProvider/when_getting_current/twice.d.ts +2 -0
  56. package/dist/esm/identity/for_IdentityProvider/when_getting_current/twice.d.ts.map +1 -0
  57. package/dist/esm/identity/for_IdentityProvider/when_getting_current/twice.js +15 -0
  58. package/dist/esm/identity/for_IdentityProvider/when_getting_current/twice.js.map +1 -0
  59. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_a_details_type_that_declares_no_fields.js +2 -3
  60. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_a_details_type_that_declares_no_fields.js.map +1 -1
  61. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_a_forged_identity_cookie.d.ts +2 -0
  62. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_a_forged_identity_cookie.d.ts.map +1 -0
  63. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_a_forged_identity_cookie.js +18 -0
  64. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_a_forged_identity_cookie.js.map +1 -0
  65. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_roles.js +2 -3
  66. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_roles.js.map +1 -1
  67. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_type_safe_details.js +2 -3
  68. package/dist/esm/identity/for_IdentityProvider/when_getting_current/with_type_safe_details.js.map +1 -1
  69. package/dist/esm/identity/for_IdentityProvider/when_getting_current/without_roles.js +2 -3
  70. package/dist/esm/identity/for_IdentityProvider/when_getting_current/without_roles.js.map +1 -1
  71. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_getting_current.d.ts +2 -0
  72. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_getting_current.d.ts.map +1 -0
  73. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_getting_current.js +18 -0
  74. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_getting_current.js.map +1 -0
  75. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_the_server_rejects_a_retained_transition_identity.d.ts +2 -0
  76. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_the_server_rejects_a_retained_transition_identity.d.ts.map +1 -0
  77. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_the_server_rejects_a_retained_transition_identity.js +17 -0
  78. package/dist/esm/identity/for_IdentityProvider/when_refreshing/after_the_server_rejects_a_retained_transition_identity.js.map +1 -0
  79. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_the_server_has_no_identity_endpoint.d.ts +2 -0
  80. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_the_server_has_no_identity_endpoint.d.ts.map +1 -0
  81. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_the_server_has_no_identity_endpoint.js +13 -0
  82. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_the_server_has_no_identity_endpoint.js.map +1 -0
  83. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_there_is_no_identity_endpoint_on_consecutive_requests.d.ts +2 -0
  84. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_there_is_no_identity_endpoint_on_consecutive_requests.d.ts.map +1 -0
  85. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_there_is_no_identity_endpoint_on_consecutive_requests.js +17 -0
  86. package/dist/esm/identity/for_IdentityProvider/when_refreshing/and_there_is_no_identity_endpoint_on_consecutive_requests.js.map +1 -0
  87. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_changed_credentials.d.ts +2 -0
  88. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_changed_credentials.d.ts.map +1 -0
  89. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_changed_credentials.js +21 -0
  90. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_changed_credentials.js.map +1 -0
  91. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_expired_credentials.d.ts +2 -0
  92. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_expired_credentials.d.ts.map +1 -0
  93. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_expired_credentials.js +16 -0
  94. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_expired_credentials.js.map +1 -0
  95. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_new_cookie_on_the_not_found_response.d.ts +2 -0
  96. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_new_cookie_on_the_not_found_response.d.ts.map +1 -0
  97. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_new_cookie_on_the_not_found_response.js +17 -0
  98. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_new_cookie_on_the_not_found_response.js.map +1 -0
  99. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_secure_legacy_cookie_and_no_identity_endpoint.d.ts +2 -0
  100. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_secure_legacy_cookie_and_no_identity_endpoint.d.ts.map +1 -0
  101. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_secure_legacy_cookie_and_no_identity_endpoint.js +15 -0
  102. package/dist/esm/identity/for_IdentityProvider/when_refreshing/with_a_secure_legacy_cookie_and_no_identity_endpoint.js.map +1 -0
  103. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  104. package/identity/IdentityProvider.ts +137 -43
  105. package/identity/deserializeIdentityDetails.ts +1 -2
  106. package/identity/for_IdentityProvider/given/a_browser_with_a_legacy_identity.ts +46 -0
  107. package/identity/for_IdentityProvider/given/a_cookie_first_backend.ts +25 -0
  108. package/identity/for_IdentityProvider/given/a_secure_browser_with_a_legacy_identity.ts +8 -0
  109. package/identity/for_IdentityProvider/given/an_identity_provider.ts +19 -0
  110. package/identity/for_IdentityProvider/when_clearing_cache/after_a_legacy_refresh.ts +21 -0
  111. package/identity/for_IdentityProvider/when_clearing_cache.ts +24 -0
  112. package/identity/for_IdentityProvider/when_getting_current/after_reloading_a_legacy_refresh.ts +24 -0
  113. package/identity/for_IdentityProvider/when_getting_current/after_the_server_did_not_resolve_an_identity.ts +31 -0
  114. package/identity/for_IdentityProvider/when_getting_current/and_the_server_has_no_identity_endpoint.ts +38 -0
  115. package/identity/for_IdentityProvider/when_getting_current/and_the_server_rejects_the_caller_with_a_forged_identity_cookie.ts +23 -0
  116. package/identity/for_IdentityProvider/when_getting_current/twice.ts +22 -0
  117. package/identity/for_IdentityProvider/when_getting_current/with_a_details_type_that_declares_no_fields.ts +2 -3
  118. package/identity/for_IdentityProvider/when_getting_current/with_a_forged_identity_cookie.ts +29 -0
  119. package/identity/for_IdentityProvider/when_getting_current/with_roles.ts +2 -3
  120. package/identity/for_IdentityProvider/when_getting_current/with_type_safe_details.ts +2 -4
  121. package/identity/for_IdentityProvider/when_getting_current/without_roles.ts +2 -3
  122. package/identity/for_IdentityProvider/when_refreshing/after_getting_current.ts +25 -0
  123. package/identity/for_IdentityProvider/when_refreshing/after_the_server_rejects_a_retained_transition_identity.ts +23 -0
  124. package/identity/for_IdentityProvider/when_refreshing/and_the_server_has_no_identity_endpoint.ts +19 -0
  125. package/identity/for_IdentityProvider/when_refreshing/and_there_is_no_identity_endpoint_on_consecutive_requests.ts +24 -0
  126. package/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_changed_credentials.ts +27 -0
  127. package/identity/for_IdentityProvider/when_refreshing/with_a_cookie_first_backend_and_expired_credentials.ts +22 -0
  128. package/identity/for_IdentityProvider/when_refreshing/with_a_new_cookie_on_the_not_found_response.ts +23 -0
  129. package/identity/for_IdentityProvider/when_refreshing/with_a_secure_legacy_cookie_and_no_identity_endpoint.ts +21 -0
  130. package/package.json +1 -1
@@ -5,7 +5,7 @@ import { IdentityProvider } from '../../IdentityProvider.js';
5
5
  import { an_identity_provider } from '../given/an_identity_provider.js';
6
6
  import { given } from '../../../given.js';
7
7
 
8
- describe('when getting current without roles', given(an_identity_provider, () => {
8
+ describe('when getting current without roles', given(an_identity_provider, context => {
9
9
  let identity: { id: string; name: string; roles: string[]; isInRole: (role: string) => boolean };
10
10
 
11
11
  beforeEach(async () => {
@@ -14,8 +14,7 @@ describe('when getting current without roles', given(an_identity_provider, () =>
14
14
  name: 'Test User',
15
15
  details: {}
16
16
  };
17
- const encodedData = btoa(JSON.stringify(identityData));
18
- (global as { document?: { cookie: string } }).document!.cookie = `.cratis-identity=${encodedData}`;
17
+ context.serverReports(identityData);
19
18
 
20
19
  const result = await IdentityProvider.getCurrent();
21
20
  identity = {
@@ -0,0 +1,25 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { IdentityProvider } from '../../IdentityProvider.js';
5
+ import { IIdentity } from '../../IIdentity.js';
6
+ import { an_identity_provider } from '../given/an_identity_provider.js';
7
+ import { given } from '../../../given.js';
8
+
9
+ describe('when refreshing after getting current', given(an_identity_provider, context => {
10
+ let refreshed: IIdentity;
11
+ let current: IIdentity;
12
+
13
+ beforeEach(async () => {
14
+ context.serverReports({ id: 'user-123', name: 'Test User', roles: [], details: {} });
15
+ await IdentityProvider.getCurrent();
16
+
17
+ context.serverReports({ id: 'user-123', name: 'Renamed User', roles: [], details: {} });
18
+ refreshed = await IdentityProvider.refresh();
19
+ current = await IdentityProvider.getCurrent();
20
+ });
21
+
22
+ it('should ask the server again', () => context.fetchStub.calledTwice.should.be.true);
23
+ it('should report what the server reports now', () => refreshed.name.should.equal('Renamed User'));
24
+ it('should keep the refreshed identity for the next caller', () => current.name.should.equal('Renamed User'));
25
+ }));
@@ -0,0 +1,23 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { IdentityProvider } from '../../IdentityProvider.js';
5
+ import { IIdentity } from '../../IIdentity.js';
6
+ import { a_browser_with_a_legacy_identity } from '../given/a_browser_with_a_legacy_identity.js';
7
+ import { given } from '../../../given.js';
8
+
9
+ describe('when refreshing after the server rejects a retained transition identity', given(a_browser_with_a_legacy_identity, context => {
10
+ let rejected: IIdentity;
11
+ let refreshed: IIdentity;
12
+
13
+ beforeEach(async () => {
14
+ await IdentityProvider.refresh();
15
+ context.fetchStub.resolves({ ok: false, status: 401 } as Response);
16
+ rejected = await IdentityProvider.refresh();
17
+ context.fetchStub.resolves({ ok: false, status: 404 } as Response);
18
+ refreshed = await IdentityProvider.refresh();
19
+ });
20
+
21
+ it('should not overrule the rejection with the retained identity', () => rejected.isSet.should.be.false);
22
+ it('should discard the transition identity after the rejection', () => refreshed.isSet.should.be.false);
23
+ }));
@@ -0,0 +1,19 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { IdentityProvider } from '../../IdentityProvider.js';
5
+ import { IIdentity } from '../../IIdentity.js';
6
+ import { a_browser_with_a_legacy_identity } from '../given/a_browser_with_a_legacy_identity.js';
7
+ import { given } from '../../../given.js';
8
+
9
+ describe('when refreshing and the server has no identity endpoint', given(a_browser_with_a_legacy_identity, context => {
10
+ let refreshed: IIdentity;
11
+
12
+ beforeEach(async () => {
13
+ refreshed = await IdentityProvider.refresh();
14
+ });
15
+
16
+ it('should ask the server first', () => context.fetchStub.calledOnce.should.be.true);
17
+ it('should preserve the transition fallback', () => refreshed.id.should.equal('user-123'));
18
+ it('should preserve the roles from the fallback', () => refreshed.isInRole('Reader').should.be.true);
19
+ }));
@@ -0,0 +1,24 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { IdentityProvider } from '../../IdentityProvider.js';
5
+ import { IIdentity } from '../../IIdentity.js';
6
+ import { a_browser_with_a_legacy_identity } from '../given/a_browser_with_a_legacy_identity.js';
7
+ import { given } from '../../../given.js';
8
+
9
+ // The proxy may authorize from its own cache without reissuing its readable cookie.
10
+ describe('when refreshing consecutively without an identity endpoint', given(a_browser_with_a_legacy_identity, context => {
11
+ let refreshed: IIdentity;
12
+
13
+ beforeEach(async () => {
14
+ await IdentityProvider.refresh();
15
+ refreshed = await IdentityProvider.refresh();
16
+ });
17
+
18
+ it('should ask the server for each refresh', () => context.fetchStub.calledTwice.should.be.true);
19
+ it('should retain the transition identity', () => refreshed.id.should.equal('user-123'));
20
+ it('should retain the transition roles', () => refreshed.isInRole('Reader').should.be.true);
21
+ it('should restore the root cookie for navigation', () => document.cookie.should.contain('.cratis-identity='));
22
+ it('should retain SameSite Lax on HTTP', () => context.cookieJar.getCookiesSync('http://localhost/')[0].sameSite!.should.equal('lax'));
23
+ it('should not require HTTPS on an HTTP site', () => context.cookieJar.getCookiesSync('http://localhost/')[0].secure.should.be.false);
24
+ }));
@@ -0,0 +1,27 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { IdentityProvider } from '../../IdentityProvider.js';
5
+ import { IIdentity } from '../../IIdentity.js';
6
+ import { a_cookie_first_backend } from '../given/a_cookie_first_backend.js';
7
+ import { given } from '../../../given.js';
8
+
9
+ describe('when refreshing with a cookie-first backend and changed credentials', given(a_cookie_first_backend, context => {
10
+ let refreshed: IIdentity;
11
+ let current: IIdentity;
12
+
13
+ beforeEach(async () => {
14
+ await IdentityProvider.getCurrent();
15
+ context.currentIdentity = { id: 'user-456', name: 'Current User', roles: ['Editor'], details: { department: 'Current' } };
16
+ refreshed = await IdentityProvider.refresh();
17
+ current = await IdentityProvider.getCurrent();
18
+ });
19
+
20
+ it('should ask the backend again', () => context.fetchStub.calledTwice.should.be.true);
21
+ it('should report the current principal', () => refreshed.id.should.equal('user-456'));
22
+ it('should report the current name', () => refreshed.name.should.equal('Current User'));
23
+ it('should report the current roles', () => refreshed.roles.should.deep.equal(['Editor']));
24
+ it('should report the recomputed details', () => refreshed.details.should.deep.equal({ department: 'Current' }));
25
+ it('should cache the refreshed identity', () => current.id.should.equal('user-456'));
26
+ it('should expire the legacy cookie at the root path', () => document.cookie.should.equal('.cratis-identity=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/'));
27
+ }));
@@ -0,0 +1,22 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { IdentityProvider } from '../../IdentityProvider.js';
5
+ import { IIdentity } from '../../IIdentity.js';
6
+ import { a_cookie_first_backend } from '../given/a_cookie_first_backend.js';
7
+ import { given } from '../../../given.js';
8
+
9
+ describe('when refreshing with a cookie-first backend and expired credentials', given(a_cookie_first_backend, context => {
10
+ let refreshed: IIdentity;
11
+
12
+ beforeEach(async () => {
13
+ await IdentityProvider.getCurrent();
14
+ context.currentIdentity = undefined;
15
+ refreshed = await IdentityProvider.refresh();
16
+ });
17
+
18
+ it('should ask the backend again', () => context.fetchStub.calledTwice.should.be.true);
19
+ it('should report that the identity is no longer set', () => refreshed.isSet.should.be.false);
20
+ it('should not keep the previous principal', () => refreshed.id.should.equal(''));
21
+ it('should not keep the previous roles', () => refreshed.roles.should.be.empty);
22
+ }));
@@ -0,0 +1,23 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { IdentityProvider } from '../../IdentityProvider.js';
5
+ import { IIdentity } from '../../IIdentity.js';
6
+ import { a_browser_with_a_legacy_identity } from '../given/a_browser_with_a_legacy_identity.js';
7
+ import { given } from '../../../given.js';
8
+
9
+ describe('when refreshing with a new cookie on the not found response', given(a_browser_with_a_legacy_identity, context => {
10
+ let refreshed: IIdentity;
11
+
12
+ beforeEach(async () => {
13
+ context.fetchStub.callsFake(async () => {
14
+ document.cookie = `.cratis-identity=${btoa(JSON.stringify({ id: 'user-456', name: 'Updated User', roles: ['Writer'], details: {} }))};path=/`;
15
+ return { ok: false, status: 404 } as Response;
16
+ });
17
+ refreshed = await IdentityProvider.refresh();
18
+ });
19
+
20
+ it('should prefer the identity issued by the response', () => refreshed.id.should.equal('user-456'));
21
+ it('should use the updated roles', () => refreshed.isInRole('Writer').should.be.true);
22
+ it('should not retain the earlier roles', () => refreshed.isInRole('Reader').should.be.false);
23
+ }));
@@ -0,0 +1,21 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import { IdentityProvider } from '../../IdentityProvider.js';
5
+ import { IIdentity } from '../../IIdentity.js';
6
+ import { a_secure_browser_with_a_legacy_identity } from '../given/a_secure_browser_with_a_legacy_identity.js';
7
+ import { given } from '../../../given.js';
8
+
9
+ describe('when refreshing a secure legacy cookie without an identity endpoint', given(a_secure_browser_with_a_legacy_identity, context => {
10
+ let refreshed: IIdentity;
11
+
12
+ beforeEach(async () => {
13
+ await IdentityProvider.refresh();
14
+ refreshed = await IdentityProvider.refresh();
15
+ });
16
+
17
+ it('should retain the transition identity', () => refreshed.id.should.equal('user-123'));
18
+ it('should restore the cookie for HTTPS navigation', () => context.cookieJar.getCookieStringSync('https://identity.example/').should.contain('.cratis-identity='));
19
+ it('should not send the restored cookie over HTTP', () => context.cookieJar.getCookieStringSync('http://identity.example/').should.equal(''));
20
+ it('should retain SameSite Lax', () => context.cookieJar.getCookiesSync('https://identity.example/')[0].sameSite!.should.equal('lax'));
21
+ }));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@cratis/arc",
4
- "version": "22.45.0",
4
+ "version": "22.47.0",
5
5
  "description": "TypeScript command, query, validation, identity, and messaging runtime for Cratis Arc — the CQRS application framework for ASP.NET Core — used by generated proxies.",
6
6
  "keywords": [
7
7
  "cratis",