@icure/api 7.1.25 → 7.1.27

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.
@@ -15,4 +15,5 @@ export declare class OperationToken {
15
15
  creationTime?: number;
16
16
  validity?: number;
17
17
  operation?: string;
18
+ description?: string;
18
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"OperationToken.js","sourceRoot":"","sources":["../../../icc-api/model/OperationToken.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAEH,MAAa,cAAc;IACzB,YAAY,IAAgB;QAC1B,MAAM,CAAC,MAAM,CAAC,IAAsB,EAAE,IAAI,CAAC,CAAA;IAC7C,CAAC;CAMF;AATD,wCASC","sourcesContent":["/**\n * iCure Data Stack API Documentation\n * The iCure Data Stack Application API is the native interface to iCure. This version is obsolete, please use v2.\n *\n * OpenAPI spec version: v1\n *\n *\n * NOTE: This class is auto generated by the swagger code generator program.\n * https://github.com/swagger-api/swagger-codegen.git\n * Do not edit the class manually.\n */\n\nexport class OperationToken {\n constructor(json: JSON | any) {\n Object.assign(this as OperationToken, json)\n }\n\n tokenHash?: string\n creationTime?: number\n validity?: number\n operation?: string\n}\n"]}
1
+ {"version":3,"file":"OperationToken.js","sourceRoot":"","sources":["../../../icc-api/model/OperationToken.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;AAEH,MAAa,cAAc;IACzB,YAAY,IAAgB;QAC1B,MAAM,CAAC,MAAM,CAAC,IAAsB,EAAE,IAAI,CAAC,CAAA;IAC7C,CAAC;CAOF;AAVD,wCAUC","sourcesContent":["/**\n * iCure Data Stack API Documentation\n * The iCure Data Stack Application API is the native interface to iCure. This version is obsolete, please use v2.\n *\n * OpenAPI spec version: v1\n *\n *\n * NOTE: This class is auto generated by the swagger code generator program.\n * https://github.com/swagger-api/swagger-codegen.git\n * Do not edit the class manually.\n */\n\nexport class OperationToken {\n constructor(json: JSON | any) {\n Object.assign(this as OperationToken, json)\n }\n\n tokenHash?: string\n creationTime?: number\n validity?: number\n operation?: string\n description?: string\n}\n"]}
@@ -19,9 +19,17 @@ export interface AuthenticationProvider {
19
19
  * @param matches the list of groups the user is in, containing also the group-specific id of the user. Note that users with same login username but
20
20
  * different password are considered as if they are different users and should not appear in these matches. You can get this list by calling
21
21
  * {@link IccUserApi.getMatchingUsers} authenticated.
22
- * @return a new authentication provider
22
+ * @return an object containing:
23
+ * - `switchedProvider`: a new authentication provider, which can be used to perform requests as the user in the new group
24
+ * - `isGroupLocked`: true if the returned authentication provider is "locked" within new group, depends on the implementation of
25
+ * AuthenticationProvider used. This means that using this provider when performing a request to get the list of groups the user is in may return
26
+ * under certain circumstances only the new group, even though the original provider was able to return multiple groups. Even if true you can
27
+ * still switch to another group, but you will have to use another authentication provider to get the matches.
23
28
  */
24
- switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<AuthenticationProvider>;
29
+ switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<{
30
+ switchedProvider: AuthenticationProvider;
31
+ isGroupLocked: boolean;
32
+ }>;
25
33
  getIcureTokens(): Promise<{
26
34
  token: string;
27
35
  refreshToken: string;
@@ -43,7 +51,10 @@ export declare class EnsembleAuthenticationProvider implements AuthenticationPro
43
51
  refreshToken: string;
44
52
  } | undefined>;
45
53
  getAuthService(): AuthService;
46
- switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<AuthenticationProvider>;
54
+ switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<{
55
+ switchedProvider: AuthenticationProvider;
56
+ isGroupLocked: boolean;
57
+ }>;
47
58
  }
48
59
  export declare class JwtAuthenticationProvider implements AuthenticationProvider {
49
60
  private readonly authApi;
@@ -68,7 +79,10 @@ export declare class JwtAuthenticationProvider implements AuthenticationProvider
68
79
  refreshToken: string;
69
80
  } | undefined);
70
81
  getAuthService(): AuthService;
71
- switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<AuthenticationProvider>;
82
+ switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<{
83
+ switchedProvider: AuthenticationProvider;
84
+ isGroupLocked: boolean;
85
+ }>;
72
86
  }
73
87
  export declare class BasicAuthenticationProvider implements AuthenticationProvider {
74
88
  private username;
@@ -79,7 +93,10 @@ export declare class BasicAuthenticationProvider implements AuthenticationProvid
79
93
  } | undefined>;
80
94
  constructor(username: string, password: string);
81
95
  getAuthService(): AuthService;
82
- switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<AuthenticationProvider>;
96
+ switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<{
97
+ switchedProvider: AuthenticationProvider;
98
+ isGroupLocked: boolean;
99
+ }>;
83
100
  }
84
101
  export declare class NoAuthenticationProvider implements AuthenticationProvider {
85
102
  getAuthService(): AuthService;
@@ -87,5 +104,8 @@ export declare class NoAuthenticationProvider implements AuthenticationProvider
87
104
  token: string;
88
105
  refreshToken: string;
89
106
  } | undefined>;
90
- switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<AuthenticationProvider>;
107
+ switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<{
108
+ switchedProvider: AuthenticationProvider;
109
+ isGroupLocked: boolean;
110
+ }>;
91
111
  }
@@ -42,7 +42,10 @@ class EnsembleAuthenticationProvider {
42
42
  switchGroup(newGroupId, matches) {
43
43
  return __awaiter(this, void 0, void 0, function* () {
44
44
  const switchInfo = yield switchJwtAuth(this.authApi, this.jwtAuth, this.username, this.password, newGroupId, matches);
45
- return new EnsembleAuthenticationProvider(this.authApi, switchInfo.loginForGroup, this.password, this.jwtTimeout, switchInfo.switchedJwtAuth, new BasicAuthService_1.BasicAuthService(switchInfo.loginForGroup, this.password));
45
+ return {
46
+ switchedProvider: new EnsembleAuthenticationProvider(this.authApi, switchInfo.loginForGroup, this.password, this.jwtTimeout, switchInfo.switchedJwtAuth, new BasicAuthService_1.BasicAuthService(switchInfo.loginForGroup, this.password)),
47
+ isGroupLocked: true,
48
+ };
46
49
  });
47
50
  }
48
51
  }
@@ -80,7 +83,10 @@ class JwtAuthenticationProvider {
80
83
  switchGroup(newGroupId, matches) {
81
84
  return __awaiter(this, void 0, void 0, function* () {
82
85
  const switchInfo = yield switchJwtAuth(this.authApi, this.jwtAuth, this.username, this.password, newGroupId, matches);
83
- return new JwtAuthenticationProvider(this.authApi, switchInfo.loginForGroup, this.password, switchInfo.switchedJwtAuth);
86
+ return {
87
+ switchedProvider: new JwtAuthenticationProvider(this.authApi, switchInfo.loginForGroup, this.password, switchInfo.switchedJwtAuth),
88
+ isGroupLocked: true,
89
+ };
84
90
  });
85
91
  }
86
92
  }
@@ -98,7 +104,10 @@ class BasicAuthenticationProvider {
98
104
  }
99
105
  switchGroup(newGroupId, matches) {
100
106
  return __awaiter(this, void 0, void 0, function* () {
101
- return Promise.resolve(new BasicAuthenticationProvider(loginForGroup(newGroupId, matches), this.password));
107
+ return {
108
+ switchedProvider: new BasicAuthenticationProvider(loginForGroup(newGroupId, matches), this.password),
109
+ isGroupLocked: true,
110
+ };
102
111
  });
103
112
  }
104
113
  }
@@ -112,7 +121,7 @@ class NoAuthenticationProvider {
112
121
  }
113
122
  switchGroup(newGroupId, matches) {
114
123
  return __awaiter(this, void 0, void 0, function* () {
115
- return Promise.resolve(new NoAuthenticationProvider());
124
+ return { switchedProvider: this, isGroupLocked: false };
116
125
  });
117
126
  }
