@merkaly/nuxt 0.13.3 → 0.13.5
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.
package/README.md
CHANGED
|
@@ -169,6 +169,10 @@ To open the Auth0 signup screen instead of the login one, use `useAuth().signup(
|
|
|
169
169
|
|
|
170
170
|
The SPA keeps the session with **refresh tokens**: the client uses `useRefreshTokens` with `localStorage` cache and logs in with `audience` and `scope: openid profile email offline_access`. Before each API call the module asks Auth0 for the current access token, which is cached and renewed with the refresh token once it expires (2 hours for `https://api.merkaly.io`). When the refresh token is gone or expired, protected surfaces (`requiresAuth: true`) go back to login instead of calling the API without a token. Account linking (`linkWithConnection(connection)`) uses a separate Auth0 client, the `auth.merkaly.io` SPA client in Auth0, with an in-memory cache, created only on the first call (no extra `checkSession` on page load). It opens a login popup for that connection and sends the popup's raw ID token to `POST /auth/identities` as `{ idToken }`; the api verifies the token (signature, issuer, audience = the account linking client, expiry) and links the identity from its `sub` into the logged-in user. Requires an api with that contract (older clients that sent `{ provider, userId }` get `400`).
|
|
171
171
|
|
|
172
|
+
### Calling app header
|
|
173
|
+
|
|
174
|
+
Every API request carries the app's Auth0 client id (`merkaly.auth0.client`) in the `x-merkaly-client` header: the `$api` plugin adds it to server-side calls and the `/api` proxy sets it on every forwarded request (overwriting whatever the browser sent). The api checks it against its list of Auth0 applications and, on authenticated requests, against the token `azp` (api doc: [`docs/conventions/surface-clients.md`](https://github.com/merkaly-io/api.merkaly.io/blob/master/docs/conventions/surface-clients.md)). An app without `merkaly.auth0.client` sends no header.
|
|
175
|
+
|
|
172
176
|
The Auth0 side (tenant, API, app settings, refresh token rotation and lifetimes, organizations, and the checklist for a new app) is documented in the auth.merkaly.io repo: [`docs/tenant-setup.md`](https://github.com/merkaly-io/auth.merkaly.io/blob/master/docs/tenant-setup.md).
|
|
173
177
|
|
|
174
178
|
## SEO: robots and sitemap
|
package/dist/module.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getCurrentInstance, onServerPrefetch, reactive, ref, useNuxtApp, useState } from "#imports";
|
|
2
2
|
function useApi(callback) {
|
|
3
3
|
const { $api } = useNuxtApp();
|
|
4
|
-
|
|
4
|
+
let controller = new AbortController();
|
|
5
5
|
const params = reactive({});
|
|
6
6
|
const getOptions = (currentParams) => {
|
|
7
7
|
const options = callback(currentParams);
|
|
@@ -23,6 +23,8 @@ function useApi(callback) {
|
|
|
23
23
|
params[key2] = args[key2];
|
|
24
24
|
});
|
|
25
25
|
const currentOptions = getOptions(params);
|
|
26
|
+
controller = new AbortController();
|
|
27
|
+
loading.value = true;
|
|
26
28
|
await $api(currentOptions.uri, {
|
|
27
29
|
...currentOptions,
|
|
28
30
|
controller,
|
|
@@ -32,10 +34,7 @@ function useApi(callback) {
|
|
|
32
34
|
loading,
|
|
33
35
|
meta,
|
|
34
36
|
params
|
|
35
|
-
}).
|
|
36
|
-
loading.value = false;
|
|
37
|
-
throw reason;
|
|
38
|
-
});
|
|
37
|
+
}).finally(() => loading.value = false);
|
|
39
38
|
};
|
|
40
39
|
if (initialOptions.immediate) {
|
|
41
40
|
const instance = getCurrentInstance();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { defineNuxtPlugin, useNuxtApp, useRequestURL, useRuntimeConfig } from "#app";
|
|
2
2
|
import { useAuth, useOrganization } from "#imports";
|
|
3
3
|
const GLOBAL_API_HEADER = "x-merkaly-global";
|
|
4
|
+
const CLIENT_HEADER = "x-merkaly-client";
|
|
4
5
|
function serverBaseURL(api, global) {
|
|
5
6
|
const prefix = global ? "" : (api.prefix ?? "").replace(/^\/+|\/+$/g, "");
|
|
6
7
|
return prefix ? `${api.url.replace(/\/+$/, "")}/${prefix}` : api.url;
|
|
@@ -35,6 +36,7 @@ This surface has requiresTenant: true. Possible causes:
|
|
|
35
36
|
[GLOBAL_API_HEADER]: options.global ? "true" : "",
|
|
36
37
|
...requestHost ? { "x-merkaly-host": requestHost } : {},
|
|
37
38
|
// tenant host, as the proxy sends it
|
|
39
|
+
...merkaly.auth0.client ? { [CLIENT_HEADER]: merkaly.auth0.client } : {},
|
|
38
40
|
...options?.headers
|
|
39
41
|
},
|
|
40
42
|
method: options?.method,
|
|
@@ -2,6 +2,7 @@ import { defineEventHandler, getRequestURL, proxyRequest } from "h3";
|
|
|
2
2
|
import { useRuntimeConfig } from "#imports";
|
|
3
3
|
const GLOBAL_API_HEADER = "x-merkaly-global";
|
|
4
4
|
const TENANT_HOST_HEADER = "x-merkaly-host";
|
|
5
|
+
const CLIENT_HEADER = "x-merkaly-client";
|
|
5
6
|
const API_PREFIX_PATTERN = /^\/api\/?/;
|
|
6
7
|
const API_ROUTE_PATTERN = /^\/api(?:\/|$)/;
|
|
7
8
|
const EDGE_SLASH_PATTERN = /^\/|\/$/g;
|
|
@@ -33,6 +34,8 @@ export default defineEventHandler((event) => {
|
|
|
33
34
|
const path = resolveProxyPath(prefix, url.pathname, url.search);
|
|
34
35
|
event.node.req.headers["x-forwarded-host"] = url.host;
|
|
35
36
|
event.node.req.headers[TENANT_HOST_HEADER] = url.host;
|
|
37
|
+
if ($config.merkaly.auth0.client) event.node.req.headers[CLIENT_HEADER] = $config.merkaly.auth0.client;
|
|
38
|
+
else Reflect.deleteProperty(event.node.req.headers, CLIENT_HEADER);
|
|
36
39
|
stripEdgeHeaders(event.node.req.headers);
|
|
37
40
|
if (import.meta.dev && targetOrigin.hostname.endsWith(".test")) {
|
|
38
41
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|