1 | /**
|
2 | * The type of the configuration object used to create a `OAuth2PopupFlow`
|
3 | *
|
4 | * Each property has a JSDOC description to explain what it does.
|
5 | */
|
6 | export interface OAuth2PopupFlowOptions<TokenPayload extends {
|
7 | exp: number;
|
8 | }> {
|
9 | /**
|
10 | * REQUIRED
|
11 | * The full URI of the authorization endpoint provided by the authorization server.
|
12 | *
|
13 | * e.g. `https://example.com/oauth/authorize`
|
14 | */
|
15 | authorizationUri: string;
|
16 | /**
|
17 | * REQUIRED
|
18 | * The client ID of your application provided by the authorization server.
|
19 | *
|
20 | * This client ID is sent to the authorization server using `authorizationUrl` endpoint in the
|
21 | * query portion of the URL along with the other parameters.
|
22 | * This value will be URL encoded like so:
|
23 | *
|
24 | * `https://example.com/oauth/authorize?client_id=SOME_CLIENT_ID_VALUE...`
|
25 | */
|
26 | clientId: string;
|
27 | /**
|
28 | * REQUIRED
|
29 | * The URI that the authorization server will to redirect after the user has been authenticated.
|
30 | * This redirect URI *must* be a URI from *your application* and it must also be registered with
|
31 | * the authorization server. Some authorities call this a "callback URLs" or "login URLs" etc.
|
32 | *
|
33 | * > e.g. `http://localhost:4200/redirect` for local testing
|
34 | * >
|
35 | * > or `https://my-application.com/redirect` for prod
|
36 | *
|
37 | * This redirect URI is sent to the authorization server using `authorizationUrl` endpoint in the
|
38 | * query portion of the URL along with the other parameters.
|
39 | * This value will be URL encoded like so:
|
40 | *
|
41 | * `https://example.com/oauth/authorize?redirect_URI=http%3A%2F%2Flocalhost%2Fredirect...`
|
42 | */
|
43 | redirectUri: string;
|
44 | /**
|
45 | * REQUIRED
|
46 | * A list permission separated by spaces that is the scope of permissions your application is
|
47 | * requesting from the authorization server. If the user is logging in the first time, it may ask
|
48 | * them to approve those permission before authorizing your application.
|
49 | *
|
50 | * > e.g. `openid profile`
|
51 | *
|
52 | * The scopes are sent to the authorization server using `authorizationUrl` endpoint in the
|
53 | * query portion of the URL along with the other parameters.
|
54 | * This value will be URL encoded like so:
|
55 | *
|
56 | * `https://example.com/oauth/authorize?scope=openid%20profile...`
|
57 | */
|
58 | scope: string;
|
59 | /**
|
60 | * OPTIONAL
|
61 | * `response_type` is an argument to be passed to the authorization server via the
|
62 | * `authorizationUri` endpoint in the query portion of the URL.
|
63 | *
|
64 | * Most implementations of oauth2 use the default value of `token` to tell the authorization
|
65 | * server to start the implicit grant flow but you may override that value with this option.
|
66 | *
|
67 | * For example, Auth0--an OAuth2 authority/authorization server--requires the value `id_token`
|
68 | * instead of `token` for the implicit flow.
|
69 | *
|
70 | * The response type is sent to the authorization server using `authorizationUrl` endpoint in the
|
71 | * query portion of the URL along with the other parameters.
|
72 | * This value will be URL encoded like so:
|
73 | *
|
74 | * `https://example.com/oauth/authorize?response_type=token...`
|
75 | */
|
76 | responseType?: string;
|
77 | /**
|
78 | * OPTIONAL
|
79 | * The key used to save the token in the given storage. The default key is `token` so the token
|
80 | * would be persisted in `localStorage.getItem('token')` if `localStorage` was the configured
|
81 | * `Storage`.
|
82 | */
|
83 | accessTokenStorageKey?: string;
|
84 | /**
|
85 | * OPTIONAL
|
86 | * During `handleRedirect`, the method will try to parse `window.location.hash` to an object using
|
87 | * `OAuth2PopupFlow.decodeUriToObject`. After that object has been decoded, this property
|
88 | * determines the key to use that will retrieve the token from that object.
|
89 | *
|
90 | * By default it is `access_token` but you you may need to change that e.g. Auth0 uses `id_token`.
|
91 | */
|
92 | accessTokenResponseKey?: string;
|
93 | /**
|
94 | * OPTIONAL
|
95 | * The storage implementation of choice. It can be `localStorage` or `sessionStorage` or something
|
96 | * else. By default, this is `localStorage` and `localStorage` is the preferred `Storage`.
|
97 | */
|
98 | storage?: Storage;
|
99 | /**
|
100 | * OPTIONAL
|
101 | * The `authenticated` method periodically checks `loggedIn()` and resolves when `loggedIn()`
|
102 | * returns `true`.
|
103 | *
|
104 | * This property is how long it will wait between checks. By default it is `200`.
|
105 | */
|
106 | pollingTime?: number;
|
107 | /**
|
108 | * OPTIONAL
|
109 | * Some oauth authorities require additional parameters to be passed to the `authorizationUri`
|
110 | * URL in order for the implicit grant flow to work.
|
111 | *
|
112 | * For example: [Auth0--an OAuth2 authority/authorization server--requires the parameters
|
113 | * `nonce`][0]
|
114 | * be passed along with every call to the `authorizationUri`. You can do that like so:
|
115 | *
|
116 | * ```ts
|
117 | * const auth = OAuth2PopupFlow({
|
118 | * authorizationUri: 'https://example.com/oauth/authorize',
|
119 | * clientId: 'foo_client',
|
120 | * redirectUri: 'http://localhost:8080/redirect',
|
121 | * scope: 'openid profile',
|
122 | * // this can be a function or static object
|
123 | * additionalAuthorizationParameters: () => {
|
124 | * // in prod, consider something more cryptographic
|
125 | * const nonce = Math.floor(Math.random() * 1000).toString();
|
126 | * localStorage.setItem('nonce', nonce);
|
127 | * return { nonce };
|
128 | * // `nonce` will now be encoded in the URL like so:
|
129 | * // https://example.com/oauth/authorize?client_id=foo_client...nonce=1234
|
130 | * },
|
131 | * // the token returned by Auth0, has the `nonce` in the payload
|
132 | * // you can add this additional check now
|
133 | * tokenValidator: ({ payload }) => {
|
134 | * const storageNonce = parseInt(localStorage.getItem('nonce'), 10);
|
135 | * const payloadNonce = parseInt(payload.nonce, 10);
|
136 | * return storageNonce === payloadNonce;
|
137 | * },
|
138 | * });
|
139 | * ```
|
140 | *
|
141 | * [0]: https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce
|
142 | */
|
143 | additionalAuthorizationParameters?: (() => {
|
144 | [key: string]: string;
|
145 | }) | {
|
146 | [key: string]: string;
|
147 | };
|
148 | /**
|
149 | * OPTIONAL
|
150 | * This function intercepts the `loggedIn` method and causes it to return early with `false` if
|
151 | * this function itself returns `false`. Use this function to validate claims in the token payload
|
152 | * or token.
|
153 | *
|
154 | * [For example: validating the `nonce`:][0]
|
155 | *
|
156 | * ```ts
|
157 | * const auth = OAuth2PopupFlow({
|
158 | * authorizationUri: 'https://example.com/oauth/authorize',
|
159 | * clientId: 'foo_client',
|
160 | * redirectUri: 'http://localhost:8080/redirect',
|
161 | * scope: 'openid profile',
|
162 | * // this can be a function or static object
|
163 | * additionalAuthorizationParameters: () => {
|
164 | * // in prod, consider something more cryptographic
|
165 | * const nonce = Math.floor(Math.random() * 1000).toString();
|
166 | * localStorage.setItem('nonce', nonce);
|
167 | * return { nonce };
|
168 | * // `nonce` will now be encoded in the URL like so:
|
169 | * // https://example.com/oauth/authorize?client_id=foo_client...nonce=1234
|
170 | * },
|
171 | * // the token returned by Auth0, has the `nonce` in the payload
|
172 | * // you can add this additional check now
|
173 | * tokenValidator: ({ payload }) => {
|
174 | * const storageNonce = parseInt(localStorage.getItem('nonce'), 10);
|
175 | * const payloadNonce = parseInt(payload.nonce, 10);
|
176 | * return storageNonce === payloadNonce;
|
177 | * },
|
178 | * });
|
179 | * ```
|
180 | *
|
181 | * [0]: https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce
|
182 | */
|
183 | tokenValidator?: (options: {
|
184 | payload: TokenPayload;
|
185 | token: string;
|
186 | }) => boolean;
|
187 | /**
|
188 | * OPTIONAL
|
189 | * A hook that runs in `tryLoginPopup` before any popup is opened. This function can return a
|
190 | * `Promise` and the popup will not open until it resolves.
|
191 | *
|
192 | * A typical use case would be to wait a certain amount of time before opening the popup to let
|
193 | * the user see why the popup is happening.
|
194 | */
|
195 | beforePopup?: () => any | Promise<any>;
|
196 | /**
|
197 | * OPTIONAL
|
198 | * A hook that runs in `handleRedirect` that takes in the result of the hash payload from the
|
199 | * authorization server. Use this hook to grab more from the response or to debug the response
|
200 | * from the authorization URL.
|
201 | */
|
202 | afterResponse?: (authorizationResponse: {
|
203 | [key: string]: string | undefined;
|
204 | }) => void;
|
205 | }
|
206 | declare const FixedTypesOAuth2PopupFlow: <TokenPayload extends {
|
207 | exp: number;
|
208 | }>(opts: OAuth2PopupFlowOptions<TokenPayload>) => Pick<{
|
209 | /**
|
210 | * REQUIRED
|
211 | * The full URI of the authorization endpoint provided by the authorization server.
|
212 | *
|
213 | * e.g. `https://example.com/oauth/authorize`
|
214 | */
|
215 | authorizationUri: string;
|
216 | /**
|
217 | * REQUIRED
|
218 | * The client ID of your application provided by the authorization server.
|
219 | *
|
220 | * This client ID is sent to the authorization server using `authorizationUrl` endpoint in the
|
221 | * query portion of the URL along with the other parameters.
|
222 | * This value will be URL encoded like so:
|
223 | *
|
224 | * `https://example.com/oauth/authorize?client_id=SOME_CLIENT_ID_VALUE...`
|
225 | */
|
226 | clientId: string;
|
227 | /**
|
228 | * REQUIRED
|
229 | * The URI that the authorization server will to redirect after the user has been authenticated.
|
230 | * This redirect URI *must* be a URI from *your application* and it must also be registered with
|
231 | * the authorization server. Some authorities call this a "callback URLs" or "login URLs" etc.
|
232 | *
|
233 | * > e.g. `http://localhost:4200/redirect` for local testing
|
234 | * >
|
235 | * > or `https://my-application.com/redirect` for prod
|
236 | *
|
237 | * This redirect URI is sent to the authorization server using `authorizationUrl` endpoint in the
|
238 | * query portion of the URL along with the other parameters.
|
239 | * This value will be URL encoded like so:
|
240 | *
|
241 | * `https://example.com/oauth/authorize?redirect_URI=http%3A%2F%2Flocalhost%2Fredirect...`
|
242 | */
|
243 | redirectUri: string;
|
244 | /**
|
245 | * REQUIRED
|
246 | * A list permission separated by spaces that is the scope of permissions your application is
|
247 | * requesting from the authorization server. If the user is logging in the first time, it may ask
|
248 | * them to approve those permission before authorizing your application.
|
249 | *
|
250 | * > e.g. `openid profile`
|
251 | *
|
252 | * The scopes are sent to the authorization server using `authorizationUrl` endpoint in the
|
253 | * query portion of the URL along with the other parameters.
|
254 | * This value will be URL encoded like so:
|
255 | *
|
256 | * `https://example.com/oauth/authorize?scope=openid%20profile...`
|
257 | */
|
258 | scope: string;
|
259 | /**
|
260 | * OPTIONAL
|
261 | * Some oauth authorities require additional parameters to be passed to the `authorizationUri`
|
262 | * URL in order for the implicit grant flow to work.
|
263 | *
|
264 | * For example: [Auth0--an OAuth2 authority/authorization server--requires the parameters
|
265 | * `nonce`][0]
|
266 | * be passed along with every call to the `authorizationUri`. You can do that like so:
|
267 | *
|
268 | * ```ts
|
269 | * const auth = OAuth2PopupFlow({
|
270 | * authorizationUri: 'https://example.com/oauth/authorize',
|
271 | * clientId: 'foo_client',
|
272 | * redirectUri: 'http://localhost:8080/redirect',
|
273 | * scope: 'openid profile',
|
274 | * // this can be a function or static object
|
275 | * additionalAuthorizationParameters: () => {
|
276 | * // in prod, consider something more cryptographic
|
277 | * const nonce = Math.floor(Math.random() * 1000).toString();
|
278 | * localStorage.setItem('nonce', nonce);
|
279 | * return { nonce };
|
280 | * // `nonce` will now be encoded in the URL like so:
|
281 | * // https://example.com/oauth/authorize?client_id=foo_client...nonce=1234
|
282 | * },
|
283 | * // the token returned by Auth0, has the `nonce` in the payload
|
284 | * // you can add this additional check now
|
285 | * tokenValidator: ({ payload }) => {
|
286 | * const storageNonce = parseInt(localStorage.getItem('nonce'), 10);
|
287 | * const payloadNonce = parseInt(payload.nonce, 10);
|
288 | * return storageNonce === payloadNonce;
|
289 | * },
|
290 | * });
|
291 | * ```
|
292 | *
|
293 | * [0]: https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce
|
294 | */
|
295 | additionalAuthorizationParameters?: {
|
296 | [key: string]: string;
|
297 | } | (() => {
|
298 | [key: string]: string;
|
299 | }) | undefined;
|
300 | /**
|
301 | * OPTIONAL
|
302 | * This function intercepts the `loggedIn` method and causes it to return early with `false` if
|
303 | * this function itself returns `false`. Use this function to validate claims in the token payload
|
304 | * or token.
|
305 | *
|
306 | * [For example: validating the `nonce`:][0]
|
307 | *
|
308 | * ```ts
|
309 | * const auth = OAuth2PopupFlow({
|
310 | * authorizationUri: 'https://example.com/oauth/authorize',
|
311 | * clientId: 'foo_client',
|
312 | * redirectUri: 'http://localhost:8080/redirect',
|
313 | * scope: 'openid profile',
|
314 | * // this can be a function or static object
|
315 | * additionalAuthorizationParameters: () => {
|
316 | * // in prod, consider something more cryptographic
|
317 | * const nonce = Math.floor(Math.random() * 1000).toString();
|
318 | * localStorage.setItem('nonce', nonce);
|
319 | * return { nonce };
|
320 | * // `nonce` will now be encoded in the URL like so:
|
321 | * // https://example.com/oauth/authorize?client_id=foo_client...nonce=1234
|
322 | * },
|
323 | * // the token returned by Auth0, has the `nonce` in the payload
|
324 | * // you can add this additional check now
|
325 | * tokenValidator: ({ payload }) => {
|
326 | * const storageNonce = parseInt(localStorage.getItem('nonce'), 10);
|
327 | * const payloadNonce = parseInt(payload.nonce, 10);
|
328 | * return storageNonce === payloadNonce;
|
329 | * },
|
330 | * });
|
331 | * ```
|
332 | *
|
333 | * [0]: https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce
|
334 | */
|
335 | tokenValidator?: ((options: {
|
336 | payload: {
|
337 | exp: number;
|
338 | };
|
339 | token: string;
|
340 | }) => boolean) | undefined;
|
341 | /**
|
342 | * OPTIONAL
|
343 | * A hook that runs in `tryLoginPopup` before any popup is opened. This function can return a
|
344 | * `Promise` and the popup will not open until it resolves.
|
345 | *
|
346 | * A typical use case would be to wait a certain amount of time before opening the popup to let
|
347 | * the user see why the popup is happening.
|
348 | */
|
349 | beforePopup?: (() => any) | undefined;
|
350 | /**
|
351 | * OPTIONAL
|
352 | * A hook that runs in `handleRedirect` that takes in the result of the hash payload from the
|
353 | * authorization server. Use this hook to grab more from the response or to debug the response
|
354 | * from the authorization URL.
|
355 | */
|
356 | afterResponse?: ((authorizationResponse: {
|
357 | [key: string]: string | undefined;
|
358 | }) => void) | undefined;
|
359 | responseType: string;
|
360 | accessTokenStorageKey: string;
|
361 | accessTokenResponseKey: string;
|
362 | storage: Storage;
|
363 | pollingTime: number;
|
364 | addEventListener: (type: string, listener: EventListenerOrEventListenerObject) => void;
|
365 | dispatchEvent: (event: Event) => boolean;
|
366 | removeEventListener: (type: string, listener: EventListenerOrEventListenerObject) => void;
|
367 | loggedIn: () => boolean;
|
368 | logout: () => void;
|
369 | tokenExpired: () => boolean;
|
370 | handleRedirect: () => "REDIRECT_URI_MISMATCH" | "FALSY_HASH" | "FALSY_TOKEN" | "SUCCESS";
|
371 | tryLoginPopup: () => Promise<"SUCCESS" | "ALREADY_LOGGED_IN" | "POPUP_FAILED">;
|
372 | authenticated: () => Promise<void>;
|
373 | token: () => Promise<string>;
|
374 | tokenPayload: () => Promise<{
|
375 | exp: number;
|
376 | }>;
|
377 | }, "storage" | "responseType" | "token" | "accessTokenStorageKey" | "accessTokenResponseKey" | "pollingTime" | "authorizationUri" | "clientId" | "redirectUri" | "scope" | "additionalAuthorizationParameters" | "tokenValidator" | "beforePopup" | "afterResponse" | "logout" | "addEventListener" | "dispatchEvent" | "removeEventListener" | "loggedIn" | "tokenExpired" | "handleRedirect" | "tryLoginPopup" | "authenticated" | "tokenPayload">;
|
378 | export { FixedTypesOAuth2PopupFlow as OAuth2PopupFlow };
|
379 | export default FixedTypesOAuth2PopupFlow;
|