@jbrowse/plugin-authentication 2.2.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/LICENSE +201 -0
  2. package/dist/DropboxOAuthModel/configSchema.d.ts +5 -0
  3. package/dist/DropboxOAuthModel/configSchema.js +69 -0
  4. package/dist/DropboxOAuthModel/configSchema.js.map +1 -0
  5. package/dist/DropboxOAuthModel/index.d.ts +2 -0
  6. package/dist/DropboxOAuthModel/index.js +11 -0
  7. package/dist/DropboxOAuthModel/index.js.map +1 -0
  8. package/dist/DropboxOAuthModel/model.d.ts +98 -0
  9. package/dist/DropboxOAuthModel/model.js +103 -0
  10. package/dist/DropboxOAuthModel/model.js.map +1 -0
  11. package/dist/ExternalTokenModel/ExternalTokenEntryForm.d.ts +5 -0
  12. package/dist/ExternalTokenModel/ExternalTokenEntryForm.js +59 -0
  13. package/dist/ExternalTokenModel/ExternalTokenEntryForm.js.map +1 -0
  14. package/dist/ExternalTokenModel/configSchema.d.ts +5 -0
  15. package/dist/ExternalTokenModel/configSchema.js +26 -0
  16. package/dist/ExternalTokenModel/configSchema.js.map +1 -0
  17. package/dist/ExternalTokenModel/index.d.ts +2 -0
  18. package/dist/ExternalTokenModel/index.js +11 -0
  19. package/dist/ExternalTokenModel/index.js.map +1 -0
  20. package/dist/ExternalTokenModel/model.d.ts +67 -0
  21. package/dist/ExternalTokenModel/model.js +59 -0
  22. package/dist/ExternalTokenModel/model.js.map +1 -0
  23. package/dist/GoogleDriveOAuthModel/configSchema.d.ts +5 -0
  24. package/dist/GoogleDriveOAuthModel/configSchema.js +53 -0
  25. package/dist/GoogleDriveOAuthModel/configSchema.js.map +1 -0
  26. package/dist/GoogleDriveOAuthModel/index.d.ts +2 -0
  27. package/dist/GoogleDriveOAuthModel/index.js +11 -0
  28. package/dist/GoogleDriveOAuthModel/index.js.map +1 -0
  29. package/dist/GoogleDriveOAuthModel/model.d.ts +111 -0
  30. package/dist/GoogleDriveOAuthModel/model.js +115 -0
  31. package/dist/GoogleDriveOAuthModel/model.js.map +1 -0
  32. package/dist/HTTPBasicModel/HTTPBasicLoginForm.d.ts +5 -0
  33. package/dist/HTTPBasicModel/HTTPBasicLoginForm.js +55 -0
  34. package/dist/HTTPBasicModel/HTTPBasicLoginForm.js.map +1 -0
  35. package/dist/HTTPBasicModel/configSchema.d.ts +5 -0
  36. package/dist/HTTPBasicModel/configSchema.js +34 -0
  37. package/dist/HTTPBasicModel/configSchema.js.map +1 -0
  38. package/dist/HTTPBasicModel/index.d.ts +2 -0
  39. package/dist/HTTPBasicModel/index.js +11 -0
  40. package/dist/HTTPBasicModel/index.js.map +1 -0
  41. package/dist/HTTPBasicModel/model.d.ts +67 -0
  42. package/dist/HTTPBasicModel/model.js +59 -0
  43. package/dist/HTTPBasicModel/model.js.map +1 -0
  44. package/dist/OAuthModel/configSchema.d.ts +5 -0
  45. package/dist/OAuthModel/configSchema.js +90 -0
  46. package/dist/OAuthModel/configSchema.js.map +1 -0
  47. package/dist/OAuthModel/index.d.ts +2 -0
  48. package/dist/OAuthModel/index.js +11 -0
  49. package/dist/OAuthModel/index.js.map +1 -0
  50. package/dist/OAuthModel/model.d.ts +91 -0
  51. package/dist/OAuthModel/model.js +317 -0
  52. package/dist/OAuthModel/model.js.map +1 -0
  53. package/dist/index.d.ts +399 -0
  54. package/dist/index.js +80 -0
  55. package/dist/index.js.map +1 -0
  56. package/esm/DropboxOAuthModel/configSchema.d.ts +5 -0
  57. package/esm/DropboxOAuthModel/configSchema.js +64 -0
  58. package/esm/DropboxOAuthModel/configSchema.js.map +1 -0
  59. package/esm/DropboxOAuthModel/index.d.ts +2 -0
  60. package/esm/DropboxOAuthModel/index.js +3 -0
  61. package/esm/DropboxOAuthModel/index.js.map +1 -0
  62. package/esm/DropboxOAuthModel/model.d.ts +98 -0
  63. package/esm/DropboxOAuthModel/model.js +96 -0
  64. package/esm/DropboxOAuthModel/model.js.map +1 -0
  65. package/esm/ExternalTokenModel/ExternalTokenEntryForm.d.ts +5 -0
  66. package/esm/ExternalTokenModel/ExternalTokenEntryForm.js +29 -0
  67. package/esm/ExternalTokenModel/ExternalTokenEntryForm.js.map +1 -0
  68. package/esm/ExternalTokenModel/configSchema.d.ts +5 -0
  69. package/esm/ExternalTokenModel/configSchema.js +24 -0
  70. package/esm/ExternalTokenModel/configSchema.js.map +1 -0
  71. package/esm/ExternalTokenModel/index.d.ts +2 -0
  72. package/esm/ExternalTokenModel/index.js +3 -0
  73. package/esm/ExternalTokenModel/index.js.map +1 -0
  74. package/esm/ExternalTokenModel/model.d.ts +67 -0
  75. package/esm/ExternalTokenModel/model.js +57 -0
  76. package/esm/ExternalTokenModel/model.js.map +1 -0
  77. package/esm/GoogleDriveOAuthModel/configSchema.d.ts +5 -0
  78. package/esm/GoogleDriveOAuthModel/configSchema.js +48 -0
  79. package/esm/GoogleDriveOAuthModel/configSchema.js.map +1 -0
  80. package/esm/GoogleDriveOAuthModel/index.d.ts +2 -0
  81. package/esm/GoogleDriveOAuthModel/index.js +3 -0
  82. package/esm/GoogleDriveOAuthModel/index.js.map +1 -0
  83. package/esm/GoogleDriveOAuthModel/model.d.ts +111 -0
  84. package/esm/GoogleDriveOAuthModel/model.js +108 -0
  85. package/esm/GoogleDriveOAuthModel/model.js.map +1 -0
  86. package/esm/HTTPBasicModel/HTTPBasicLoginForm.d.ts +5 -0
  87. package/esm/HTTPBasicModel/HTTPBasicLoginForm.js +28 -0
  88. package/esm/HTTPBasicModel/HTTPBasicLoginForm.js.map +1 -0
  89. package/esm/HTTPBasicModel/configSchema.d.ts +5 -0
  90. package/esm/HTTPBasicModel/configSchema.js +32 -0
  91. package/esm/HTTPBasicModel/configSchema.js.map +1 -0
  92. package/esm/HTTPBasicModel/index.d.ts +2 -0
  93. package/esm/HTTPBasicModel/index.js +3 -0
  94. package/esm/HTTPBasicModel/index.js.map +1 -0
  95. package/esm/HTTPBasicModel/model.d.ts +67 -0
  96. package/esm/HTTPBasicModel/model.js +57 -0
  97. package/esm/HTTPBasicModel/model.js.map +1 -0
  98. package/esm/OAuthModel/configSchema.d.ts +5 -0
  99. package/esm/OAuthModel/configSchema.js +88 -0
  100. package/esm/OAuthModel/configSchema.js.map +1 -0
  101. package/esm/OAuthModel/index.d.ts +2 -0
  102. package/esm/OAuthModel/index.js +3 -0
  103. package/esm/OAuthModel/index.js.map +1 -0
  104. package/esm/OAuthModel/model.d.ts +91 -0
  105. package/esm/OAuthModel/model.js +289 -0
  106. package/esm/OAuthModel/model.js.map +1 -0
  107. package/esm/index.d.ts +399 -0
  108. package/esm/index.js +64 -0
  109. package/esm/index.js.map +1 -0
  110. package/package.json +63 -0
  111. package/src/DropboxOAuthModel/configSchema.ts +77 -0
  112. package/src/DropboxOAuthModel/index.ts +2 -0
  113. package/src/DropboxOAuthModel/model.tsx +141 -0
  114. package/src/ExternalTokenModel/ExternalTokenEntryForm.tsx +61 -0
  115. package/src/ExternalTokenModel/configSchema.ts +36 -0
  116. package/src/ExternalTokenModel/index.ts +2 -0
  117. package/src/ExternalTokenModel/model.tsx +70 -0
  118. package/src/GoogleDriveOAuthModel/configSchema.ts +61 -0
  119. package/src/GoogleDriveOAuthModel/index.ts +2 -0
  120. package/src/GoogleDriveOAuthModel/model.tsx +174 -0
  121. package/src/HTTPBasicModel/HTTPBasicLoginForm.tsx +71 -0
  122. package/src/HTTPBasicModel/configSchema.ts +43 -0
  123. package/src/HTTPBasicModel/index.ts +2 -0
  124. package/src/HTTPBasicModel/model.tsx +70 -0
  125. package/src/OAuthModel/configSchema.ts +98 -0
  126. package/src/OAuthModel/index.ts +2 -0
  127. package/src/OAuthModel/model.tsx +357 -0
  128. package/src/__snapshots__/index.test.js.snap +8 -0
  129. package/src/index.test.js +96 -0
  130. package/src/index.ts +97 -0
