@crossauth/frontend 0.0.2

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.
@@ -0,0 +1,44 @@
1
+ import { CrossauthError } from '@crossauth/common';
2
+ import { OAuthTokenProvider } from './tokenprovider.ts';
3
+
4
+ /**
5
+ * Used by {@link OAuthClient} and {@link OAuthBsffClient} to automatically
6
+ * refresh access and ID tokens
7
+ */
8
+ export declare class OAuthAutoRefresher {
9
+ private autoRefreshUrl;
10
+ protected csrfHeader: string;
11
+ protected headers: {
12
+ [key: string]: string;
13
+ };
14
+ private autoRefreshActive;
15
+ protected mode: "no-cors" | "cors" | "same-origin";
16
+ protected credentials: "include" | "omit" | "same-origin";
17
+ protected tokenProvider: OAuthTokenProvider;
18
+ /**
19
+ * Constructor
20
+ *
21
+ * @param options
22
+ * - `autoRefreshUrl` the URL to call to perform the refresh Default is `/autorefresh`
23
+ * - `csrfHeader` the header to put CSRF tokens into
24
+ * (default `X-CROSSAUTH-CSRF`))
25
+ * - `mode` overrides the default `mode` in fetch calls
26
+ * - `credentials` - overrides the default `credentials` for fetch calls
27
+ * - `headers` - adds headers to fetfh calls
28
+ * - `tokenProvider` - class for fetching tokens and adding them to requests
29
+ */
30
+ constructor(options: {
31
+ autoRefreshUrl: string;
32
+ csrfHeader?: string;
33
+ credentials?: "include" | "omit" | "same-origin";
34
+ mode?: "no-cors" | "cors" | "same-origin";
35
+ headers?: {
36
+ [key: string]: any;
37
+ };
38
+ tokenProvider: OAuthTokenProvider;
39
+ });
40
+ startAutoRefresh(tokensToFetch?: ("access" | "id")[], errorFn?: (msg: string, e?: CrossauthError) => void): Promise<void>;
41
+ stopAutoRefresh(): void;
42
+ private scheduleAutoRefresh;
43
+ private autoRefresh;
44
+ }
@@ -0,0 +1,208 @@
1
+ import { CrossauthError } from '@crossauth/common';
2
+
3
+ /**
4
+ * A browser-side OAuth client designed with work with the
5
+ * backend-for-frontend (BFF) mode of the backend OAuth client.
6
+ *
7
+ * See {@link @crossauth/fastify!FastifyOAuthClient}.
8
+ */
9
+ export declare class OAuthBffClient {
10
+ private bffPrefix;
11
+ private csrfHeader;
12
+ private enableCsrfProtection;
13
+ private headers;
14
+ private mode;
15
+ private credentials;
16
+ private autoRefresher;
17
+ private deviceCodePoller;
18
+ private getCsrfTokenUrl;
19
+ private autoRefreshUrl;
20
+ private tokensUrl;
21
+ /**
22
+ * Constructor
23
+ *
24
+ * @param options
25
+ * - `bffPrefix` the base url for BFF calls to the OAuth client
26
+ * (eg `bff`, which is the default)
27
+ * - `csrfHeader` the header to put CSRF tokens into
28
+ * (default `X-CROSSAUTH-CSRF`))
29
+ * - `getCsrfTokenUrl` URL to use to fetch CSRF tokens. Default is
30
+ * `/api/getcsrftoken`
31
+ * - `autoRefreshUrl` URL to use to refresh tokens. Default is
32
+ * `/api/refreshtokens`
33
+ * - `tokensUrl` URL to use to fetch token payloads. Default is
34
+ * `/tokens`
35
+ * - `deviceCodePollUrl` URL for polling for device code authorization.
36
+ * Default is `/devicecodepoll`
37
+ * - `mode` overrides the default `mode` in fetch calls
38
+ * - `credentials` - overrides the default `credentials` for fetch calls
39
+ * - `headers` - adds headers to fetfh calls
40
+ */
41
+ constructor(options?: {
42
+ bffPrefix?: string;
43
+ csrfHeader?: string;
44
+ credentials?: "include" | "omit" | "same-origin";
45
+ mode?: "no-cors" | "cors" | "same-origin";
46
+ headers?: {
47
+ [key: string]: any;
48
+ };
49
+ enableCsrfProtection?: boolean;
50
+ getCsrfTokenUrl?: string;
51
+ autoRefreshUrl?: string;
52
+ tokensUrl?: string;
53
+ deviceCodePollUrl?: string;
54
+ });
55
+ /**
56
+ * Gets a CSRF token from the server
57
+ * @returns the CSRF token that can be included in
58
+ * the `X-CROSSAUTH-CSRF` header
59
+ */
60
+ getCsrfToken(): Promise<string | undefined>;
61
+ /**
62
+ * Fetches the ID token from the client.
63
+ *
64
+ * This only returns something if the ID token was returned to the BFF
65
+ * client in a previous OAuth call. Otherwise it returns an empty JSON.
66
+ *
67
+ * @param crfToken the CSRF token. If emtpy, one will be fetched before
68
+ * making the request
69
+ * @returns the ID token payload or an empty object if there isn't one
70
+ */
71
+ getIdToken(csrfToken?: string): Promise<{
72
+ [key: string]: any;
73
+ } | null>;
74
+ /**
75
+ * Returns whether or not there is an ID token stored in the BFF server
76
+ * for this client.
77
+ *
78
+ * @param crfToken the CSRF token. If emtpy, one will be fetched before
79
+ * making the request
80
+ * @returns true or false
81
+ */
82
+ haveIdToken(csrfToken?: string): Promise<boolean>;
83
+ /**
84
+ * Fetches the access token from the client.
85
+ *
86
+ * This only returns something if the access token was returned to the BFF
87
+ * client in a previous OAuth call. Otherwise it returns an empty JSON.
88
+ *
89
+ * @param crfToken the CSRF token. If emtpy, one will be fetched before
90
+ * making the request
91
+ * @param headers any additional headers to add (will be added to
92
+ * the ones given with {@link OAuthBffClient.addHeader} )
93
+ * @returns the access token payload or an empty object if there isn't one
94
+ */
95
+ getAccessToken(csrfToken?: string): Promise<{
96
+ [key: string]: any;
97
+ } | null>;
98
+ /**
99
+ * Returns whether or not there is an access token stored in the BFF server
100
+ * for this client.
101
+ *
102
+ * @param crfToken the CSRF token. If emtpy, one will be fetched before
103
+ * making the request
104
+ * @returns true or false
105
+ */
106
+ haveAccessToken(csrfToken?: string): Promise<boolean>;
107
+ /**
108
+ * Fetches the refresh token from the client.
109
+ *
110
+ * This only returns something if the refresh token was returned to the BFF
111
+ * client in a previous OAuth call. Otherwise it returns an empty JSON.
112
+ *
113
+ * @param crfToken the CSRF token. If emtpy, one will be fetched before
114
+ * making the request
115
+ * @returns the refresh token payload or an empty object if there isn't one
116
+ */
117
+ getRefreshToken(csrfToken?: string): Promise<{
118
+ [key: string]: any;
119
+ } | null>;
120
+ /**
121
+ * Returns whether or not there is a refresh token stored in the BFF server
122
+ * for this client.
123
+ *
124
+ * @param crfToken the CSRF token. If emtpy, one will be fetched before
125
+ * making the request
126
+ * @returns true or false
127
+ */
128
+ haveRefreshToken(csrfToken?: string): Promise<boolean>;
129
+ /**
130
+ * Calls an API endpoint via the BFF server
131
+ * @param method the HTTP method
132
+ * @param endpoint the endpoint to call, relative to `bffPrefix`
133
+ * @param body : the body to pass to the call
134
+ * @param csrfToken : the CSRF token
135
+ * @returns the HTTP status code and the body or null
136
+ */
137
+ api(method: "GET" | "POST" | "PUT" | "PATCH" | "OPTIONS" | "HEAD" | "DELETE", endpoint: string, body?: {
138
+ [key: string]: any;
139
+ }, csrfToken?: string): Promise<{
140
+ status: number;
141
+ body: {
142
+ [key: string]: any;
143
+ } | null;
144
+ }>;
145
+ /**
146
+ * Return all tokens that the client has been enabled to return.
147
+ *
148
+ * @param csrfToken the CSRF token if one is needed
149
+ * @returns an object with the following (whichever are enabled at the client)
150
+ * - `id_token`
151
+ * - `access_token`
152
+ * - `refresh_token`
153
+ * - `have_id_token`
154
+ * - `have_access_token`
155
+ * - `have_refresh_token`
156
+ */
157
+ getTokens(csrfToken?: string): Promise<{
158
+ [key: string]: any;
159
+ } | null>;
160
+ /**
161
+ * Turns auto refresh of tokens on
162
+ * @param tokensToFetch which tokens to fetch
163
+ * @param errorFn what to call in case of error
164
+ */
165
+ startAutoRefresh(tokensToFetch?: ("access" | "id")[], errorFn?: (msg: string, e?: CrossauthError) => void): Promise<void>;
166
+ /**
167
+ * Turns auto refresh of tokens off
168
+ */
169
+ stopAutoRefresh(): void;
170
+ /**
171
+ * Turns polling for a device code
172
+ * @param tokensToFetch which tokens to fetch
173
+ * @param errorFn what to call in case of error
174
+ */
175
+ startDeviceCodePolling(deviceCode: string, pollResultFn: (status: ("complete" | "completeAndRedirect" | "authorization_pending" | "expired_token" | "error"), error?: string, location?: string) => void, interval?: number): Promise<void>;
176
+ /**
177
+ * Turns off polling for a device code
178
+ */
179
+ stopDeviceCodePolling(): void;
180
+ /**
181
+ * Fetches the expiry times for each token.
182
+ * @param crfToken the CSRF token. If emtpy
183
+ * , one will be fetched before
184
+ * making the request
185
+ * @returns for each token, either the expiry, `null` if it does not
186
+ * expire, or `undefined` if the token does not exist
187
+ */
188
+ getTokenExpiries(tokensToFetch: ("access" | "id" | "refresh")[], csrfToken?: string): Promise<{
189
+ id: number | null | undefined;
190
+ access: number | null | undefined;
191
+ refresh: number | null | undefined;
192
+ }>;
193
+ /**
194
+ * Makes a fetch, adding in the requested token
195
+ * @param url the URL to fetch
196
+ * @param params parameters to add to the fetch
197
+ * @param token which token to add
198
+ * @returns parsed JSON response
199
+ */
200
+ jsonFetchWithToken(url: string, params: {
201
+ [key: string]: any;
202
+ }, _token: "access" | "refresh"): Promise<Response>;
203
+ receiveTokens(_tokens: {
204
+ access_token?: string | null;
205
+ id_token?: string | null;
206
+ refresh_token?: string | null;
207
+ }): Promise<void>;
208
+ }
@@ -0,0 +1,271 @@
1
+ import { OAuthClientBase, CrossauthError, OAuthTokenResponse, OAuthDeviceAuthorizationResponse } from '@crossauth/common';
2
+ import { OAuthTokenConsumer } from './tokenconsumer';
3
+
4
+ /**
5
+ * This is the type for a function that is called when an OAuth endpoint
6
+ * returns the `error` field.
7
+ */
8
+ export type ErrorFn = (client: OAuthClient, error: string, errorDescription?: string) => Promise<any>;
9
+ /**
10
+ * If this URL was called with an OAuth authorize response, the `token`
11
+ * endpoint will be called and, if successful, passed to this function.
12
+ */
13
+ export type ReceiveTokenFn = (client: OAuthClient, response: OAuthTokenResponse) => Promise<any>;
14
+ export type TokenResponseType = "memory" | "localStorage" | "sessionStorage";
15
+ export declare class OAuthClient extends OAuthClientBase {
16
+ #private;
17
+ private resServerBaseUrl;
18
+ private resServerHeaders;
19
+ private resServerMode;
20
+ private resServerCredentials;
21
+ private accessTokenResponseType?;
22
+ private refreshTokenResponseType?;
23
+ private idTokenResponseType?;
24
+ private accessTokenName;
25
+ private refreshTokenName;
26
+ private idTokenName;
27
+ get idTokenPayload(): {
28
+ [key: string]: any;
29
+ } | undefined;
30
+ private autoRefresher;
31
+ private deviceCodePoller;
32
+ private deviceAuthorizationUrl;
33
+ /**
34
+ * Constructor
35
+ *
36
+ * @param options
37
+ * - `authServerBaseUrl` the base url the authorization server.
38
+ * For example, the authorize endpoint would be
39
+ * `authServerBaseUrl + "authorize"`.
40
+ * Required: no default
41
+ * - `resServerBaseUrl` the base url the resource server.
42
+ * For example, Relative URLs to the resource server are relative
43
+ * to this. If you always give absolute URLs, this is optional.
44
+ * If you don't give it and you do make relative URLs, it will be
45
+ * relative to the page you are on. Default: empty string.
46
+ * - `redirect_uri` a URL on the site serving this app which the
47
+ * authorization server will redirect to with an authorization
48
+ * code. See description in class documentation.
49
+ * This is not required if you are not using OAuth flows
50
+ * which require a redirect URI (eg the password flow).
51
+ * - `accessTokenResponseType` where to store access tokens. See
52
+ * class documentation. Default `return`.
53
+ * - `refreshTokenResponseType` where to store refresh tokens. See
54
+ * class documentation. Default `return`.
55
+ * - `idTokenResponseType` where to store id tokens. See
56
+ * class documentation. Default `return`.
57
+ * - `accessTokenName` name for access token in local or session
58
+ * storage, depending on `accessTokenResponseType`
59
+ * - `refreshTokenName` name for refresh token in local or session
60
+ * storage, depending on `refreshTokenResponseType`
61
+ * - `idTokenName` name for id token in local or session
62
+ * storage, depending on `idTokenResponseType`
63
+ * - `mresServerMode` overrides the default `mode` in fetch calls
64
+ * - `resServerCredentials` - overrides the default `credentials` for fetch calls
65
+ * - `resServerHeaders` - adds headers to fetfh calls
66
+ * - `autoRefresh` - if set and tokens are present in local or session storage,
67
+ * automatically turn on auto refresh
68
+ * - `deviceAuthorization` URL, relative to the authorization server base,
69
+ * for starting the device code flow. Default `device_authorization`
70
+ * Default is `/devicecodepoll`
71
+ * For other options see {@link @crossauth/common/OAuthClientBase}.
72
+ */
73
+ constructor(options: {
74
+ authServerBaseUrl: string;
75
+ stateLength?: number;
76
+ verifierLength?: number;
77
+ client_id: string;
78
+ client_secret?: string;
79
+ redirect_uri?: string;
80
+ codeChallengeMethod?: "plain" | "S256";
81
+ tokenConsumer: OAuthTokenConsumer;
82
+ resServerBaseUrl?: string;
83
+ accessTokenResponseType?: TokenResponseType;
84
+ refreshTokenResponseType?: TokenResponseType;
85
+ idTokenResponseType?: TokenResponseType;
86
+ accessTokenName?: string;
87
+ refreshTokenName?: string;
88
+ idTokenName?: string;
89
+ resServerCredentials?: "include" | "omit" | "same-origin";
90
+ resServerMode?: "no-cors" | "cors" | "same-origin";
91
+ resServerHeaders?: {
92
+ [key: string]: any;
93
+ };
94
+ autoRefresh?: ("access" | "id")[];
95
+ deviceAuthorizationUrl?: string;
96
+ });
97
+ /**
98
+ * Processes the query parameters for a Redirect URI request if they
99
+ * exist in the URL.
100
+ *
101
+ * Call this on page load to see if it was called as redirect URI.
102
+ *
103
+ * If this URL doesn't match the redirect URI passed in the constructor,
104
+ * or this URL was not called with OAuth Redirect URI query parameters,
105
+ * undefined is returned.
106
+ *
107
+ * If this URL contains the error query parameter, `errorFn` is called.
108
+ * It is also called if the state does not match.
109
+ *
110
+ * If an authorization code was in the query parameters, the token
111
+ * endpoint is called. Depending on whether that returned an error,
112
+ * either `receiveTokenFn` or `errorFn` will be called.
113
+ *
114
+ * @param receiveTokenFn if defined, called if a token is returned.
115
+ *
116
+ * @param errorFn if defined, called if any OAuth endpoint returned `error`,
117
+ * or if the `state` was not correct.
118
+ *
119
+ * @returns the result of `receiveTokenFn`, `errorFn` or `undefined`. If
120
+ * `receiveTokenFn`/`errorFn` is not defined, rather than calling
121
+ * it, this function just returns the OAuth response.
122
+ *
123
+ */
124
+ handleRedirectUri(): Promise<any | undefined>;
125
+ /**
126
+ * Turns auto refresh of tokens on
127
+ * @param tokensToFetch which tokens to fetch
128
+ * @param errorFn what to call in case of error
129
+ */
130
+ startAutoRefresh(tokensToFetch?: ("access" | "id")[], errorFn?: (msg: string, e?: CrossauthError) => void): Promise<void>;
131
+ /**
132
+ * Turns auto refresh of tokens off
133
+ */
134
+ stopAutoRefresh(): void;
135
+ /**
136
+ * Turns polling for a device code
137
+ * @param tokensToFetch which tokens to fetch
138
+ * @param errorFn what to call in case of error
139
+ */
140
+ startDeviceCodePolling(deviceCode: string, pollResultFn: (status: ("complete" | "completeAndRedirect" | "authorization_pending" | "expired_token" | "error"), error?: string, location?: string) => void, interval?: number): Promise<void>;
141
+ /**
142
+ * Turns off polling for a device code
143
+ */
144
+ stopDeviceCodePolling(): void;
145
+ /**
146
+ * Return the ID token payload
147
+ *
148
+ * This does the same thign as {@link idTokenPayload}. We have it here
149
+ * as well for consistency with {@link OAuthBffClient}.
150
+ *
151
+ * @returns the payload as an object
152
+ */
153
+ getIdToken(): {
154
+ [key: string]: any;
155
+ } | undefined;
156
+ /**
157
+ * Produce a random Base64-url-encoded string, whose length before
158
+ * base64-url-encoding is the given length,
159
+ * @param length the length of the random array before base64-url-encoding.
160
+ * @returns the random value as a Base64-url-encoded srting
161
+ */
162
+ protected randomValue(length: number): string;
163
+ /**
164
+ * SHA256 and Base64-url-encodes the given test
165
+ * @param plaintext the text to encode
166
+ * @returns the SHA256 hash, Base64-url-encode
167
+ */
168
+ protected sha256(plaintext: string): Promise<string>;
169
+ /**
170
+ * Calls an API endpoint on the resource server
171
+ * @param method the HTTP method
172
+ * @param endpoint the endpoint to call, relative to `resServerBaseUrl`
173
+ * @param body : the body to pass to the call
174
+ * @returns the HTTP status code and the body or null
175
+ */
176
+ api(method: "GET" | "POST" | "PUT" | "PATCH" | "OPTIONS" | "HEAD" | "DELETE", endpoint: string, body?: {
177
+ [key: string]: any;
178
+ }): Promise<{
179
+ status: number;
180
+ body: {
181
+ [key: string]: any;
182
+ } | null;
183
+ }>;
184
+ /**
185
+ * Fetches the expiry times for each token.
186
+ * @param crfToken the CSRF token. If emtpy
187
+ * , one will be fetched before
188
+ * making the request
189
+ * @returns for each token, either the expiry, `null` if it does not
190
+ * expire, or `undefined` if the token does not exist
191
+ */
192
+ getTokenExpiries(_tokensToFetch: ("access" | "id" | "refresh")[], _csrfToken?: string): Promise<{
193
+ id: number | null | undefined;
194
+ access: number | null | undefined;
195
+ refresh: number | null | undefined;
196
+ }>;
197
+ /**
198
+ * Makes a fetch, adding in the requested token.
199
+ *
200
+ * Also adds client ID and secret if they are defined.
201
+ *
202
+ * @param url the URL to fetch
203
+ * @param params parameters to add to the fetch
204
+ * @param token which token to add
205
+ * @returns parsed JSON response
206
+ */
207
+ jsonFetchWithToken(url: string, params: {
208
+ [key: string]: any;
209
+ }, token: "access" | "refresh"): Promise<Response>;
210
+ /**
211
+ * Does nothing as CSRF tokens are not needed for this class
212
+ * @returns `undefined`
213
+ */
214
+ getCsrfToken(): Promise<undefined>;
215
+ receiveTokens(tokens: {
216
+ access_token?: string | null;
217
+ id_token?: string | null;
218
+ refresh_token?: string | null;
219
+ }): Promise<void>;
220
+ /**
221
+ * See {@link @crossuath/common!OAuthClientBase}. Calls the base function
222
+ * then saves the tokens, as per the requested method
223
+ * @param scope
224
+ */
225
+ clientCredentialsFlow(scope?: string): Promise<OAuthTokenResponse>;
226
+ /**
227
+ * See {@link @crossuath/common!OAuthClientBase}. Calls the base function
228
+ * then saves the tokens, as per the requested method
229
+ * @param scope
230
+ */
231
+ passwordFlow(username: string, password: string, scope?: string): Promise<OAuthTokenResponse>;
232
+ /**
233
+ * See {@link @crossuath/common!OAuthClientBase}. Calls the base function
234
+ * then saves the tokens, as per the requested method
235
+ * @param scope
236
+ */
237
+ deviceCodeFlow(scope?: string): Promise<OAuthDeviceAuthorizationResponse>;
238
+ /**
239
+ * See {@link @crossuath/common!OAuthClientBase}. Calls the base function
240
+ * then saves the tokens, as per the requested method
241
+ * @param scope
242
+ */
243
+ mfaOtpComplete(mfaToken: string, otp: string): Promise<{
244
+ access_token?: string;
245
+ refresh_token?: string;
246
+ id_token?: string;
247
+ expires_in?: number;
248
+ scope?: string;
249
+ token_type?: string;
250
+ error?: string;
251
+ error_description?: string;
252
+ }>;
253
+ /**
254
+ * See {@link @crossuath/common!OAuthClientBase}. Calls the base function
255
+ * then saves the tokens, as per the requested method
256
+ * @param scope
257
+ */
258
+ mfaOobComplete(mfaToken: string, oobCode: string, bindingCode: string): Promise<OAuthTokenResponse>;
259
+ /**
260
+ * See {@link @crossuath/common!OAuthClientBase}. Calls the base function
261
+ * then saves the tokens, as per the requested method
262
+ * @param scope
263
+ */
264
+ refreshTokenFlow(refreshToken?: string): Promise<OAuthTokenResponse>;
265
+ /**
266
+ * Executes the authorization code flow
267
+ * @param scope the scope to request
268
+ * @param pkce whether or not to use PKCE.
269
+ */
270
+ authorizationCodeFlow(scope?: string, pkce?: boolean): Promise<void>;
271
+ }
@@ -0,0 +1,38 @@
1
+ import { OAuthClientBase } from '@crossauth/common';
2
+
3
+ /**
4
+ * Used by {@link OAuthClient} and {@link OAuthBsffClient} to poll for
5
+ * authorization in the device code flow
6
+ */
7
+ export declare class OAuthDeviceCodePoller {
8
+ private deviceCodePollUrl;
9
+ protected headers: {
10
+ [key: string]: string;
11
+ };
12
+ private pollingActive;
13
+ protected mode: "no-cors" | "cors" | "same-origin";
14
+ protected credentials: "include" | "omit" | "same-origin";
15
+ protected respectRedirect: boolean;
16
+ protected oauthClient?: OAuthClientBase;
17
+ /**
18
+ * Constructor
19
+ *
20
+ * @param options
21
+ * - `deviceCodePollUrl` the URL to call to poll for authorization. Default `/devicecodepoll`
22
+ * - `mode` overrides the default `mode` in fetch calls
23
+ * - `credentials` - overrides the default `credentials` for fetch calls
24
+ * - `headers` - adds headers to fetfh calls
25
+ */
26
+ constructor(options: {
27
+ deviceCodePollUrl?: string | null;
28
+ credentials?: "include" | "omit" | "same-origin";
29
+ mode?: "no-cors" | "cors" | "same-origin";
30
+ headers?: {
31
+ [key: string]: any;
32
+ };
33
+ oauthClient?: OAuthClientBase;
34
+ });
35
+ startPolling(deviceCode: string, pollResultFn: (status: ("complete" | "completeAndRedirect" | "authorization_pending" | "expired_token" | "error"), error?: string, location?: string) => void, interval?: number): Promise<void>;
36
+ stopPolling(): void;
37
+ private poll;
38
+ }
@@ -0,0 +1,10 @@
1
+ import { OAuthTokenConsumerBase } from '@crossauth/common';
2
+
3
+ export declare class OAuthTokenConsumer extends OAuthTokenConsumerBase {
4
+ /**
5
+ * SHA256 and Base64-url-encodes the given test
6
+ * @param plaintext the text to encode
7
+ * @returns the SHA256 hash, Base64-url-encode
8
+ */
9
+ hash(plaintext: string): Promise<string>;
10
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * USed by {@link OAuthAutoRefresher} to get tokens from the client
3
+ */
4
+ export declare abstract class OAuthTokenProvider {
5
+ /**
6
+ * Gets a CSRF token from the server
7
+ * @returns the CSRF token that can be included in
8
+ * the `X-CROSSAUTH-CSRF` header
9
+ */
10
+ getCsrfToken(): Promise<string | undefined>;
11
+ /**
12
+ * Fetches the expiry times for each token.
13
+ * @param crfToken the CSRF token. If emtpy
14
+ * , one will be fetched before
15
+ * making the request
16
+ * @returns for each token, either the expiry, `null` if it does not
17
+ * expire, or `undefined` if the token does not exist
18
+ */
19
+ abstract getTokenExpiries(tokensToFetch: ("access" | "id" | "refresh")[], csrfToken?: string): Promise<{
20
+ id: number | null | undefined;
21
+ access: number | null | undefined;
22
+ refresh: number | null | undefined;
23
+ }>;
24
+ /**
25
+ * Makes a fetch, adding in the requested token
26
+ * @param url the URL to fetch
27
+ * @param params parameters to add to the fetch
28
+ * @param token which token to add. Ignored as this client doesn't add tokens
29
+ * @returns parsed JSON response
30
+ */
31
+ abstract jsonFetchWithToken(url: string, params: {
32
+ [key: string]: any;
33
+ }, token: "access" | "refresh"): Promise<Response>;
34
+ abstract receiveTokens(tokens: {
35
+ access_token?: string | null;
36
+ id_token?: string | null;
37
+ refresh_token?: string | null;
38
+ }): Promise<void>;
39
+ }
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@crossauth/frontend",
3
+ "private": false,
4
+ "version": "0.0.2",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "typings": "./dist/index.d.ts",
9
+ "types": "./dist/index.d.ts",
10
+ "files": [
11
+ "dist/*"
12
+ ],
13
+ "devDependencies": {
14
+ "@types/node": "^20.10.8",
15
+ "@types/supertest": "^6.0.2",
16
+ "typedoc": "^0.25.4",
17
+ "typescript": "^5.3.3",
18
+ "vite": "^5.0.8",
19
+ "vite-plugin-dts": "^3.6.4",
20
+ "vitest": "^1.1.0"
21
+ },
22
+ "dependencies": {
23
+ "@esbuild-plugins/node-modules-polyfill": "^0.2.2",
24
+ "@crossauth/common": "^0.0.2"
25
+ },
26
+ "scripts": {
27
+ "dev": "vite",
28
+ "build": "vite build --emptyOutDir=false",
29
+ "preview": "vite preview",
30
+ "test": "echo 'No tests defined'",
31
+ "testonce": "echo 'No tests defined'",
32
+ "doc": "typedoc"
33
+ }
34
+ }