118
127
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AuthenticationProvider.js","sourceRoot":"","sources":["../../../icc-x-api/auth/AuthenticationProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthService } from './AuthService'\nimport { IccAuthApi } from '../../icc-api'\nimport { EnsembleAuthService } from './EnsembleAuthService'\nimport { JwtBridgedAuthService } from './JwtBridgedAuthService'\nimport { NoAuthService } from './NoAuthService'\nimport { BasicAuthService } from './BasicAuthService'\nimport { JwtAuthService } from './JwtAuthService'\nimport { UserGroup } from '../../icc-api/model/UserGroup'\n\n/**\n * @internal you should not implement this interface yourself.\n */\nexport interface AuthenticationProvider {\n /**\n * @internal this method is meant for internal use only and may be changed without notice\n */\n getAuthService(): AuthService\n\n /**\n * @internal this method is meant for internal use only and may be changed without notice\n * Gives a new authentication provider for the same user and authentication method but for a different iCure group\n * @param newGroupId id of the new group to switch to\n * @param matches the list of groups the user is in, containing also the group-specific id of the user. Note that users with same login username but\n * different password are considered as if they are different users and should not appear in these matches. You can get this list by calling\n * {@link IccUserApi.getMatchingUsers} authenticated.\n * @return a new authentication provider\n */\n switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<AuthenticationProvider>\n\n getIcureTokens(): Promise<{ token: string; refreshToken: string } | undefined>\n}\n\nexport class EnsembleAuthenticationProvider implements AuthenticationProvider {\n private readonly basicAuth: BasicAuthService\n private jwtAuth: JwtAuthService | JwtBridgedAuthService\n private suspensionEnd: Date | undefined\n\n constructor(\n private readonly authApi: IccAuthApi,\n private readonly username: string,\n private readonly password: string,\n private readonly jwtTimeout: number = 3600,\n jwtAuth?: JwtAuthService | JwtBridgedAuthService,\n basicAuth?: BasicAuthService,\n thirdPartyTokens: { [thirdParty: string]: string } = {}\n ) {\n this.jwtAuth = jwtAuth ?? new JwtBridgedAuthService(this.authApi, this.username, this.password, thirdPartyTokens)\n this.basicAuth = basicAuth ?? new BasicAuthService(this.username, this.password)\n }\n\n getIcureTokens(): Promise<{ token: string; refreshToken: string } | undefined> {\n return this.jwtAuth.getIcureTokens()\n }\n\n getAuthService(): AuthService {\n // If the jwtAuth is in an error state, it instantiates a new one,\n // but it will not use it until the suspension ends\n if (this.jwtAuth.isInErrorState()) {\n console.warn('Error state in JWT, I will skip it')\n this.jwtAuth = new JwtBridgedAuthService(this.authApi, this.username, this.password)\n this.suspensionEnd = new Date(new Date().getTime() + this.jwtTimeout * 1000)\n }\n\n return !!this.suspensionEnd && new Date() <= this.suspensionEnd\n ? new EnsembleAuthService(null, new NoAuthService(), this.basicAuth)\n : new EnsembleAuthService(this.jwtAuth, new NoAuthService(), this.basicAuth)\n }\n\n async switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<AuthenticationProvider> {\n const switchInfo = await switchJwtAuth(this.authApi, this.jwtAuth, this.username, this.password, newGroupId, matches)\n return new EnsembleAuthenticationProvider(\n this.authApi,\n switchInfo.loginForGroup,\n this.password,\n this.jwtTimeout,\n switchInfo.switchedJwtAuth,\n new BasicAuthService(switchInfo.loginForGroup, this.password)\n )\n }\n}\n\nexport class JwtAuthenticationProvider implements AuthenticationProvider {\n getIcureTokens(): Promise<{ token: string; refreshToken: string } | undefined> {\n return this.jwtAuth.getIcureTokens()\n }\n\n private readonly jwtAuth: JwtAuthService | JwtBridgedAuthService\n\n /**\n * @internal\n * @param authApi\n * @param username\n * @param password\n * @param jwtAuth\n * @param icureToken\n */\n constructor(\n private readonly authApi: IccAuthApi,\n private readonly username?: string,\n private readonly password?: string,\n jwtAuth?: JwtAuthService | JwtBridgedAuthService,\n private readonly icureToken?: { token: string; refreshToken: string }\n ) {\n const composedAuth =\n jwtAuth ??\n (icureToken\n ? new JwtAuthService(authApi, { authJwt: icureToken.token, refreshJwt: icureToken.refreshToken })\n : !!username && !!password\n ? new JwtBridgedAuthService(authApi, username!, password!)\n : undefined)\n if (!composedAuth) {\n throw new Error('No authentication method provided')\n }\n this.jwtAuth = composedAuth\n }\n\n getAuthService(): AuthService {\n return this.jwtAuth\n }\n\n async switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<AuthenticationProvider> {\n const switchInfo = await switchJwtAuth(this.authApi, this.jwtAuth, this.username, this.password, newGroupId, matches)\n return new JwtAuthenticationProvider(this.authApi, switchInfo.loginForGroup, this.password, switchInfo.switchedJwtAuth)\n }\n}\n\nexport class BasicAuthenticationProvider implements AuthenticationProvider {\n getIcureTokens(): Promise<{ token: string; refreshToken: string } | undefined> {\n return Promise.resolve() as Promise<undefined>\n }\n\n constructor(private username: string, private password: string) {}\n\n getAuthService(): AuthService {\n return new BasicAuthService(this.username, this.password)\n }\n\n async switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<AuthenticationProvider> {\n return Promise.resolve(new BasicAuthenticationProvider(loginForGroup(newGroupId, matches), this.password))\n }\n}\n\nexport class NoAuthenticationProvider implements AuthenticationProvider {\n getAuthService(): AuthService {\n return new NoAuthService()\n }\n\n getIcureTokens(): Promise<{ token: string; refreshToken: string } | undefined> {\n return Promise.resolve() as Promise<undefined>\n }\n\n async switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<AuthenticationProvider> {\n return Promise.resolve(new NoAuthenticationProvider())\n }\n}\n\n/**\n * @internal\n */\nfunction loginForGroup(groupId: string, matches: Array<UserGroup>): string {\n const matchForGroup = matches.find((x) => x.groupId === groupId)\n if (!matchForGroup?.userId) {\n throw new Error(`Can't switch to group ${groupId} for the current user.`)\n }\n return `${groupId}/${matchForGroup.userId}`\n}\n\n/**\n * @internal\n * Creates a jwtAuth from an existing one in order to switch group\n */\nasync function switchJwtAuth(\n authApi: IccAuthApi,\n jwtAuth: JwtAuthService | JwtBridgedAuthService,\n username: string | undefined,\n password: string | undefined,\n newGroupId: string,\n matches: Array<UserGroup>\n): Promise<{ loginForGroup: string; switchedJwtAuth: JwtAuthService | JwtBridgedAuthService }> {\n const refreshToken = jwtAuth.isInErrorState() ? undefined : await jwtAuth.refreshToken\n const switchedJwtInfo = refreshToken ? await authApi.switchGroup(refreshToken, newGroupId).catch(() => undefined as any) : undefined\n const updatedLogin = loginForGroup(newGroupId, matches)\n const switchedJwtAuth =\n !!username && !!password\n ? new JwtBridgedAuthService(\n authApi,\n updatedLogin,\n password,\n switchedJwtInfo?.token && switchedJwtInfo?.refreshToken\n ? { authJwt: switchedJwtInfo.token, refreshJwt: switchedJwtInfo.refreshToken }\n : undefined\n )\n : new JwtAuthService(\n authApi,\n switchedJwtInfo?.token && switchedJwtInfo?.refreshToken\n ? { authJwt: switchedJwtInfo.token, refreshJwt: switchedJwtInfo.refreshToken }\n : undefined\n )\n return { loginForGroup: updatedLogin, switchedJwtAuth }\n}\n"]}
1
+ {"version":3,"file":"AuthenticationProvider.js","sourceRoot":"","sources":["../../../icc-x-api/auth/AuthenticationProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthService } from './AuthService'\nimport { IccAuthApi } from '../../icc-api'\nimport { EnsembleAuthService } from './EnsembleAuthService'\nimport { JwtBridgedAuthService } from './JwtBridgedAuthService'\nimport { NoAuthService } from './NoAuthService'\nimport { BasicAuthService } from './BasicAuthService'\nimport { JwtAuthService } from './JwtAuthService'\nimport { UserGroup } from '../../icc-api/model/UserGroup'\nimport { tr } from 'date-fns/locale'\n\n/**\n * @internal you should not implement this interface yourself.\n */\nexport interface AuthenticationProvider {\n /**\n * @internal this method is meant for internal use only and may be changed without notice\n */\n getAuthService(): AuthService\n\n /**\n * @internal this method is meant for internal use only and may be changed without notice\n * Gives a new authentication provider for the same user and authentication method but for a different iCure group\n * @param newGroupId id of the new group to switch to\n * @param matches the list of groups the user is in, containing also the group-specific id of the user. Note that users with same login username but\n * different password are considered as if they are different users and should not appear in these matches. You can get this list by calling\n * {@link IccUserApi.getMatchingUsers} authenticated.\n * @return an object containing:\n * - `switchedProvider`: a new authentication provider, which can be used to perform requests as the user in the new group\n * - `isGroupLocked`: true if the returned authentication provider is \"locked\" within new group, depends on the implementation of\n * AuthenticationProvider used. This means that using this provider when performing a request to get the list of groups the user is in may return\n * under certain circumstances only the new group, even though the original provider was able to return multiple groups. Even if true you can\n * still switch to another group, but you will have to use another authentication provider to get the matches.\n */\n switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<{ switchedProvider: AuthenticationProvider; isGroupLocked: boolean }>\n\n getIcureTokens(): Promise<{ token: string; refreshToken: string } | undefined>\n}\n\nexport class EnsembleAuthenticationProvider implements AuthenticationProvider {\n private readonly basicAuth: BasicAuthService\n private jwtAuth: JwtAuthService | JwtBridgedAuthService\n private suspensionEnd: Date | undefined\n\n constructor(\n private readonly authApi: IccAuthApi,\n private readonly username: string,\n private readonly password: string,\n private readonly jwtTimeout: number = 3600,\n jwtAuth?: JwtAuthService | JwtBridgedAuthService,\n basicAuth?: BasicAuthService,\n thirdPartyTokens: { [thirdParty: string]: string } = {}\n ) {\n this.jwtAuth = jwtAuth ?? new JwtBridgedAuthService(this.authApi, this.username, this.password, thirdPartyTokens)\n this.basicAuth = basicAuth ?? new BasicAuthService(this.username, this.password)\n }\n\n getIcureTokens(): Promise<{ token: string; refreshToken: string } | undefined> {\n return this.jwtAuth.getIcureTokens()\n }\n\n getAuthService(): AuthService {\n // If the jwtAuth is in an error state, it instantiates a new one,\n // but it will not use it until the suspension ends\n if (this.jwtAuth.isInErrorState()) {\n console.warn('Error state in JWT, I will skip it')\n this.jwtAuth = new JwtBridgedAuthService(this.authApi, this.username, this.password)\n this.suspensionEnd = new Date(new Date().getTime() + this.jwtTimeout * 1000)\n }\n\n return !!this.suspensionEnd && new Date() <= this.suspensionEnd\n ? new EnsembleAuthService(null, new NoAuthService(), this.basicAuth)\n : new EnsembleAuthService(this.jwtAuth, new NoAuthService(), this.basicAuth)\n }\n\n async switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<{ switchedProvider: AuthenticationProvider; isGroupLocked: boolean }> {\n const switchInfo = await switchJwtAuth(this.authApi, this.jwtAuth, this.username, this.password, newGroupId, matches)\n return {\n switchedProvider: new EnsembleAuthenticationProvider(\n this.authApi,\n switchInfo.loginForGroup,\n this.password,\n this.jwtTimeout,\n switchInfo.switchedJwtAuth,\n new BasicAuthService(switchInfo.loginForGroup, this.password)\n ),\n isGroupLocked: true,\n }\n }\n}\n\nexport class JwtAuthenticationProvider implements AuthenticationProvider {\n getIcureTokens(): Promise<{ token: string; refreshToken: string } | undefined> {\n return this.jwtAuth.getIcureTokens()\n }\n\n private readonly jwtAuth: JwtAuthService | JwtBridgedAuthService\n\n /**\n * @internal\n * @param authApi\n * @param username\n * @param password\n * @param jwtAuth\n * @param icureToken\n */\n constructor(\n private readonly authApi: IccAuthApi,\n private readonly username?: string,\n private readonly password?: string,\n jwtAuth?: JwtAuthService | JwtBridgedAuthService,\n private readonly icureToken?: { token: string; refreshToken: string }\n ) {\n const composedAuth =\n jwtAuth ??\n (icureToken\n ? new JwtAuthService(authApi, { authJwt: icureToken.token, refreshJwt: icureToken.refreshToken })\n : !!username && !!password\n ? new JwtBridgedAuthService(authApi, username!, password!)\n : undefined)\n if (!composedAuth) {\n throw new Error('No authentication method provided')\n }\n this.jwtAuth = composedAuth\n }\n\n getAuthService(): AuthService {\n return this.jwtAuth\n }\n\n async switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<{ switchedProvider: AuthenticationProvider; isGroupLocked: boolean }> {\n const switchInfo = await switchJwtAuth(this.authApi, this.jwtAuth, this.username, this.password, newGroupId, matches)\n return {\n switchedProvider: new JwtAuthenticationProvider(this.authApi, switchInfo.loginForGroup, this.password, switchInfo.switchedJwtAuth),\n isGroupLocked: true,\n }\n }\n}\n\nexport class BasicAuthenticationProvider implements AuthenticationProvider {\n getIcureTokens(): Promise<{ token: string; refreshToken: string } | undefined> {\n return Promise.resolve() as Promise<undefined>\n }\n\n constructor(private username: string, private password: string) {}\n\n getAuthService(): AuthService {\n return new BasicAuthService(this.username, this.password)\n }\n\n async switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<{ switchedProvider: AuthenticationProvider; isGroupLocked: boolean }> {\n return {\n switchedProvider: new BasicAuthenticationProvider(loginForGroup(newGroupId, matches), this.password),\n isGroupLocked: true,\n }\n }\n}\n\nexport class NoAuthenticationProvider implements AuthenticationProvider {\n getAuthService(): AuthService {\n return new NoAuthService()\n }\n\n getIcureTokens(): Promise<{ token: string; refreshToken: string } | undefined> {\n return Promise.resolve() as Promise<undefined>\n }\n\n async switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<{ switchedProvider: AuthenticationProvider; isGroupLocked: boolean }> {\n return { switchedProvider: this, isGroupLocked: false }\n }\n}\n\n/**\n * @internal\n */\nfunction loginForGroup(groupId: string, matches: Array<UserGroup>): string {\n const matchForGroup = matches.find((x) => x.groupId === groupId)\n if (!matchForGroup?.userId) {\n throw new Error(`Can't switch to group ${groupId} for the current user.`)\n }\n return `${groupId}/${matchForGroup.userId}`\n}\n\n/**\n * @internal\n * Creates a jwtAuth from an existing one in order to switch group\n */\nasync function switchJwtAuth(\n authApi: IccAuthApi,\n jwtAuth: JwtAuthService | JwtBridgedAuthService,\n username: string | undefined,\n password: string | undefined,\n newGroupId: string,\n matches: Array<UserGroup>\n): Promise<{ loginForGroup: string; switchedJwtAuth: JwtAuthService | JwtBridgedAuthService }> {\n const refreshToken = jwtAuth.isInErrorState() ? undefined : await jwtAuth.refreshToken\n const switchedJwtInfo = refreshToken ? await authApi.switchGroup(refreshToken, newGroupId).catch(() => undefined as any) : undefined\n const updatedLogin = loginForGroup(newGroupId, matches)\n const switchedJwtAuth =\n !!username && !!password\n ? new JwtBridgedAuthService(\n authApi,\n updatedLogin,\n password,\n switchedJwtInfo?.token && switchedJwtInfo?.refreshToken\n ? { authJwt: switchedJwtInfo.token, refreshJwt: switchedJwtInfo.refreshToken }\n : undefined\n )\n : new JwtAuthService(\n authApi,\n switchedJwtInfo?.token && switchedJwtInfo?.refreshToken\n ? { authJwt: switchedJwtInfo.token, refreshJwt: switchedJwtInfo.refreshToken }\n : undefined\n )\n return { loginForGroup: updatedLogin, switchedJwtAuth }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { AuthenticationProvider } from './AuthenticationProvider';
2
2
  import { UserGroup } from '../../icc-api/model/UserGroup';
3
3
  import { AuthService } from './AuthService';
4
- import { IccAuthApi } from '../../icc-api';
4
+ import { IccAuthApi, OAuthThirdParty } from '../../icc-api';
5
5
  /**
6
6
  * Needed by a {@link SmartAuthProvider} to get the secrets (password, token, etc.) for authentication to the iCure SDK as needed.
7
7
  */
@@ -42,14 +42,16 @@ export interface AuthSecretProvider {
42
42
  * @return a promise that resolves with the secret and the secret type to use for authentication. If the promise rejects then the ongoing SDK
43
43
  * operation will fail without being re-attempted.
44
44
  */
45
- getSecret(acceptedSecrets: AuthSecretType[], previousAttempts: {
46
- secret: string;
47
- secretType: AuthSecretType;
48
- }[]): Promise<{
49
- secret: string;
50
- secretType: AuthSecretType;
51
- }>;
45
+ getSecret(acceptedSecrets: AuthSecretType[], previousAttempts: AuthSecretDetails[]): Promise<AuthSecretDetails>;
52
46
  }
47
+ export type AuthSecretDetails = {
48
+ value: string;
49
+ secretType: Exclude<AuthSecretType, AuthSecretType.EXTERNAL_AUTHENTICATION>;
50
+ } | {
51
+ value: string;
52
+ secretType: AuthSecretType.EXTERNAL_AUTHENTICATION;
53
+ oauthType: OAuthThirdParty;
54
+ };
53
55
  /**
54
56
  * Represents a type of secret that can be used for authentication with iCure.
55
57
  */
@@ -72,7 +74,12 @@ export declare enum AuthSecretType {
72
74
  * A long-lived iCure token, an internal authentication token that lasts longer than 5 minutes. Unlike passwords these tokens usually are generated
73
75
  * by some component of iCure, and are not chosen by the user.
74
76
  */
75
- LONG_LIVED_TOKEN = "LONG_LIVED_TOKEN"
77
+ LONG_LIVED_TOKEN = "LONG_LIVED_TOKEN",
78
+ /**
79
+ * A token provided by an external authentication provider (e.g. Oauth/Google).
80
+ * Not yet in use.
81
+ */
82
+ EXTERNAL_AUTHENTICATION = "EXTERNAL_AUTHENTICATION"
76
83
  }
77
84
  /**
78
85
  * @internal this class is meant for internal use only and may be changed without notice. The SmartAuthProvider will be initialised automatically
@@ -105,14 +112,22 @@ export declare class SmartAuthProvider implements AuthenticationProvider {
105
112
  * @param props optional initialisation properties.
106
113
  */
107
114
  static initialise(authApi: IccAuthApi, login: string, secretProvider: AuthSecretProvider, props?: {
108
- initialSecret?: string;
115
+ initialSecret?: {
116
+ plainSecret: string;
117
+ } | {
118
+ oauthToken: string;
119
+ oauthType: OAuthThirdParty;
120
+ };
109
121
  initialAuthToken?: string;
110
122
  initialRefreshToken?: string;
111
123
  loginGroupId?: string;
112
124
  }): SmartAuthProvider;
113
125
  private constructor();
114
126
  getAuthService(): AuthService;
115
- switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<AuthenticationProvider>;
127
+ switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<{
128
+ switchedProvider: AuthenticationProvider;
129
+ isGroupLocked: boolean;
130
+ }>;
116
131
  getIcureTokens(): Promise<{
117
132
  token: string;
118
133
  refreshToken: string;
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.SmartAuthProvider = exports.AuthSecretType = void 0;
13
+ const icc_api_1 = require("../../icc-api");
13
14
  const XHR_1 = require("../../icc-api/api/XHR");
14
15
  var XHRError = XHR_1.XHR.XHRError;
15
16
  const JwtUtils_1 = require("./JwtUtils");
@@ -41,7 +42,7 @@ var AuthSecretType;
41
42
  * A token provided by an external authentication provider (e.g. Oauth/Google).
42
43
  * Not yet in use.
43
44
  */
44
- // EXTERNAL_AUTHENTICATION = 'EXTERNAL_AUTHENTICATION',
45
+ AuthSecretType["EXTERNAL_AUTHENTICATION"] = "EXTERNAL_AUTHENTICATION";
45
46
  /**
46
47
  * A special case of external authentication where the provider is a digital identity provider.
47
48
  * Not yet in use.
@@ -78,7 +79,20 @@ class SmartAuthProvider {
78
79
  * @param props optional initialisation properties.
79
80
  */
80
81
  static initialise(authApi, login, secretProvider, props = {}) {
81
- return new SmartAuthProvider(new TokenProvider(login, props.loginGroupId, props.initialSecret ? { value: props.initialSecret, type: undefined } : undefined, props.initialAuthToken, props.initialRefreshToken, authApi, secretProvider), props.loginGroupId);
82
+ let initialSecret = undefined;
83
+ if (props.initialSecret) {
84
+ if ('plainSecret' in props.initialSecret) {
85
+ initialSecret = { value: props.initialSecret.plainSecret, type: undefined };
86
+ }
87
+ else {
88
+ initialSecret = {
89
+ value: props.initialSecret.oauthToken,
90
+ type: ServerAuthenticationClass.EXTERNAL_AUTHENTICATION,
91
+ oauthType: props.initialSecret.oauthType,
92
+ };
93
+ }
94
+ }
95
+ return new SmartAuthProvider(new TokenProvider(login, props.loginGroupId, initialSecret, props.initialAuthToken, props.initialRefreshToken, authApi, secretProvider), props.loginGroupId);
82
96
  }
83
97
  constructor(tokenProvider, groupId) {
84
98
  this.tokenProvider = tokenProvider;
@@ -90,11 +104,11 @@ class SmartAuthProvider {
90
104
  switchGroup(newGroupId, matches) {
91
105
  return __awaiter(this, void 0, void 0, function* () {
92
106
  if (newGroupId == this.groupId)
93
- return Promise.resolve(this);
107
+ return { switchedProvider: this, isGroupLocked: false };
94
108
  if (!matches.find((match) => match.groupId == newGroupId))
95
109
  throw new Error('New group id not found in matches.');
96
110
  const switchedProvider = yield this.tokenProvider.switchedGroup(newGroupId);
97
- return new SmartAuthProvider(switchedProvider, this.groupId);
111
+ return { switchedProvider: new SmartAuthProvider(switchedProvider, this.groupId), isGroupLocked: false };
98
112
  });
99
113
  }
100
114
  getIcureTokens() {
@@ -107,10 +121,13 @@ var ServerAuthenticationClass;
107
121
  // DIGITAL_ID = 60,
108
122
  ServerAuthenticationClass[ServerAuthenticationClass["TWO_FACTOR_AUTHENTICATION"] = 50] = "TWO_FACTOR_AUTHENTICATION";
109
123
  ServerAuthenticationClass[ServerAuthenticationClass["SHORT_LIVED_TOKEN"] = 40] = "SHORT_LIVED_TOKEN";
110
- // EXTERNAL_AUTHENTICATION = 30,
124
+ ServerAuthenticationClass[ServerAuthenticationClass["EXTERNAL_AUTHENTICATION"] = 30] = "EXTERNAL_AUTHENTICATION";
111
125
  ServerAuthenticationClass[ServerAuthenticationClass["PASSWORD"] = 20] = "PASSWORD";
112
126
  ServerAuthenticationClass[ServerAuthenticationClass["LONG_LIVED_TOKEN"] = 10] = "LONG_LIVED_TOKEN";
113
127
  })(ServerAuthenticationClass || (ServerAuthenticationClass = {}));
128
+ // In some providers Oauth tokens may have short duration or may be usable only once. We only want to cache them if they are going to be reusable and
129
+ // if they last more than 5 minutes.
130
+ const longLivedOAuthTokens = new Set([icc_api_1.OAuthThirdParty.GOOGLE]);
114
131
  class TokenProvider {
115
132
  constructor(login, groupId, currentLongLivedSecret, cachedToken, cachedRefreshToken, authApi, authSecretProvider) {
116
133
  this.login = login;
@@ -160,7 +177,7 @@ class TokenProvider {
160
177
  getNewToken(minimumAuthenticationClassLevel) {
161
178
  return __awaiter(this, void 0, void 0, function* () {
162
179
  if (!!this.currentLongLivedSecret && (!this.currentLongLivedSecret.type || this.currentLongLivedSecret.type >= minimumAuthenticationClassLevel)) {
163
- const resultWithCachedSecret = yield this.doGetTokenWithSecret(this.currentLongLivedSecret.value, minimumAuthenticationClassLevel);
180
+ const resultWithCachedSecret = yield this.doGetTokenWithSecret(this.currentLongLivedSecret, minimumAuthenticationClassLevel);
164
181
  if ('success' in resultWithCachedSecret) {
165
182
  return resultWithCachedSecret.success;
166
183
  }
@@ -190,19 +207,20 @@ class TokenProvider {
190
207
  throw new Error('Internal error: no secret type is accepted for this request. Group may be misconfigured, or client may be outdated.');
191
208
  const attempts = [];
192
209
  while (true) {
193
- const { secret, secretType } = yield this.authSecretProvider.getSecret([...acceptedSecrets], attempts);
194
- if (!acceptedSecrets.includes(secretType))
195
- throw new Error(`Accepted secret types are ${JSON.stringify(acceptedSecrets)}, but got a secret of type ${secretType}.`);
196
- attempts.push({ secret, secretType });
197
- const result = yield this.doGetTokenWithSecret(secret, minimumAuthenticationClassLevel);
210
+ const secretDetails = yield this.authSecretProvider.getSecret([...acceptedSecrets], attempts);
211
+ if (!acceptedSecrets.includes(secretDetails.secretType))
212
+ throw new Error(`Accepted secret types are ${JSON.stringify(acceptedSecrets)}, but got a secret of type ${secretDetails.secretType}.`);
213
+ attempts.push(secretDetails);
214
+ const result = yield this.doGetTokenWithSecret(secretDetails, minimumAuthenticationClassLevel);
198
215
  if ('success' in result) {
199
- this.updateCachedSecret(secret, secretType);
216
+ this.updateCachedSecret(secretDetails);
200
217
  return result.success;
201
218
  }
202
219
  else if (result.failure == DoGetTokenResultFailureReason.NEEDS_2FA) {
203
- return this.askTotpAndGetToken(secret, minimumAuthenticationClassLevel);
220
+ return this.askTotpAndGetToken(secretDetails.value, minimumAuthenticationClassLevel);
204
221
  }
205
- else if (secretType == AuthSecretType.PASSWORD && result.failure == DoGetTokenResultFailureReason.INVALID_AUTH_CLASS_LEVEL) {
222
+ else if (secretDetails.value == AuthSecretType.PASSWORD && result.failure == DoGetTokenResultFailureReason.INVALID_AUTH_CLASS_LEVEL) {
223
+ // If we tried a password, and it turns out that the user has 2fa not enabled next time we don't consider password valid
206
224
  return this.askSecretAndGetToken(minimumAuthenticationClassLevel, false);
207
225
  } // else retry
208
226
  }
@@ -214,13 +232,13 @@ class TokenProvider {
214
232
  throw new Error("Internal error: asking for totp to login but minimumAuthenticationClassLevel is higher than TWO_FACTOR_AUTHENTICATION's level.");
215
233
  const attempts = [];
216
234
  while (true) {
217
- const { secret, secretType } = yield this.authSecretProvider.getSecret([AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN], attempts);
218
- if (secretType != AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN)
219
- throw new Error(`Was expecting a 2fa token but got a secret of type ${secretType}.`);
220
- attempts.push({ secret, secretType });
221
- const result = yield this.doGetTokenWithSecret(`${password}|${secret}`, minimumAuthenticationClassLevel);
235
+ const details = yield this.authSecretProvider.getSecret([AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN], attempts);
236
+ if (details.secretType != AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN)
237
+ throw new Error(`Was expecting a 2fa token but got a secret of type ${details.secretType}.`);
238
+ attempts.push(details);
239
+ const result = yield this.doGetTokenWithSecret({ value: `${password}|${details.value}` }, minimumAuthenticationClassLevel);
222
240
  if ('success' in result) {
223
- this.updateCachedSecret(password, AuthSecretType.PASSWORD);
241
+ this.updateCachedSecret({ value: password, secretType: AuthSecretType.PASSWORD });
224
242
  return result.success;
225
243
  }
226
244
  else if (result.failure != DoGetTokenResultFailureReason.INVALID_2FA) {
@@ -231,7 +249,14 @@ class TokenProvider {
231
249
  }
232
250
  doGetTokenWithSecret(secret, minimumAuthenticationClassLevel) {
233
251
  return __awaiter(this, void 0, void 0, function* () {
234
- return this.authApi.login({ username: this.login, password: secret }, this.groupId).then((authResult) => {
252
+ let authResultPromise;
253
+ if ('oauthType' in secret && !!secret.oauthType) {
254
+ authResultPromise = this.authApi.loginWithThirdPartyToken(secret.oauthType, secret.value);
255
+ }
256
+ else {
257
+ authResultPromise = this.authApi.login({ username: this.login, password: secret.value }, this.groupId);
258
+ }
259
+ return authResultPromise.then((authResult) => {
235
260
  const { token, refreshToken } = authResult;
236
261
  if (!token || !refreshToken)
237
262
  throw new Error('Internal error: login succeeded but no token was returned. Unsupported backend version?');
@@ -277,9 +302,23 @@ class TokenProvider {
277
302
  return new TokenProvider(this.login, newGroupId, this.currentLongLivedSecret ? { value: this.currentLongLivedSecret.value, type: undefined } : undefined, groupSwitchedTokens.token, groupSwitchedTokens.refreshToken, this.authApi, this.authSecretProvider);
278
303
  });
279
304
  }
280
- updateCachedSecret(secret, secretType) {
281
- if (secretType == AuthSecretType.LONG_LIVED_TOKEN || secretType == AuthSecretType.PASSWORD) {
282
- this.currentLongLivedSecret = { value: secret, type: ServerAuthenticationClass.LONG_LIVED_TOKEN };
305
+ updateCachedSecret(details) {
306
+ switch (details.secretType) {
307
+ case AuthSecretType.PASSWORD:
308
+ this.currentLongLivedSecret = { value: details.value, type: ServerAuthenticationClass.PASSWORD };
309
+ break;
310
+ case AuthSecretType.LONG_LIVED_TOKEN:
311
+ this.currentLongLivedSecret = { value: details.value, type: ServerAuthenticationClass.LONG_LIVED_TOKEN };
312
+ break;
313
+ case AuthSecretType.EXTERNAL_AUTHENTICATION:
314
+ if (longLivedOAuthTokens.has(details.oauthType)) {
315
+ this.currentLongLivedSecret = {
316
+ value: details.value,
317
+ type: ServerAuthenticationClass.EXTERNAL_AUTHENTICATION,
318
+ oauthType: details.oauthType,
319
+ };
320
+ }
321
+ break;
283
322
  }
284
323
  }
285
324
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SmartAuthProvider.js","sourceRoot":"","sources":["../../../icc-x-api/auth/SmartAuthProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthenticationProvider, NoAuthenticationProvider } from './AuthenticationProvider'\nimport { UserGroup } from '../../icc-api/model/UserGroup'\nimport { AuthService } from './AuthService'\nimport { IccAuthApi } from '../../icc-api'\nimport { XHR } from '../../icc-api/api/XHR'\nimport XHRError = XHR.XHRError\nimport { decodeJwtClaims, isJwtInvalidOrExpired } from './JwtUtils'\n\n/**\n * Needed by a {@link SmartAuthProvider} to get the secrets (password, token, etc.) for authentication to the iCure SDK as needed.\n */\nexport interface AuthSecretProvider {\n /**\n * Provides a secret for authentication to the iCure SDK.\n *\n * ## Accepted secrets\n *\n * The method will be provided with an array of the secrets types that are acceptable (`acceptedSecrets`). Usually this array will contain multiple\n * elements, but this depends on the group configuration, the user (if he has 2fa setup or not), or the operation being performed. For groups using\n * default configurations and for patients without 2fa enabled for example the array will always contain the {@link AuthSecretType.PASSWORD} element.\n * Usually the array contain also the {@link AuthSecretType.LONG_LIVED_TOKEN} element, but if the user is attempting to perform a sensitive operations\n * such as changing his password the default group configuration does not allow for the user to authenticate using a JWT obtained from a long-lived\n * token for this operation, meaning the array will not contain the {@link AuthSecretType.LONG_LIVED_TOKEN} element.\n *\n * Regardless of the number of elements in the array only one secret of the accepted types is sufficient for the operation to succeed.\n *\n * ## TWO_FACTOR_AUTHENTICATION_TOKEN secret type\n *\n * The {@link AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN} secret type is only used when the user has 2fa enabled. In this case the SDK will call\n * this method twice, once containing the {@link AuthSecretType.PASSWORD} element in the `acceptedSecrets` array, and if the provided secret is a\n * valid password the SDK will immediately call this method again, this time containing the {@link AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN}\n * instead of the {@link AuthSecretType.PASSWORD} element.\n *\n * Any future call to this method from the same provider instance will not contain the {@link AuthSecretType.PASSWORD} element anymore, as it is\n * cached, but it may contain the {@link AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN} element instead.\n *\n * Note that the 2fa token is not needed for logging in through a long-lived or short-lived token, it is only used in combination with a password.\n * If the user is using 2fa, and you get in input as `acceptedSecrets` an array `[PASSWORD, LONG_LIVED_TOKEN, SHORT_LIVED_TOKEN]`, and you pass to\n * authenticate a long-lived token, the SDK will not call this method again to ask for the 2fa token.\n *\n * @param acceptedSecrets the types of secrets that are acceptable for the operation being performed.\n * @param previousAttempts the secrets that were previously attempted by the SDK for this operation. This array will be empty the first time this\n * method is called for a given operation, but it may contain multiple elements if the SDK has already called this method multiple times because the\n * previously returned secrets were not valid. The first element is the first secret that was attempted, and the last element is the most recently\n * attempted.\n * @return a promise that resolves with the secret and the secret type to use for authentication. If the promise rejects then the ongoing SDK\n * operation will fail without being re-attempted.\n */\n getSecret(\n acceptedSecrets: AuthSecretType[],\n previousAttempts: { secret: string; secretType: AuthSecretType }[]\n ): Promise<{ secret: string; secretType: AuthSecretType }> // We may want to add some onSuccess callback in future or similar\n}\n\n/**\n * Represents a type of secret that can be used for authentication with iCure.\n */\nexport enum AuthSecretType {\n /**\n * Password chosen by the user.\n */\n PASSWORD = 'PASSWORD', // pragma: allowlist secret\n /**\n * Time based one time password provided by authenticator applications, generated on the basis of a timestamp and a shared secret between the iCure\n * server and the authenticator application.\n */\n TWO_FACTOR_AUTHENTICATION_TOKEN = 'TWO_FACTOR_AUTHENTICATION_TOKEN',\n /**\n * A short-lived iCure token, an internal authentication token that lasts 5 minutes or less. Unlike passwords these tokens usually are generated by\n * some component of iCure, and are not chosen by the user.\n */\n SHORT_LIVED_TOKEN = 'SHORT_LIVED_TOKEN',\n /**\n * A long-lived iCure token, an internal authentication token that lasts longer than 5 minutes. Unlike passwords these tokens usually are generated\n * by some component of iCure, and are not chosen by the user.\n */\n LONG_LIVED_TOKEN = 'LONG_LIVED_TOKEN',\n /**\n * A token provided by an external authentication provider (e.g. Oauth/Google).\n * Not yet in use.\n */\n // EXTERNAL_AUTHENTICATION = 'EXTERNAL_AUTHENTICATION',\n /**\n * A special case of external authentication where the provider is a digital identity provider.\n * Not yet in use.\n */\n // DIGITAL_ID = 'DIGITAL_ID',\n}\n\n// Here starts internal entities that should not be used directly.\n\n/**\n * @internal this class is meant for internal use only and may be changed without notice. The SmartAuthProvider will be initialised automatically\n * by the iCure api depending on the authentication options you provide.\n *\n * An authentication provider that automatically requests secrets for authentication as needed.\n *\n * This authentication provider can be initialised already with some secrets or tokens, and the provider will cache them and use them as needed for\n * as long as they remain valid. If at any point however the provider needs an updated secret or a secret of a different kind it will automatically\n * request this to the {@link SmartAuthProvider} to get the secret.\n *\n * An advantage of using this provider over others is that in case all the cached tokens and secrets were to expire while performing a request,\n * instead of having the request fail the provider will ask for new secrets from the {@link SmartAuthProvider} and the request will automatically\n * be retried with the new secret. Additionally, the provider may request updated secrets also for performing some sensitive operations (e.g. changing\n * password of the user) even if the cached tokens and/or did not expire. This could be the case for example if the cached secret is a long-lived\n * token, but in order to change the password the user needs to provide his current password.\n *\n * Note that in this context the cache of secrets and token is in memory only, and is not persisted in any way. Different instances of this provider\n * will not share the same cache.\n *\n */\nexport class SmartAuthProvider implements AuthenticationProvider {\n /**\n * Initialises a {@link SmartAuthProvider}.\n * @param authApi an \"anonymous\" {@link IccAuthApi} to use for authentication.\n * @param login\n * @param secretProvider\n * @param props optional initialisation properties.\n */\n static initialise(\n authApi: IccAuthApi,\n login: string,\n secretProvider: AuthSecretProvider,\n props: {\n initialSecret?: string\n initialAuthToken?: string\n initialRefreshToken?: string\n loginGroupId?: string\n } = {}\n ): SmartAuthProvider {\n return new SmartAuthProvider(\n new TokenProvider(\n login,\n props.loginGroupId,\n props.initialSecret ? { value: props.initialSecret, type: undefined } : undefined,\n props.initialAuthToken,\n props.initialRefreshToken,\n authApi,\n secretProvider\n ),\n props.loginGroupId\n )\n }\n\n private constructor(private readonly tokenProvider: TokenProvider, private readonly groupId: string | undefined) {}\n\n getAuthService(): AuthService {\n return new SmartAuthService(this.tokenProvider)\n }\n\n async switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<AuthenticationProvider> {\n if (newGroupId == this.groupId) return Promise.resolve(this)\n if (!matches.find((match) => match.groupId == newGroupId)) throw new Error('New group id not found in matches.')\n const switchedProvider = await this.tokenProvider.switchedGroup(newGroupId)\n return new SmartAuthProvider(switchedProvider, this.groupId)\n }\n\n getIcureTokens(): Promise<{ token: string; refreshToken: string } | undefined> {\n return Promise.resolve(undefined)\n }\n}\n\nenum ServerAuthenticationClass {\n // DIGITAL_ID = 60,\n TWO_FACTOR_AUTHENTICATION = 50,\n SHORT_LIVED_TOKEN = 40,\n // EXTERNAL_AUTHENTICATION = 30,\n PASSWORD = 20,\n LONG_LIVED_TOKEN = 10,\n}\ntype LongLivedSecretType =\n | ServerAuthenticationClass.LONG_LIVED_TOKEN\n | ServerAuthenticationClass.PASSWORD\n | ServerAuthenticationClass.TWO_FACTOR_AUTHENTICATION\nclass TokenProvider {\n constructor(\n private login: string,\n private groupId: string | undefined,\n private currentLongLivedSecret: { value: string; type: LongLivedSecretType | undefined } | undefined,\n private cachedToken: string | undefined,\n private cachedRefreshToken: string | undefined,\n private readonly authApi: IccAuthApi,\n private readonly authSecretProvider: AuthSecretProvider\n ) {}\n\n async getCachedOrRefreshedOrNewToken(): Promise<{ token: string; type: RetrievedTokenType }> {\n if (!!this.cachedToken && !isJwtInvalidOrExpired(this.cachedToken)) {\n return { token: this.cachedToken, type: RetrievedTokenType.CACHED }\n } else if (!!this.cachedRefreshToken && !isJwtInvalidOrExpired(this.cachedRefreshToken)) {\n return this.refreshAndCacheToken(this.cachedRefreshToken)\n } else {\n return { token: await this.getAndCacheNewToken(undefined), type: RetrievedTokenType.NEW }\n }\n }\n\n async getNewTokenWithClass(minimumAuthenticationClass: number): Promise<string> {\n return await this.getAndCacheNewToken(minimumAuthenticationClass)\n }\n\n private async getAndCacheNewToken(minimumAuthenticationClassLevel: number | undefined): Promise<string> {\n const { token, refreshToken } = await this.getNewToken(minimumAuthenticationClassLevel ?? 0)\n this.cachedToken = token\n this.cachedRefreshToken = refreshToken\n return token\n }\n\n private async refreshAndCacheToken(refreshToken: string): Promise<{ token: string; type: RetrievedTokenType }> {\n return await this.authApi.refreshAuthenticationJWT(refreshToken).then(\n (authResult) => {\n if (!authResult.token) throw new Error('Internal error: refresh succeeded but no token was returned. Unsupported backend version?')\n this.cachedToken = authResult.token\n return { token: authResult.token, type: RetrievedTokenType.REFRESHED }\n },\n async () => ({ token: await this.getAndCacheNewToken(undefined), type: RetrievedTokenType.NEW })\n )\n }\n\n private async getNewToken(minimumAuthenticationClassLevel: number): Promise<{ token: string; refreshToken: string }> {\n if (!!this.currentLongLivedSecret && (!this.currentLongLivedSecret.type || this.currentLongLivedSecret.type >= minimumAuthenticationClassLevel)) {\n const resultWithCachedSecret = await this.doGetTokenWithSecret(this.currentLongLivedSecret.value, minimumAuthenticationClassLevel)\n if ('success' in resultWithCachedSecret) {\n return resultWithCachedSecret.success\n } else if (\n resultWithCachedSecret.failure === DoGetTokenResultFailureReason.NEEDS_2FA &&\n minimumAuthenticationClassLevel <= ServerAuthenticationClass.TWO_FACTOR_AUTHENTICATION\n ) {\n return this.askTotpAndGetToken(this.currentLongLivedSecret.value, minimumAuthenticationClassLevel)\n } else return this.askSecretAndGetToken(minimumAuthenticationClassLevel, true)\n } else {\n return this.askSecretAndGetToken(minimumAuthenticationClassLevel, true)\n }\n }\n\n private async askSecretAndGetToken(\n minimumAuthenticationClassLevel: number,\n passwordIsValidAs2fa: boolean\n ): Promise<{ token: string; refreshToken: string }> {\n const acceptedSecrets = [\n minimumAuthenticationClassLevel <= ServerAuthenticationClass.LONG_LIVED_TOKEN ? [AuthSecretType.LONG_LIVED_TOKEN] : [],\n minimumAuthenticationClassLevel <= ServerAuthenticationClass.SHORT_LIVED_TOKEN ? [AuthSecretType.SHORT_LIVED_TOKEN] : [],\n minimumAuthenticationClassLevel <= ServerAuthenticationClass.TWO_FACTOR_AUTHENTICATION &&\n (passwordIsValidAs2fa || minimumAuthenticationClassLevel <= ServerAuthenticationClass.PASSWORD)\n ? [AuthSecretType.PASSWORD]\n : [],\n ].flat()\n if (!acceptedSecrets.length)\n throw new Error('Internal error: no secret type is accepted for this request. Group may be misconfigured, or client may be outdated.')\n const attempts: { secret: string; secretType: AuthSecretType }[] = []\n while (true) {\n const { secret, secretType } = await this.authSecretProvider.getSecret([...acceptedSecrets], attempts)\n if (!acceptedSecrets.includes(secretType))\n throw new Error(`Accepted secret types are ${JSON.stringify(acceptedSecrets)}, but got a secret of type ${secretType}.`)\n attempts.push({ secret, secretType })\n const result = await this.doGetTokenWithSecret(secret, minimumAuthenticationClassLevel)\n if ('success' in result) {\n this.updateCachedSecret(secret, secretType)\n return result.success\n } else if (result.failure == DoGetTokenResultFailureReason.NEEDS_2FA) {\n return this.askTotpAndGetToken(secret, minimumAuthenticationClassLevel)\n } else if (secretType == AuthSecretType.PASSWORD && result.failure == DoGetTokenResultFailureReason.INVALID_AUTH_CLASS_LEVEL) {\n return this.askSecretAndGetToken(minimumAuthenticationClassLevel, false)\n } // else retry\n }\n }\n\n private async askTotpAndGetToken(password: string, minimumAuthenticationClassLevel: number): Promise<{ token: string; refreshToken: string }> {\n if (minimumAuthenticationClassLevel > ServerAuthenticationClass.TWO_FACTOR_AUTHENTICATION)\n throw new Error(\n \"Internal error: asking for totp to login but minimumAuthenticationClassLevel is higher than TWO_FACTOR_AUTHENTICATION's level.\"\n )\n const attempts: { secret: string; secretType: AuthSecretType }[] = []\n while (true) {\n const { secret, secretType } = await this.authSecretProvider.getSecret([AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN], attempts)\n if (secretType != AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN)\n throw new Error(`Was expecting a 2fa token but got a secret of type ${secretType}.`)\n attempts.push({ secret, secretType })\n const result = await this.doGetTokenWithSecret(`${password}|${secret}`, minimumAuthenticationClassLevel)\n if ('success' in result) {\n this.updateCachedSecret(password, AuthSecretType.PASSWORD)\n return result.success\n } else if (result.failure != DoGetTokenResultFailureReason.INVALID_2FA) {\n throw new Error(`Unexpected error while trying to login with (previously) valid password and 2fa token ${result.failure}.`)\n } // else retry\n }\n }\n\n private async doGetTokenWithSecret(secret: string, minimumAuthenticationClassLevel: number): Promise<DoGetTokenResult> {\n return this.authApi.login({ username: this.login, password: secret }, this.groupId).then(\n (authResult) => {\n const { token, refreshToken } = authResult\n if (!token || !refreshToken) throw new Error('Internal error: login succeeded but no token was returned. Unsupported backend version?')\n const claims = decodeJwtClaims(token)\n const authClassLevel = claims['tac']\n if (!authClassLevel || typeof authClassLevel !== 'number')\n throw new Error('Internal error: authClassLevel is not a number. Unsupported backend version?')\n if (authClassLevel < minimumAuthenticationClassLevel) {\n return { failure: DoGetTokenResultFailureReason.INVALID_AUTH_CLASS_LEVEL }\n } else {\n return { success: { token, refreshToken } }\n }\n },\n (error) => {\n if (!(error instanceof XHRError)) throw error\n if (error.statusCode == 401 || error.statusCode == 412) {\n // Password is wrong (401) or unacceptable (e.g. too short, 412)\n return { failure: DoGetTokenResultFailureReason.INVALID_PW_OR_TOKEN }\n } else if (error.statusCode == 406) {\n // Password is correct, but 2fa token is not\n return { failure: DoGetTokenResultFailureReason.INVALID_2FA }\n } else if (error.statusCode == 417) {\n // Password is correct, but the user has 2fa enabled and no 2fa token was provided\n return { failure: DoGetTokenResultFailureReason.NEEDS_2FA }\n } else throw error\n }\n )\n }\n\n async switchedGroup(newGroupId: string): Promise<TokenProvider> {\n const groupSwitchedTokens = this.cachedRefreshToken\n ? await this.authApi.switchGroup(this.cachedRefreshToken, newGroupId).then(\n (response) => {\n if (!response.token || !response.refreshToken)\n throw new Error('Internal error: group switch succeeded but no token was returned. Unsupported backend version?')\n return { token: response.token, refreshToken: response.refreshToken }\n },\n () => ({ token: undefined, refreshToken: undefined })\n )\n : { token: undefined, refreshToken: undefined }\n return new TokenProvider(\n this.login,\n newGroupId,\n this.currentLongLivedSecret ? { value: this.currentLongLivedSecret.value, type: undefined } : undefined,\n groupSwitchedTokens.token,\n groupSwitchedTokens.refreshToken,\n this.authApi,\n this.authSecretProvider\n )\n }\n\n private updateCachedSecret(secret: string, secretType: AuthSecretType) {\n if (secretType == AuthSecretType.LONG_LIVED_TOKEN || secretType == AuthSecretType.PASSWORD) {\n this.currentLongLivedSecret = { value: secret, type: ServerAuthenticationClass.LONG_LIVED_TOKEN }\n }\n }\n}\ntype DoGetTokenResult = { success: { token: string; refreshToken: string } } | { failure: DoGetTokenResultFailureReason }\nenum DoGetTokenResultFailureReason {\n NEEDS_2FA,\n INVALID_2FA,\n INVALID_PW_OR_TOKEN,\n INVALID_AUTH_CLASS_LEVEL,\n}\nenum RetrievedTokenType {\n CACHED,\n REFRESHED,\n NEW,\n}\n\nenum SmartAuthServiceState {\n INITIAL,\n DONE_INITIAL,\n REATTEMPT,\n REATTEMPTED_WITH_NEW_UNBOUND_TOKEN,\n REATTEMPTED_WITH_AUTH_CLASS_SPECIFIC_TOKEN,\n EXPECT_REQUEST_WITH_SPECIFIC_AUTH_CLASS,\n TERMINAL_ERROR,\n}\nclass SmartAuthService implements AuthService {\n private currentState:\n | { id: SmartAuthServiceState.INITIAL }\n | { id: SmartAuthServiceState.DONE_INITIAL; initialToken: string }\n | { id: SmartAuthServiceState.REATTEMPT; initialToken: string; initialError: Error }\n | { id: SmartAuthServiceState.REATTEMPTED_WITH_NEW_UNBOUND_TOKEN }\n | { id: SmartAuthServiceState.REATTEMPTED_WITH_AUTH_CLASS_SPECIFIC_TOKEN }\n | { id: SmartAuthServiceState.EXPECT_REQUEST_WITH_SPECIFIC_AUTH_CLASS; errorFromNewToken: Error }\n | { id: SmartAuthServiceState.TERMINAL_ERROR; error: Error } = { id: SmartAuthServiceState.INITIAL }\n\n constructor(private readonly tokenProvider: TokenProvider) {}\n\n async getAuthHeaders(minimumAuthenticationClassLevel: number | undefined): Promise<Array<XHR.Header>> {\n return [new XHR.Header('Authorization', `Bearer ${await this.getAuthToken(minimumAuthenticationClassLevel)}`)]\n }\n\n private async getAuthToken(minimumAuthenticationClassLevel: number | undefined): Promise<string> {\n switch (this.currentState.id) {\n case SmartAuthServiceState.INITIAL:\n if (minimumAuthenticationClassLevel != undefined) {\n throw new Error('Illegal state: cannot ask for a specific auth class level at the first request attempt.')\n } else {\n const { token } = await this.tokenProvider.getCachedOrRefreshedOrNewToken()\n this.currentState = { id: SmartAuthServiceState.DONE_INITIAL, initialToken: token }\n return token\n }\n case SmartAuthServiceState.REATTEMPT:\n if (minimumAuthenticationClassLevel != undefined) {\n const token = await this.tokenProvider.getNewTokenWithClass(minimumAuthenticationClassLevel)\n this.currentState = { id: SmartAuthServiceState.REATTEMPTED_WITH_AUTH_CLASS_SPECIFIC_TOKEN }\n return token\n } else {\n const { token } = await this.tokenProvider.getCachedOrRefreshedOrNewToken()\n if (token == this.currentState.initialToken) throw this.currentState.initialError\n this.currentState = { id: SmartAuthServiceState.REATTEMPTED_WITH_NEW_UNBOUND_TOKEN }\n return token\n }\n case SmartAuthServiceState.EXPECT_REQUEST_WITH_SPECIFIC_AUTH_CLASS:\n if (minimumAuthenticationClassLevel != undefined) {\n const token = await this.tokenProvider.getNewTokenWithClass(minimumAuthenticationClassLevel)\n this.currentState = { id: SmartAuthServiceState.REATTEMPTED_WITH_AUTH_CLASS_SPECIFIC_TOKEN }\n return token\n } else throw this.currentState.errorFromNewToken\n case SmartAuthServiceState.TERMINAL_ERROR:\n throw this.currentState.error\n default:\n throw new Error(`Illegal state: cannot get token in state ${this.currentState.id}.`)\n }\n }\n\n invalidateHeader(error: Error): void {\n switch (this.currentState.id) {\n case SmartAuthServiceState.DONE_INITIAL:\n this.currentState = { id: SmartAuthServiceState.REATTEMPT, initialToken: this.currentState.initialToken, initialError: error }\n break\n case SmartAuthServiceState.REATTEMPTED_WITH_NEW_UNBOUND_TOKEN:\n this.currentState = { id: SmartAuthServiceState.EXPECT_REQUEST_WITH_SPECIFIC_AUTH_CLASS, errorFromNewToken: error }\n break\n case SmartAuthServiceState.REATTEMPTED_WITH_AUTH_CLASS_SPECIFIC_TOKEN:\n this.currentState = { id: SmartAuthServiceState.TERMINAL_ERROR, error: error }\n break\n default:\n throw new Error(`Illegal state: cannot invalidate header in state ${this.currentState.id}.`)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"SmartAuthProvider.js","sourceRoot":"","sources":["../../../icc-x-api/auth/SmartAuthProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { AuthenticationProvider, NoAuthenticationProvider } from './AuthenticationProvider'\nimport { UserGroup } from '../../icc-api/model/UserGroup'\nimport { AuthService } from './AuthService'\nimport { IccAuthApi, OAuthThirdParty } from '../../icc-api'\nimport { XHR } from '../../icc-api/api/XHR'\nimport XHRError = XHR.XHRError\nimport { decodeJwtClaims, isJwtInvalidOrExpired } from './JwtUtils'\nimport { AuthenticationResponse } from '../../icc-api/model/AuthenticationResponse'\n\n/**\n * Needed by a {@link SmartAuthProvider} to get the secrets (password, token, etc.) for authentication to the iCure SDK as needed.\n */\nexport interface AuthSecretProvider {\n /**\n * Provides a secret for authentication to the iCure SDK.\n *\n * ## Accepted secrets\n *\n * The method will be provided with an array of the secrets types that are acceptable (`acceptedSecrets`). Usually this array will contain multiple\n * elements, but this depends on the group configuration, the user (if he has 2fa setup or not), or the operation being performed. For groups using\n * default configurations and for patients without 2fa enabled for example the array will always contain the {@link AuthSecretType.PASSWORD} element.\n * Usually the array contain also the {@link AuthSecretType.LONG_LIVED_TOKEN} element, but if the user is attempting to perform a sensitive operations\n * such as changing his password the default group configuration does not allow for the user to authenticate using a JWT obtained from a long-lived\n * token for this operation, meaning the array will not contain the {@link AuthSecretType.LONG_LIVED_TOKEN} element.\n *\n * Regardless of the number of elements in the array only one secret of the accepted types is sufficient for the operation to succeed.\n *\n * ## TWO_FACTOR_AUTHENTICATION_TOKEN secret type\n *\n * The {@link AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN} secret type is only used when the user has 2fa enabled. In this case the SDK will call\n * this method twice, once containing the {@link AuthSecretType.PASSWORD} element in the `acceptedSecrets` array, and if the provided secret is a\n * valid password the SDK will immediately call this method again, this time containing the {@link AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN}\n * instead of the {@link AuthSecretType.PASSWORD} element.\n *\n * Any future call to this method from the same provider instance will not contain the {@link AuthSecretType.PASSWORD} element anymore, as it is\n * cached, but it may contain the {@link AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN} element instead.\n *\n * Note that the 2fa token is not needed for logging in through a long-lived or short-lived token, it is only used in combination with a password.\n * If the user is using 2fa, and you get in input as `acceptedSecrets` an array `[PASSWORD, LONG_LIVED_TOKEN, SHORT_LIVED_TOKEN]`, and you pass to\n * authenticate a long-lived token, the SDK will not call this method again to ask for the 2fa token.\n *\n * @param acceptedSecrets the types of secrets that are acceptable for the operation being performed.\n * @param previousAttempts the secrets that were previously attempted by the SDK for this operation. This array will be empty the first time this\n * method is called for a given operation, but it may contain multiple elements if the SDK has already called this method multiple times because the\n * previously returned secrets were not valid. The first element is the first secret that was attempted, and the last element is the most recently\n * attempted.\n * @return a promise that resolves with the secret and the secret type to use for authentication. If the promise rejects then the ongoing SDK\n * operation will fail without being re-attempted.\n */\n getSecret(acceptedSecrets: AuthSecretType[], previousAttempts: AuthSecretDetails[]): Promise<AuthSecretDetails>\n}\n\n// We may want to add some onSuccess callback in future or similar\nexport type AuthSecretDetails =\n | { value: string; secretType: Exclude<AuthSecretType, AuthSecretType.EXTERNAL_AUTHENTICATION> }\n | { value: string; secretType: AuthSecretType.EXTERNAL_AUTHENTICATION; oauthType: OAuthThirdParty }\n\n/**\n * Represents a type of secret that can be used for authentication with iCure.\n */\nexport enum AuthSecretType {\n /**\n * Password chosen by the user.\n */\n PASSWORD = 'PASSWORD', // pragma: allowlist secret\n /**\n * Time based one time password provided by authenticator applications, generated on the basis of a timestamp and a shared secret between the iCure\n * server and the authenticator application.\n */\n TWO_FACTOR_AUTHENTICATION_TOKEN = 'TWO_FACTOR_AUTHENTICATION_TOKEN',\n /**\n * A short-lived iCure token, an internal authentication token that lasts 5 minutes or less. Unlike passwords these tokens usually are generated by\n * some component of iCure, and are not chosen by the user.\n */\n SHORT_LIVED_TOKEN = 'SHORT_LIVED_TOKEN',\n /**\n * A long-lived iCure token, an internal authentication token that lasts longer than 5 minutes. Unlike passwords these tokens usually are generated\n * by some component of iCure, and are not chosen by the user.\n */\n LONG_LIVED_TOKEN = 'LONG_LIVED_TOKEN',\n /**\n * A token provided by an external authentication provider (e.g. Oauth/Google).\n * Not yet in use.\n */\n EXTERNAL_AUTHENTICATION = 'EXTERNAL_AUTHENTICATION',\n /**\n * A special case of external authentication where the provider is a digital identity provider.\n * Not yet in use.\n */\n // DIGITAL_ID = 'DIGITAL_ID',\n}\n\n// Here starts internal entities that should not be used directly.\n\n/**\n * @internal this class is meant for internal use only and may be changed without notice. The SmartAuthProvider will be initialised automatically\n * by the iCure api depending on the authentication options you provide.\n *\n * An authentication provider that automatically requests secrets for authentication as needed.\n *\n * This authentication provider can be initialised already with some secrets or tokens, and the provider will cache them and use them as needed for\n * as long as they remain valid. If at any point however the provider needs an updated secret or a secret of a different kind it will automatically\n * request this to the {@link SmartAuthProvider} to get the secret.\n *\n * An advantage of using this provider over others is that in case all the cached tokens and secrets were to expire while performing a request,\n * instead of having the request fail the provider will ask for new secrets from the {@link SmartAuthProvider} and the request will automatically\n * be retried with the new secret. Additionally, the provider may request updated secrets also for performing some sensitive operations (e.g. changing\n * password of the user) even if the cached tokens and/or did not expire. This could be the case for example if the cached secret is a long-lived\n * token, but in order to change the password the user needs to provide his current password.\n *\n * Note that in this context the cache of secrets and token is in memory only, and is not persisted in any way. Different instances of this provider\n * will not share the same cache.\n *\n */\nexport class SmartAuthProvider implements AuthenticationProvider {\n /**\n * Initialises a {@link SmartAuthProvider}.\n * @param authApi an \"anonymous\" {@link IccAuthApi} to use for authentication.\n * @param login\n * @param secretProvider\n * @param props optional initialisation properties.\n */\n static initialise(\n authApi: IccAuthApi,\n login: string,\n secretProvider: AuthSecretProvider,\n props: {\n initialSecret?: { plainSecret: string } | { oauthToken: string; oauthType: OAuthThirdParty }\n initialAuthToken?: string\n initialRefreshToken?: string\n loginGroupId?: string\n } = {}\n ): SmartAuthProvider {\n let initialSecret: CachedSecretType | undefined = undefined\n if (props.initialSecret) {\n if ('plainSecret' in props.initialSecret) {\n initialSecret = { value: props.initialSecret.plainSecret, type: undefined }\n } else {\n initialSecret = {\n value: props.initialSecret.oauthToken,\n type: ServerAuthenticationClass.EXTERNAL_AUTHENTICATION,\n oauthType: props.initialSecret.oauthType,\n }\n }\n }\n return new SmartAuthProvider(\n new TokenProvider(login, props.loginGroupId, initialSecret, props.initialAuthToken, props.initialRefreshToken, authApi, secretProvider),\n props.loginGroupId\n )\n }\n\n private constructor(private readonly tokenProvider: TokenProvider, private readonly groupId: string | undefined) {}\n\n getAuthService(): AuthService {\n return new SmartAuthService(this.tokenProvider)\n }\n\n async switchGroup(newGroupId: string, matches: Array<UserGroup>): Promise<{ switchedProvider: AuthenticationProvider; isGroupLocked: boolean }> {\n if (newGroupId == this.groupId) return { switchedProvider: this, isGroupLocked: false }\n if (!matches.find((match) => match.groupId == newGroupId)) throw new Error('New group id not found in matches.')\n const switchedProvider = await this.tokenProvider.switchedGroup(newGroupId)\n return { switchedProvider: new SmartAuthProvider(switchedProvider, this.groupId), isGroupLocked: false }\n }\n\n getIcureTokens(): Promise<{ token: string; refreshToken: string } | undefined> {\n return Promise.resolve(undefined)\n }\n}\n\nenum ServerAuthenticationClass {\n // DIGITAL_ID = 60,\n TWO_FACTOR_AUTHENTICATION = 50,\n SHORT_LIVED_TOKEN = 40,\n EXTERNAL_AUTHENTICATION = 30,\n PASSWORD = 20,\n LONG_LIVED_TOKEN = 10,\n}\n// Secrets lasting more than 5 minutes -> makes sense to reuse them to get an elevated security jwt\ntype LongLivedSecretType = ServerAuthenticationClass.LONG_LIVED_TOKEN | ServerAuthenticationClass.PASSWORD\ntype CachedSecretType =\n | { value: string; type: LongLivedSecretType | undefined }\n | { value: string; type: ServerAuthenticationClass.EXTERNAL_AUTHENTICATION; oauthType: OAuthThirdParty }\n// In some providers Oauth tokens may have short duration or may be usable only once. We only want to cache them if they are going to be reusable and\n// if they last more than 5 minutes.\nconst longLivedOAuthTokens = new Set([OAuthThirdParty.GOOGLE])\nclass TokenProvider {\n constructor(\n private login: string,\n private groupId: string | undefined,\n private currentLongLivedSecret: CachedSecretType | undefined,\n private cachedToken: string | undefined,\n private cachedRefreshToken: string | undefined,\n private readonly authApi: IccAuthApi,\n private readonly authSecretProvider: AuthSecretProvider\n ) {}\n\n async getCachedOrRefreshedOrNewToken(): Promise<{ token: string; type: RetrievedTokenType }> {\n if (!!this.cachedToken && !isJwtInvalidOrExpired(this.cachedToken)) {\n return { token: this.cachedToken, type: RetrievedTokenType.CACHED }\n } else if (!!this.cachedRefreshToken && !isJwtInvalidOrExpired(this.cachedRefreshToken)) {\n return this.refreshAndCacheToken(this.cachedRefreshToken)\n } else {\n return { token: await this.getAndCacheNewToken(undefined), type: RetrievedTokenType.NEW }\n }\n }\n\n async getNewTokenWithClass(minimumAuthenticationClass: number): Promise<string> {\n return await this.getAndCacheNewToken(minimumAuthenticationClass)\n }\n\n private async getAndCacheNewToken(minimumAuthenticationClassLevel: number | undefined): Promise<string> {\n const { token, refreshToken } = await this.getNewToken(minimumAuthenticationClassLevel ?? 0)\n this.cachedToken = token\n this.cachedRefreshToken = refreshToken\n return token\n }\n\n private async refreshAndCacheToken(refreshToken: string): Promise<{ token: string; type: RetrievedTokenType }> {\n return await this.authApi.refreshAuthenticationJWT(refreshToken).then(\n (authResult) => {\n if (!authResult.token) throw new Error('Internal error: refresh succeeded but no token was returned. Unsupported backend version?')\n this.cachedToken = authResult.token\n return { token: authResult.token, type: RetrievedTokenType.REFRESHED }\n },\n async () => ({ token: await this.getAndCacheNewToken(undefined), type: RetrievedTokenType.NEW })\n )\n }\n\n private async getNewToken(minimumAuthenticationClassLevel: number): Promise<{ token: string; refreshToken: string }> {\n if (!!this.currentLongLivedSecret && (!this.currentLongLivedSecret.type || this.currentLongLivedSecret.type >= minimumAuthenticationClassLevel)) {\n const resultWithCachedSecret = await this.doGetTokenWithSecret(this.currentLongLivedSecret, minimumAuthenticationClassLevel)\n if ('success' in resultWithCachedSecret) {\n return resultWithCachedSecret.success\n } else if (\n resultWithCachedSecret.failure === DoGetTokenResultFailureReason.NEEDS_2FA &&\n minimumAuthenticationClassLevel <= ServerAuthenticationClass.TWO_FACTOR_AUTHENTICATION\n ) {\n return this.askTotpAndGetToken(this.currentLongLivedSecret.value, minimumAuthenticationClassLevel)\n } else return this.askSecretAndGetToken(minimumAuthenticationClassLevel, true)\n } else {\n return this.askSecretAndGetToken(minimumAuthenticationClassLevel, true)\n }\n }\n\n private async askSecretAndGetToken(\n minimumAuthenticationClassLevel: number,\n passwordIsValidAs2fa: boolean\n ): Promise<{ token: string; refreshToken: string }> {\n const acceptedSecrets = [\n minimumAuthenticationClassLevel <= ServerAuthenticationClass.LONG_LIVED_TOKEN ? [AuthSecretType.LONG_LIVED_TOKEN] : [],\n minimumAuthenticationClassLevel <= ServerAuthenticationClass.SHORT_LIVED_TOKEN ? [AuthSecretType.SHORT_LIVED_TOKEN] : [],\n minimumAuthenticationClassLevel <= ServerAuthenticationClass.TWO_FACTOR_AUTHENTICATION &&\n (passwordIsValidAs2fa || minimumAuthenticationClassLevel <= ServerAuthenticationClass.PASSWORD)\n ? [AuthSecretType.PASSWORD]\n : [],\n ].flat()\n if (!acceptedSecrets.length)\n throw new Error('Internal error: no secret type is accepted for this request. Group may be misconfigured, or client may be outdated.')\n const attempts: AuthSecretDetails[] = []\n while (true) {\n const secretDetails = await this.authSecretProvider.getSecret([...acceptedSecrets], attempts)\n if (!acceptedSecrets.includes(secretDetails.secretType))\n throw new Error(`Accepted secret types are ${JSON.stringify(acceptedSecrets)}, but got a secret of type ${secretDetails.secretType}.`)\n attempts.push(secretDetails)\n const result = await this.doGetTokenWithSecret(secretDetails, minimumAuthenticationClassLevel)\n if ('success' in result) {\n this.updateCachedSecret(secretDetails)\n return result.success\n } else if (result.failure == DoGetTokenResultFailureReason.NEEDS_2FA) {\n return this.askTotpAndGetToken(secretDetails.value, minimumAuthenticationClassLevel)\n } else if (secretDetails.value == AuthSecretType.PASSWORD && result.failure == DoGetTokenResultFailureReason.INVALID_AUTH_CLASS_LEVEL) {\n // If we tried a password, and it turns out that the user has 2fa not enabled next time we don't consider password valid\n return this.askSecretAndGetToken(minimumAuthenticationClassLevel, false)\n } // else retry\n }\n }\n\n private async askTotpAndGetToken(password: string, minimumAuthenticationClassLevel: number): Promise<{ token: string; refreshToken: string }> {\n if (minimumAuthenticationClassLevel > ServerAuthenticationClass.TWO_FACTOR_AUTHENTICATION)\n throw new Error(\n \"Internal error: asking for totp to login but minimumAuthenticationClassLevel is higher than TWO_FACTOR_AUTHENTICATION's level.\"\n )\n const attempts: AuthSecretDetails[] = []\n while (true) {\n const details = await this.authSecretProvider.getSecret([AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN], attempts)\n if (details.secretType != AuthSecretType.TWO_FACTOR_AUTHENTICATION_TOKEN)\n throw new Error(`Was expecting a 2fa token but got a secret of type ${details.secretType}.`)\n attempts.push(details)\n const result = await this.doGetTokenWithSecret({ value: `${password}|${details.value}` }, minimumAuthenticationClassLevel)\n if ('success' in result) {\n this.updateCachedSecret({ value: password, secretType: AuthSecretType.PASSWORD })\n return result.success\n } else if (result.failure != DoGetTokenResultFailureReason.INVALID_2FA) {\n throw new Error(`Unexpected error while trying to login with (previously) valid password and 2fa token ${result.failure}.`)\n } // else retry\n }\n }\n\n private async doGetTokenWithSecret(\n secret: { value: string; oauthType?: OAuthThirdParty },\n minimumAuthenticationClassLevel: number\n ): Promise<DoGetTokenResult> {\n let authResultPromise: Promise<AuthenticationResponse>\n if ('oauthType' in secret && !!secret.oauthType) {\n authResultPromise = this.authApi.loginWithThirdPartyToken(secret.oauthType, secret.value)\n } else {\n authResultPromise = this.authApi.login({ username: this.login, password: secret.value }, this.groupId)\n }\n return authResultPromise.then(\n (authResult) => {\n const { token, refreshToken } = authResult\n if (!token || !refreshToken) throw new Error('Internal error: login succeeded but no token was returned. Unsupported backend version?')\n const claims = decodeJwtClaims(token)\n const authClassLevel = claims['tac']\n if (!authClassLevel || typeof authClassLevel !== 'number')\n throw new Error('Internal error: authClassLevel is not a number. Unsupported backend version?')\n if (authClassLevel < minimumAuthenticationClassLevel) {\n return { failure: DoGetTokenResultFailureReason.INVALID_AUTH_CLASS_LEVEL }\n } else {\n return { success: { token, refreshToken } }\n }\n },\n (error) => {\n if (!(error instanceof XHRError)) throw error\n if (error.statusCode == 401 || error.statusCode == 412) {\n // Password is wrong (401) or unacceptable (e.g. too short, 412)\n return { failure: DoGetTokenResultFailureReason.INVALID_PW_OR_TOKEN }\n } else if (error.statusCode == 406) {\n // Password is correct, but 2fa token is not\n return { failure: DoGetTokenResultFailureReason.INVALID_2FA }\n } else if (error.statusCode == 417) {\n // Password is correct, but the user has 2fa enabled and no 2fa token was provided\n return { failure: DoGetTokenResultFailureReason.NEEDS_2FA }\n } else throw error\n }\n )\n }\n\n async switchedGroup(newGroupId: string): Promise<TokenProvider> {\n const groupSwitchedTokens = this.cachedRefreshToken\n ? await this.authApi.switchGroup(this.cachedRefreshToken, newGroupId).then(\n (response) => {\n if (!response.token || !response.refreshToken)\n throw new Error('Internal error: group switch succeeded but no token was returned. Unsupported backend version?')\n return { token: response.token, refreshToken: response.refreshToken }\n },\n () => ({ token: undefined, refreshToken: undefined })\n )\n : { token: undefined, refreshToken: undefined }\n return new TokenProvider(\n this.login,\n newGroupId,\n this.currentLongLivedSecret ? { value: this.currentLongLivedSecret.value, type: undefined } : undefined,\n groupSwitchedTokens.token,\n groupSwitchedTokens.refreshToken,\n this.authApi,\n this.authSecretProvider\n )\n }\n\n private updateCachedSecret(details: AuthSecretDetails) {\n switch (details.secretType) {\n case AuthSecretType.PASSWORD:\n this.currentLongLivedSecret = { value: details.value, type: ServerAuthenticationClass.PASSWORD }\n break\n case AuthSecretType.LONG_LIVED_TOKEN:\n this.currentLongLivedSecret = { value: details.value, type: ServerAuthenticationClass.LONG_LIVED_TOKEN }\n break\n case AuthSecretType.EXTERNAL_AUTHENTICATION:\n if (longLivedOAuthTokens.has(details.oauthType)) {\n this.currentLongLivedSecret = {\n value: details.value,\n type: ServerAuthenticationClass.EXTERNAL_AUTHENTICATION,\n oauthType: details.oauthType,\n }\n }\n break\n }\n }\n}\ntype DoGetTokenResult = { success: { token: string; refreshToken: string } } | { failure: DoGetTokenResultFailureReason }\nenum DoGetTokenResultFailureReason {\n NEEDS_2FA,\n INVALID_2FA,\n INVALID_PW_OR_TOKEN,\n INVALID_AUTH_CLASS_LEVEL,\n}\nenum RetrievedTokenType {\n CACHED,\n REFRESHED,\n NEW,\n}\n\nenum SmartAuthServiceState {\n INITIAL,\n DONE_INITIAL,\n REATTEMPT,\n REATTEMPTED_WITH_NEW_UNBOUND_TOKEN,\n REATTEMPTED_WITH_AUTH_CLASS_SPECIFIC_TOKEN,\n EXPECT_REQUEST_WITH_SPECIFIC_AUTH_CLASS,\n TERMINAL_ERROR,\n}\nclass SmartAuthService implements AuthService {\n private currentState:\n | { id: SmartAuthServiceState.INITIAL }\n | { id: SmartAuthServiceState.DONE_INITIAL; initialToken: string }\n | { id: SmartAuthServiceState.REATTEMPT; initialToken: string; initialError: Error }\n | { id: SmartAuthServiceState.REATTEMPTED_WITH_NEW_UNBOUND_TOKEN }\n | { id: SmartAuthServiceState.REATTEMPTED_WITH_AUTH_CLASS_SPECIFIC_TOKEN }\n | { id: SmartAuthServiceState.EXPECT_REQUEST_WITH_SPECIFIC_AUTH_CLASS; errorFromNewToken: Error }\n | { id: SmartAuthServiceState.TERMINAL_ERROR; error: Error } = { id: SmartAuthServiceState.INITIAL }\n\n constructor(private readonly tokenProvider: TokenProvider) {}\n\n async getAuthHeaders(minimumAuthenticationClassLevel: number | undefined): Promise<Array<XHR.Header>> {\n return [new XHR.Header('Authorization', `Bearer ${await this.getAuthToken(minimumAuthenticationClassLevel)}`)]\n }\n\n private async getAuthToken(minimumAuthenticationClassLevel: number | undefined): Promise<string> {\n switch (this.currentState.id) {\n case SmartAuthServiceState.INITIAL:\n if (minimumAuthenticationClassLevel != undefined) {\n throw new Error('Illegal state: cannot ask for a specific auth class level at the first request attempt.')\n } else {\n const { token } = await this.tokenProvider.getCachedOrRefreshedOrNewToken()\n this.currentState = { id: SmartAuthServiceState.DONE_INITIAL, initialToken: token }\n return token\n }\n case SmartAuthServiceState.REATTEMPT:\n if (minimumAuthenticationClassLevel != undefined) {\n const token = await this.tokenProvider.getNewTokenWithClass(minimumAuthenticationClassLevel)\n this.currentState = { id: SmartAuthServiceState.REATTEMPTED_WITH_AUTH_CLASS_SPECIFIC_TOKEN }\n return token\n } else {\n const { token } = await this.tokenProvider.getCachedOrRefreshedOrNewToken()\n if (token == this.currentState.initialToken) throw this.currentState.initialError\n this.currentState = { id: SmartAuthServiceState.REATTEMPTED_WITH_NEW_UNBOUND_TOKEN }\n return token\n }\n case SmartAuthServiceState.EXPECT_REQUEST_WITH_SPECIFIC_AUTH_CLASS:\n if (minimumAuthenticationClassLevel != undefined) {\n const token = await this.tokenProvider.getNewTokenWithClass(minimumAuthenticationClassLevel)\n this.currentState = { id: SmartAuthServiceState.REATTEMPTED_WITH_AUTH_CLASS_SPECIFIC_TOKEN }\n return token\n } else throw this.currentState.errorFromNewToken\n case SmartAuthServiceState.TERMINAL_ERROR:\n throw this.currentState.error\n default:\n throw new Error(`Illegal state: cannot get token in state ${this.currentState.id}.`)\n }\n }\n\n invalidateHeader(error: Error): void {\n switch (this.currentState.id) {\n case SmartAuthServiceState.DONE_INITIAL:\n this.currentState = { id: SmartAuthServiceState.REATTEMPT, initialToken: this.currentState.initialToken, initialError: error }\n break\n case SmartAuthServiceState.REATTEMPTED_WITH_NEW_UNBOUND_TOKEN:\n this.currentState = { id: SmartAuthServiceState.EXPECT_REQUEST_WITH_SPECIFIC_AUTH_CLASS, errorFromNewToken: error }\n break\n case SmartAuthServiceState.REATTEMPTED_WITH_AUTH_CLASS_SPECIFIC_TOKEN:\n this.currentState = { id: SmartAuthServiceState.TERMINAL_ERROR, error: error }\n break\n default:\n throw new Error(`Illegal state: cannot invalidate header in state ${this.currentState.id}.`)\n }\n }\n}\n"]}