@@ -0,0 +1,67 @@
1
+ /// <reference types="react" />
2
+ import { UriLocation } from '@jbrowse/core/util/types';
3
+ import { HTTPBasicInternetAccountConfigModel } from './configSchema';
4
+ import { Instance } from 'mobx-state-tree';
5
+ declare const stateModelFactory: (configSchema: HTTPBasicInternetAccountConfigModel) => import("mobx-state-tree").IModelType<{
6
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
7
+ type: import("mobx-state-tree").ISimpleType<string>;
8
+ } & {
9
+ type: import("mobx-state-tree").ISimpleType<"HTTPBasicInternetAccount">;
10
+ configuration: import("mobx-state-tree").ITypeUnion<any, any, any>;
11
+ }, {
12
+ readonly name: string;
13
+ readonly description: string;
14
+ readonly internetAccountId: string;
15
+ readonly authHeader: string;
16
+ readonly tokenType: string;
17
+ readonly domains: string[];
18
+ readonly toggleContents: import("react").ReactNode;
19
+ readonly SelectorComponent: import("@jbrowse/core/util/types").AnyReactComponentType | undefined;
20
+ readonly selectorLabel: string | undefined;
21
+ } & {
22
+ handlesLocation(location: UriLocation): boolean;
23
+ readonly tokenKey: string;
24
+ } & {
25
+ getTokenFromUser(resolve: (token: string) => void, reject: (error: Error) => void): void;
26
+ storeToken(token: string): void;
27
+ removeToken(): void;
28
+ retrieveToken(): string | null;
29
+ validateToken(token: string, location: UriLocation): Promise<string>;
30
+ } & {
31
+ getToken(location?: UriLocation | undefined): Promise<string>;
32
+ } & {
33
+ addAuthHeaderToInit(init: RequestInit | undefined, token: string): {
34
+ headers: Headers;
35
+ body?: BodyInit | null | undefined;
36
+ cache?: RequestCache | undefined;
37
+ credentials?: RequestCredentials | undefined;
38
+ integrity?: string | undefined;
39
+ keepalive?: boolean | undefined;
40
+ method?: string | undefined;
41
+ mode?: RequestMode | undefined;
42
+ redirect?: RequestRedirect | undefined;
43
+ referrer?: string | undefined;
44
+ referrerPolicy?: ReferrerPolicy | undefined;
45
+ signal?: AbortSignal | null | undefined;
46
+ window?: null | undefined;
47
+ };
48
+ getPreAuthorizationInformation(location: UriLocation): Promise<{
49
+ internetAccountType: string;
50
+ authInfo: {
51
+ token: string;
52
+ configuration: any;
53
+ };
54
+ }>;
55
+ } & {
56
+ getFetcher(location?: UriLocation | undefined): (input: RequestInfo, init?: RequestInit | undefined) => Promise<Response>;
57
+ } & {
58
+ openLocation(location: UriLocation): import("@jbrowse/core/util/io").RemoteFileWithRangeCache;
59
+ } & {
60
+ readonly validateWithHEAD: boolean;
61
+ } & {
62
+ getTokenFromUser(resolve: (token: string) => void, reject: (error: Error) => void): void;
63
+ validateToken(token: string, location: UriLocation): Promise<string>;
64
+ }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
65
+ export default stateModelFactory;
66
+ export declare type HTTPBasicStateModel = ReturnType<typeof stateModelFactory>;
67
+ export declare type HTTPBasicModel = Instance<HTTPBasicStateModel>;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const configuration_1 = require("@jbrowse/core/configuration");
4
+ const models_1 = require("@jbrowse/core/pluggableElementTypes/models");
5
+ const mobx_state_tree_1 = require("mobx-state-tree");
6
+ const HTTPBasicLoginForm_1 = require("./HTTPBasicLoginForm");
7
+ const stateModelFactory = (configSchema) => {
8
+ return models_1.InternetAccount.named('HTTPBasicInternetAccount')
9
+ .props({
10
+ type: mobx_state_tree_1.types.literal('HTTPBasicInternetAccount'),
11
+ configuration: (0, configuration_1.ConfigurationReference)(configSchema),
12
+ })
13
+ .views(self => ({
14
+ get validateWithHEAD() {
15
+ return (0, configuration_1.getConf)(self, 'validateWithHEAD');
16
+ },
17
+ }))
18
+ .actions(self => ({
19
+ getTokenFromUser(resolve, reject) {
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ const { session } = (0, mobx_state_tree_1.getRoot)(self);
22
+ session.queueDialog((doneCallback) => [
23
+ HTTPBasicLoginForm_1.HTTPBasicLoginForm,
24
+ {
25
+ internetAccountId: self.internetAccountId,
26
+ handleClose: (token) => {
27
+ if (token) {
28
+ resolve(token);
29
+ }
30
+ else {
31
+ reject(new Error('user cancelled entry'));
32
+ }
33
+ doneCallback();
34
+ },
35
+ },
36
+ ]);
37
+ },
38
+ async validateToken(token, location) {
39
+ if (!self.validateWithHEAD) {
40
+ return token;
41
+ }
42
+ const newInit = self.addAuthHeaderToInit({ method: 'HEAD' }, token);
43
+ const response = await fetch(location.uri, newInit);
44
+ if (!response.ok) {
45
+ let errorMessage;
46
+ try {
47
+ errorMessage = await response.text();
48
+ }
49
+ catch (error) {
50
+ errorMessage = '';
51
+ }
52
+ throw new Error(`Error validating token — ${response.status} (${response.statusText})${errorMessage ? ` (${errorMessage})` : ''}`);
53
+ }
54
+ return token;
55
+ },
56
+ }));
57
+ };
58
+ exports.default = stateModelFactory;
59
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/HTTPBasicModel/model.tsx"],"names":[],"mappings":";;AAAA,+DAA6E;AAC7E,uEAA4E;AAG5E,qDAA0D;AAE1D,6DAAyD;AAEzD,MAAM,iBAAiB,GAAG,CACxB,YAAiD,EACjD,EAAE;IACF,OAAO,wBAAe,CAAC,KAAK,CAAC,0BAA0B,CAAC;SACrD,KAAK,CAAC;QACL,IAAI,EAAE,uBAAK,CAAC,OAAO,CAAC,0BAA0B,CAAC;QAC/C,aAAa,EAAE,IAAA,sCAAsB,EAAC,YAAY,CAAC;KACpD,CAAC;SACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACd,IAAI,gBAAgB;YAClB,OAAO,IAAA,uBAAO,EAAC,IAAI,EAAE,kBAAkB,CAAC,CAAA;QAC1C,CAAC;KACF,CAAC,CAAC;SACF,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,gBAAgB,CACd,OAAgC,EAChC,MAA8B;YAE9B,8DAA8D;YAC9D,MAAM,EAAE,OAAO,EAAE,GAAG,IAAA,yBAAO,EAAM,IAAI,CAAC,CAAA;YACtC,OAAO,CAAC,WAAW,CAAC,CAAC,YAAwB,EAAE,EAAE,CAAC;gBAChD,uCAAkB;gBAClB;oBACE,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;oBACzC,WAAW,EAAE,CAAC,KAAa,EAAE,EAAE;wBAC7B,IAAI,KAAK,EAAE;4BACT,OAAO,CAAC,KAAK,CAAC,CAAA;yBACf;6BAAM;4BACL,MAAM,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAA;yBAC1C;wBACD,YAAY,EAAE,CAAA;oBAChB,CAAC;iBACF;aACF,CAAC,CAAA;QACJ,CAAC;QACD,KAAK,CAAC,aAAa,CAAC,KAAa,EAAE,QAAqB;YACtD,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;gBAC1B,OAAO,KAAK,CAAA;aACb;YACD,MAAM,OAAO,GAAG,IAAI,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,KAAK,CAAC,CAAA;YACnE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;YACnD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;gBAChB,IAAI,YAAY,CAAA;gBAChB,IAAI;oBACF,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;iBACrC;gBAAC,OAAO,KAAK,EAAE;oBACd,YAAY,GAAG,EAAE,CAAA;iBAClB;gBACD,MAAM,IAAI,KAAK,CACb,4BAA4B,QAAQ,CAAC,MAAM,KACzC,QAAQ,CAAC,UACX,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/C,CAAA;aACF;YACD,OAAO,KAAK,CAAA;QACd,CAAC;KACF,CAAC,CAAC,CAAA;AACP,CAAC,CAAA;AAED,kBAAe,iBAAiB,CAAA"}
@@ -0,0 +1,5 @@
1
+ import { Instance } from 'mobx-state-tree';
2
+ declare const OAuthConfigSchema: import("@jbrowse/core/configuration").AnyConfigurationSchemaType;
3
+ export declare type OAuthInternetAccountConfigModel = typeof OAuthConfigSchema;
4
+ export declare type OAuthInternetAccountConfig = Instance<OAuthInternetAccountConfigModel>;
5
+ export default OAuthConfigSchema;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const configuration_1 = require("@jbrowse/core/configuration");
4
+ const models_1 = require("@jbrowse/core/pluggableElementTypes/models");
5
+ /**
6
+ * #config OAuthInternetAccount
7
+ */
8
+ function x() { } // eslint-disable-line @typescript-eslint/no-unused-vars
9
+ const OAuthConfigSchema = (0, configuration_1.ConfigurationSchema)('OAuthInternetAccount', {
10
+ /**
11
+ * #slot
12
+ */
13
+ tokenType: {
14
+ description: 'a custom name for a token to include in the header',
15
+ type: 'string',
16
+ defaultValue: 'Bearer',
17
+ },
18
+ /**
19
+ * #slot
20
+ */
21
+ authEndpoint: {
22
+ description: 'the authorization code endpoint of the internet account',
23
+ type: 'string',
24
+ defaultValue: '',
25
+ },
26
+ /**
27
+ * #slot
28
+ */
29
+ tokenEndpoint: {
30
+ description: 'the token endpoint of the internet account',
31
+ type: 'string',
32
+ defaultValue: '',
33
+ },
34
+ /**
35
+ * #slot
36
+ */
37
+ needsPKCE: {
38
+ description: 'boolean to indicate if the endpoint needs a PKCE code',
39
+ type: 'boolean',
40
+ defaultValue: false,
41
+ },
42
+ /**
43
+ * #slot
44
+ */
45
+ clientId: {
46
+ description: 'id for the OAuth application',
47
+ type: 'string',
48
+ defaultValue: '',
49
+ },
50
+ /**
51
+ * #slot
52
+ */
53
+ scopes: {
54
+ description: 'optional scopes for the authorization call',
55
+ type: 'string',
56
+ defaultValue: '',
57
+ },
58
+ /**
59
+ * #slot
60
+ */
61
+ state: {
62
+ description: 'optional state for the authorization call',
63
+ type: 'string',
64
+ defaultValue: '',
65
+ },
66
+ /**
67
+ * #slot
68
+ */
69
+ responseType: {
70
+ description: 'the type of response from the authorization endpoint',
71
+ type: 'string',
72
+ defaultValue: 'code',
73
+ },
74
+ /**
75
+ * #slot
76
+ */
77
+ hasRefreshToken: {
78
+ description: 'true if the endpoint can supply a refresh token',
79
+ type: 'boolean',
80
+ defaultValue: false,
81
+ },
82
+ }, {
83
+ /**
84
+ * #baseConfiguration
85
+ */
86
+ baseConfiguration: models_1.BaseInternetAccountConfig,
87
+ explicitlyTyped: true,
88
+ });
89
+ exports.default = OAuthConfigSchema;
90
+ //# sourceMappingURL=configSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configSchema.js","sourceRoot":"","sources":["../../src/OAuthModel/configSchema.ts"],"names":[],"mappings":";;AAAA,+DAAiE;AAEjE,uEAAsF;AAEtF;;GAEG;AACH,SAAS,CAAC,KAAI,CAAC,CAAC,wDAAwD;AAExE,MAAM,iBAAiB,GAAG,IAAA,mCAAmB,EAC3C,sBAAsB,EACtB;IACE;;OAEG;IACH,SAAS,EAAE;QACT,WAAW,EAAE,oDAAoD;QACjE,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,QAAQ;KACvB;IACD;;OAEG;IACH,YAAY,EAAE;QACZ,WAAW,EAAE,yDAAyD;QACtE,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,EAAE;KACjB;IACD;;OAEG;IACH,aAAa,EAAE;QACb,WAAW,EAAE,4CAA4C;QACzD,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,EAAE;KACjB;IACD;;OAEG;IACH,SAAS,EAAE;QACT,WAAW,EAAE,uDAAuD;QACpE,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,KAAK;KACpB;IACD;;OAEG;IACH,QAAQ,EAAE;QACR,WAAW,EAAE,8BAA8B;QAC3C,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,EAAE;KACjB;IACD;;OAEG;IACH,MAAM,EAAE;QACN,WAAW,EAAE,4CAA4C;QACzD,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,EAAE;KACjB;IACD;;OAEG;IACH,KAAK,EAAE;QACL,WAAW,EAAE,2CAA2C;QACxD,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,EAAE;KACjB;IACD;;OAEG;IACH,YAAY,EAAE;QACZ,WAAW,EAAE,sDAAsD;QACnE,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,MAAM;KACrB;IACD;;OAEG;IACH,eAAe,EAAE;QACf,WAAW,EAAE,iDAAiD;QAC9D,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,KAAK;KACpB;CACF,EACD;IACE;;OAEG;IACH,iBAAiB,EAAE,kCAAyB;IAC5C,eAAe,EAAE,IAAI;CACtB,CACF,CAAA;AAKD,kBAAe,iBAAiB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { default as configSchema } from './configSchema';
2
+ export { default as modelFactory } from './model';
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.modelFactory = exports.configSchema = void 0;
7
+ var configSchema_1 = require("./configSchema");
8
+ Object.defineProperty(exports, "configSchema", { enumerable: true, get: function () { return __importDefault(configSchema_1).default; } });
9
+ var model_1 = require("./model");
10
+ Object.defineProperty(exports, "modelFactory", { enumerable: true, get: function () { return __importDefault(model_1).default; } });
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/OAuthModel/index.ts"],"names":[],"mappings":";;;;;;AAAA,+CAAwD;AAA/C,6HAAA,OAAO,OAAgB;AAChC,iCAAiD;AAAxC,sHAAA,OAAO,OAAgB"}
@@ -0,0 +1,91 @@
1
+ /// <reference types="react" />
2
+ import { UriLocation } from '@jbrowse/core/util';
3
+ import { Instance } from 'mobx-state-tree';
4
+ import { OAuthInternetAccountConfigModel } from './configSchema';
5
+ declare const stateModelFactory: (configSchema: OAuthInternetAccountConfigModel) => import("mobx-state-tree").IModelType<{
6
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
7
+ type: import("mobx-state-tree").ISimpleType<string>;
8
+ } & {
9
+ type: import("mobx-state-tree").ISimpleType<"OAuthInternetAccount">;
10
+ configuration: import("mobx-state-tree").ITypeUnion<any, any, any>;
11
+ }, {
12
+ readonly name: string;
13
+ readonly description: string;
14
+ readonly internetAccountId: string;
15
+ readonly authHeader: string;
16
+ readonly tokenType: string;
17
+ readonly domains: string[];
18
+ readonly toggleContents: import("react").ReactNode;
19
+ readonly SelectorComponent: import("@jbrowse/core/util").AnyReactComponentType | undefined;
20
+ readonly selectorLabel: string | undefined;
21
+ } & {
22
+ handlesLocation(location: UriLocation): boolean;
23
+ readonly tokenKey: string;
24
+ } & {
25
+ getTokenFromUser(resolve: (token: string) => void, reject: (error: Error) => void): void;
26
+ storeToken(token: string): void;
27
+ removeToken(): void;
28
+ retrieveToken(): string | null;
29
+ validateToken(token: string, location: UriLocation): Promise<string>;
30
+ } & {
31
+ getToken(location?: UriLocation | undefined): Promise<string>;
32
+ } & {
33
+ addAuthHeaderToInit(init: RequestInit | undefined, token: string): {
34
+ headers: Headers;
35
+ body?: BodyInit | null | undefined;
36
+ cache?: RequestCache | undefined;
37
+ credentials?: RequestCredentials | undefined;
38
+ integrity?: string | undefined;
39
+ keepalive?: boolean | undefined;
40
+ method?: string | undefined;
41
+ mode?: RequestMode | undefined;
42
+ redirect?: RequestRedirect | undefined;
43
+ referrer?: string | undefined;
44
+ referrerPolicy?: ReferrerPolicy | undefined;
45
+ signal?: AbortSignal | null | undefined;
46
+ window?: null | undefined;
47
+ };
48
+ getPreAuthorizationInformation(location: UriLocation): Promise<{
49
+ internetAccountType: string;
50
+ authInfo: {
51
+ token: string;
52
+ configuration: any;
53
+ };
54
+ }>;
55
+ } & {
56
+ getFetcher(location?: UriLocation | undefined): (input: RequestInfo, init?: RequestInit | undefined) => Promise<Response>;
57
+ } & {
58
+ openLocation(location: UriLocation): import("@jbrowse/core/util/io").RemoteFileWithRangeCache;
59
+ } & {
60
+ readonly codeVerifierPKCE: string;
61
+ } & {
62
+ readonly authEndpoint: string;
63
+ readonly tokenEndpoint: string;
64
+ readonly needsPKCE: boolean;
65
+ readonly clientId: string;
66
+ readonly scopes: string;
67
+ /**
68
+ * OAuth state parameter: https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1
69
+ * Can override or extend if dynamic state is needed.
70
+ */
71
+ state(): string | undefined;
72
+ readonly responseType: "code" | "token";
73
+ readonly hasRefreshToken: boolean;
74
+ readonly refreshTokenKey: string;
75
+ } & {
76
+ storeRefreshToken(refreshToken: string): void;
77
+ removeRefreshToken(): void;
78
+ retrieveRefreshToken(): string | null;
79
+ exchangeAuthorizationForAccessToken(token: string, redirectUri: string): Promise<string>;
80
+ exchangeRefreshForAccessToken(refreshToken: string): Promise<string>;
81
+ } & {
82
+ addMessageChannel(resolve: (token: string) => void, reject: (error: Error) => void): void;
83
+ deleteMessageChannel(): void;
84
+ finishOAuthWindow(event: MessageEvent, resolve: (token: string) => void, reject: (error: Error) => void): Promise<void>;
85
+ useEndpointForAuthorization(resolve: (token: string) => void, reject: (error: Error) => void): Promise<void>;
86
+ getTokenFromUser(resolve: (token: string) => void, reject: (error: Error) => void): Promise<void>;
87
+ validateToken(token: string, location: UriLocation): Promise<string>;
88
+ }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
89
+ export default stateModelFactory;
90
+ export declare type OAuthStateModel = ReturnType<typeof stateModelFactory>;
91
+ export declare type OAuthModel = Instance<OAuthStateModel>;
@@ -0,0 +1,317 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const configuration_1 = require("@jbrowse/core/configuration");
30
+ const models_1 = require("@jbrowse/core/pluggableElementTypes/models");
31
+ const util_1 = require("@jbrowse/core/util");
32
+ const mobx_state_tree_1 = require("mobx-state-tree");
33
+ const jwt_decode_1 = __importDefault(require("jwt-decode"));
34
+ function fixup(buf) {
35
+ return buf.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
36
+ }
37
+ function getGlobalObject() {
38
+ // Based on window-or-global
39
+ // https://github.com/purposeindustries/window-or-global/blob/322abc71de0010c9e5d9d0729df40959e1ef8775/lib/index.js
40
+ return (
41
+ // eslint-disable-next-line no-restricted-globals
42
+ (typeof self === 'object' && self.self === self && self) ||
43
+ (typeof global === 'object' && global.global === global && global) ||
44
+ // @ts-ignore
45
+ this);
46
+ }
47
+ const stateModelFactory = (configSchema) => {
48
+ return models_1.InternetAccount.named('OAuthInternetAccount')
49
+ .props({
50
+ type: mobx_state_tree_1.types.literal('OAuthInternetAccount'),
51
+ configuration: (0, configuration_1.ConfigurationReference)(configSchema),
52
+ })
53
+ .views(() => {
54
+ let codeVerifier = undefined;
55
+ return {
56
+ get codeVerifierPKCE() {
57
+ if (codeVerifier) {
58
+ return codeVerifier;
59
+ }
60
+ const global = getGlobalObject();
61
+ const array = new Uint8Array(32);
62
+ global.crypto.getRandomValues(array);
63
+ codeVerifier = fixup(Buffer.from(array).toString('base64'));
64
+ return codeVerifier;
65
+ },
66
+ };
67
+ })
68
+ .views(self => ({
69
+ get authEndpoint() {
70
+ return (0, configuration_1.getConf)(self, 'authEndpoint');
71
+ },
72
+ get tokenEndpoint() {
73
+ return (0, configuration_1.getConf)(self, 'tokenEndpoint');
74
+ },
75
+ get needsPKCE() {
76
+ return (0, configuration_1.getConf)(self, 'needsPKCE');
77
+ },
78
+ get clientId() {
79
+ return (0, configuration_1.getConf)(self, 'clientId');
80
+ },
81
+ get scopes() {
82
+ return (0, configuration_1.getConf)(self, 'scopes');
83
+ },
84
+ /**
85
+ * OAuth state parameter: https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1
86
+ * Can override or extend if dynamic state is needed.
87
+ */
88
+ state() {
89
+ return (0, configuration_1.getConf)(self, 'state') || undefined;
90
+ },
91
+ get responseType() {
92
+ return (0, configuration_1.getConf)(self, 'responseType');
93
+ },
94
+ get hasRefreshToken() {
95
+ return (0, configuration_1.getConf)(self, 'hasRefreshToken');
96
+ },
97
+ get refreshTokenKey() {
98
+ return `${self.internetAccountId}-refreshToken`;
99
+ },
100
+ }))
101
+ .actions(self => ({
102
+ storeRefreshToken(refreshToken) {
103
+ localStorage.setItem(self.refreshTokenKey, refreshToken);
104
+ },
105
+ removeRefreshToken() {
106
+ localStorage.removeItem(self.refreshTokenKey);
107
+ },
108
+ retrieveRefreshToken() {
109
+ return localStorage.getItem(self.refreshTokenKey);
110
+ },
111
+ async exchangeAuthorizationForAccessToken(token, redirectUri) {
112
+ const data = {
113
+ code: token,
114
+ grant_type: 'authorization_code',
115
+ client_id: self.clientId,
116
+ code_verifier: self.codeVerifierPKCE,
117
+ redirect_uri: redirectUri,
118
+ };
119
+ const params = new URLSearchParams(Object.entries(data));
120
+ const response = await fetch(self.tokenEndpoint, {
121
+ method: 'POST',
122
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
123
+ body: params.toString(),
124
+ });
125
+ if (!response.ok) {
126
+ let errorMessage;
127
+ try {
128
+ errorMessage = await response.text();
129
+ }
130
+ catch (error) {
131
+ errorMessage = '';
132
+ }
133
+ throw new Error(`Failed to obtain token from endpoint: ${response.status} (${response.statusText})${errorMessage ? ` (${errorMessage})` : ''}`);
134
+ }
135
+ const accessToken = await response.json();
136
+ if (accessToken.refresh_token) {
137
+ this.storeRefreshToken(accessToken.refresh_token);
138
+ }
139
+ return accessToken.access_token;
140
+ },
141
+ async exchangeRefreshForAccessToken(refreshToken) {
142
+ var _a;
143
+ const data = {
144
+ grant_type: 'refresh_token',
145
+ refresh_token: refreshToken,
146
+ client_id: self.clientId,
147
+ };
148
+ const params = new URLSearchParams(Object.entries(data));
149
+ const response = await fetch(self.tokenEndpoint, {
150
+ method: 'POST',
151
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
152
+ body: params.toString(),
153
+ });
154
+ if (!response.ok) {
155
+ self.removeToken();
156
+ let text = await response.text();
157
+ try {
158
+ const obj = JSON.parse(text);
159
+ if (obj.error === 'invalid_grant') {
160
+ this.removeRefreshToken();
161
+ }
162
+ text = (_a = obj === null || obj === void 0 ? void 0 : obj.error_description) !== null && _a !== void 0 ? _a : text;
163
+ }
164
+ catch (e) {
165
+ /* just use original text as error */
166
+ }
167
+ throw new Error(`Network response failure — ${response.status} (${response.statusText}) ${text ? ` (${text})` : ''}`);
168
+ }
169
+ const accessToken = await response.json();
170
+ if (accessToken.refresh_token) {
171
+ this.storeRefreshToken(accessToken.refresh_token);
172
+ }
173
+ return accessToken.access_token;
174
+ },
175
+ }))
176
+ .actions(self => {
177
+ let listener;
178
+ let refreshTokenPromise = undefined;
179
+ return {
180
+ // used to listen to child window for auth code/token
181
+ addMessageChannel(resolve, reject) {
182
+ listener = event => {
183
+ this.finishOAuthWindow(event, resolve, reject);
184
+ };
185
+ window.addEventListener('message', listener);
186
+ },
187
+ deleteMessageChannel() {
188
+ window.removeEventListener('message', listener);
189
+ },
190
+ async finishOAuthWindow(event, resolve, reject) {
191
+ if (event.data.name !== `JBrowseAuthWindow-${self.internetAccountId}`) {
192
+ return this.deleteMessageChannel();
193
+ }
194
+ const redirectUriWithInfo = event.data.redirectUri;
195
+ const fixedQueryString = redirectUriWithInfo.replace('#', '?');
196
+ const redirectUrl = new URL(fixedQueryString);
197
+ const queryStringSearch = redirectUrl.search;
198
+ const urlParams = new URLSearchParams(queryStringSearch);
199
+ if (urlParams.has('access_token')) {
200
+ const token = urlParams.get('access_token');
201
+ if (!token) {
202
+ return reject(new Error('Error with token endpoint'));
203
+ }
204
+ self.storeToken(token);
205
+ return resolve(token);
206
+ }
207
+ if (urlParams.has('code')) {
208
+ const code = urlParams.get('code');
209
+ if (!code) {
210
+ return reject(new Error('Error with authorization endpoint'));
211
+ }
212
+ try {
213
+ const token = await self.exchangeAuthorizationForAccessToken(code, redirectUrl.origin + redirectUrl.pathname);
214
+ self.storeToken(token);
215
+ return resolve(token);
216
+ }
217
+ catch (error) {
218
+ if (error instanceof Error) {
219
+ return reject(error);
220
+ }
221
+ else {
222
+ return reject(new Error(String(error)));
223
+ }
224
+ }
225
+ }
226
+ if (redirectUriWithInfo.includes('access_denied')) {
227
+ return reject(new Error('OAuth flow was cancelled'));
228
+ }
229
+ if (redirectUriWithInfo.includes('error')) {
230
+ return reject(new Error('Oauth flow error: ' + queryStringSearch));
231
+ }
232
+ this.deleteMessageChannel();
233
+ },
234
+ // opens external OAuth flow, popup for web and new browser window for desktop
235
+ async useEndpointForAuthorization(resolve, reject) {
236
+ const redirectUri = util_1.isElectron
237
+ ? 'http://localhost/auth'
238
+ : window.location.origin + window.location.pathname;
239
+ const data = {
240
+ client_id: self.clientId,
241
+ redirect_uri: redirectUri,
242
+ response_type: self.responseType || 'code',
243
+ };
244
+ if (self.state()) {
245
+ data.state = self.state();
246
+ }
247
+ if (self.scopes) {
248
+ data.scope = self.scopes;
249
+ }
250
+ if (self.needsPKCE) {
251
+ const { codeVerifierPKCE } = self;
252
+ const sha256 = await Promise.resolve().then(() => __importStar(require('crypto-js/sha256'))).then(f => f.default);
253
+ const Base64 = await Promise.resolve().then(() => __importStar(require('crypto-js/enc-base64')));
254
+ const codeChallenge = fixup(Base64.stringify(sha256(codeVerifierPKCE)));
255
+ data.code_challenge = codeChallenge;
256
+ data.code_challenge_method = 'S256';
257
+ }
258
+ if (self.hasRefreshToken) {
259
+ data.token_access_type = 'offline';
260
+ }
261
+ const params = new URLSearchParams(Object.entries(data));
262
+ const url = new URL(self.authEndpoint);
263
+ url.search = params.toString();
264
+ const eventName = `JBrowseAuthWindow-${self.internetAccountId}`;
265
+ if (util_1.isElectron) {
266
+ const { ipcRenderer } = window.require('electron');
267
+ const redirectUri = await ipcRenderer.invoke('openAuthWindow', {
268
+ internetAccountId: self.internetAccountId,
269
+ data,
270
+ url: url.toString(),
271
+ });
272
+ const eventFromDesktop = new MessageEvent('message', {
273
+ data: { name: eventName, redirectUri: redirectUri },
274
+ });
275
+ this.finishOAuthWindow(eventFromDesktop, resolve, reject);
276
+ }
277
+ else {
278
+ const options = `width=500,height=600,left=0,top=0`;
279
+ window.open(url, eventName, options);
280
+ }
281
+ },
282
+ async getTokenFromUser(resolve, reject) {
283
+ const refreshToken = self.hasRefreshToken && self.retrieveRefreshToken();
284
+ if (refreshToken) {
285
+ resolve(await self.exchangeRefreshForAccessToken(refreshToken));
286
+ }
287
+ this.addMessageChannel(resolve, reject);
288
+ this.useEndpointForAuthorization(resolve, reject);
289
+ },
290
+ async validateToken(token, location) {
291
+ const decoded = (0, jwt_decode_1.default)(token);
292
+ if (decoded.exp && decoded.exp < new Date().getTime() / 1000) {
293
+ const refreshToken = self.hasRefreshToken && self.retrieveRefreshToken();
294
+ if (refreshToken) {
295
+ try {
296
+ if (!refreshTokenPromise) {
297
+ refreshTokenPromise =
298
+ self.exchangeRefreshForAccessToken(refreshToken);
299
+ }
300
+ const newToken = await refreshTokenPromise;
301
+ return this.validateToken(newToken, location);
302
+ }
303
+ catch (err) {
304
+ throw new Error(`Token could not be refreshed. ${err}`);
305
+ }
306
+ }
307
+ }
308
+ else {
309
+ refreshTokenPromise = undefined;
310
+ }
311
+ return token;
312
+ },
313
+ };
314
+ });
315
+ };
316
+ exports.default = stateModelFactory;
317
+ //# sourceMappingURL=model.js.map