My new Nuxt module for doing amazing things.
- π REST requests
- π Login, Registration, Logout, session receipt, refresh token
- π§ Flexible system of page protection settings
- β‘ Server shutdown detection system
- Add
nuxt-local-auth
dependency to your project
# Using pnpm
pnpm add -D nuxt-local-auth
# Using yarn
yarn add --dev nuxt-local-auth
# Using npm
npm install --save-dev nuxt-local-auth
- Add
nuxt-local-auth
to themodules
section ofnuxt.config.ts
export default defineNuxtConfig({
modules: [
'nuxt-local-auth'
]
});
That's it! You can now use Nuxt Local Auth in your Nuxt app β¨
Default settings of module. See all interfaces here.
export default defineNuxtConfig({
localAuth: {
origin: '',
sessions: {
refreshEvery: undefined,
cookiePrefix: 'localAuth',
},
token: {
lifetime: 86400,
path: 'token',
type: 'Bearer',
queryKey: undefined,
},
refreshToken: {
enabled: false,
path: 'refresh',
bodyKey: 'refresh',
queryKey: 'refresh'
},
endpoints: {
signIn: { path: 'auth/signIn', method: 'POST' },
getMe: { path: 'users/me', method: 'GET' },
refreshToken: { path: 'auth/refresh', method: 'POST' },
signUp: undefined,
signOut: undefined
},
pages: {
auth: '/login',
defaultRedirect: '/',
handleIsServerDown: false,
protectAllPages: false,
}
}
});
Use useLocalAuth
to get auth context methods. Return interface see here
const auth = useLocalAuth();
type SignInResponse = {
accessToken: string;
};
// You can use type response for all auth methods
auth.signIn<SignInResponse>({
login: 'admin',
password: 'admin'
}).then(res => {
console.log(res.accessToken);
}).catch(e => {
console.error(e);
});
// nuxt.config.ts
export default defineNuxtConfig({
localAuth: {
refreshToken: {
enabled: true,
bodyKey: 'refresh'
},
endpoints: {
refreshToken: { path: 'auth/refresh/', method: 'POST' },
}
}
});
Since to update the token, you need to execute the {origin}/{endpoints/refreshToken/path}
request by passing the token in its body, you need to specify under which key the token will be transferred. To do this, there is a bodyKey
parameter in the refreshToken
section
After enabling refresh tokens, the refreshToken
and refreshTokenWithCheck
methods will stop giving an error.
const { refreshToken, refreshTokenWithCheck } = useLocalAuth();
// Forced update token
await refreshToken();
// Check whether the token is rotten or not, and then update
await refreshTokenWithCheck();
How does the refreshTokenWithCheck
function understand when to update the token? It's simple! In the token
section, you can find the lifetime
parameter, which, by default, has a value of 86400
seconds, which is equal to one day, after logging in. You can change this value to set the token lifetime, or specify the path to the value from the authorization response that the server will return.
Example:
- Server response
{ "accessToken": "...", "refreshToken": "...", "exp": 123123 }
- You need to set the value
lifetime
:'exp'
To use authorization via the url string, you need to set the value of this key in the token
section, the queryKey
key. After that, the mechanism will start working. It is also possible to read the refresh
token from the query string, the key is set as refresh
by default, but it will not work without enabling the main token
.
// nuxt.config.ts
export default defineNuxtConfig({
localAuth: {
token: {
queryKey: 'token'
},
refreshToken: {
enabled: true,
queryKey: 'refresh'
},
pages: {
auth: 'login'
}
}
});
The query string will look like this: {clientOrigin}/{pages/auth}?{token/queryKey}=...&{refreshToken/queryKey}=...
Work example: http://localhost:3000/login?token=...&refresh=...
As a result, an automatic login will be performed. If the refresh token is not passed, the system will also be able to start, but all methods of updating the token will stop working
Page protection can be organized in two ways: global protection and configuration of a specific page, via definePageMeta
-
Global Protecting
// nuxt.config.ts export default defineNuxtConfig({ localAuth: { pages: { auth: 'login', protectAllPages: true } } });
-
definePageMeta
<!-- pages/login.vue--> <script lang="ts" setup> // Example #1 - disable middleware definePageMeta({ localAuth: false }); // Example #2 - enable middleware definePageMeta({ localAuth: true }); // Example #3 - authorized users only definePageMeta({ localAuth: { authorizedOnly: true } }); // Example #4 - unauthorized users only definePageMeta({ localAuth: { unauthorizedOnly: true } }); // Example #5 - closed page from all π definePageMeta({ localAuth: { authorizedOnly: true, unauthorizedOnly: true } }); </script>
The module has a mechanism for catching long responses, or domain unavailability. In such cases, the module will redirect the user to the error page, which can be set in the pages
serverIsDown
section.
// nuxt.config.ts
export default defineNuxtConfig({
localAuth: {
pages: {
serverIsDown: '/error'
}
}
});
If the server returns an error code, a logout
will be performed, and the user will be redirected to the page specified in auth
. After logging in, the user will be directed to defaultRedirect
, which can be changed for a specific case in the config of the method itself, passing the path in the redirectTo
key.
interface ModuleOptions {
/* Path to server. Default: ''
* Example: 'http://localhost:8000/api/v1' - remote server
* Example: 'api' - local nuxt server
* */
origin: string;
/* Config Cookie settings and additional options */
sessions: ModuleOptionsSession;
/* Main token config */
token: ModuleOptionsToken;
/* Refresh token config */
refreshToken: ModuleOptionsRefreshToken;
/* Config endpoints to server routes */
endpoints: ModuleOptionsEndpoints;
/* Pages redirecting config */
pages: ModuleOptionsPages;
}
interface ModuleOptionsSession {
/* Enabled refresh user data every N ms. Default: undefined
* Example: one getMe request in 5 seconds. value > 5000
* Example: disable refresh. value > undefined
* */
refreshEvery?: number;
/* Cookie prefix in app storage. Default: localAuth
* Example: localAuth:token -> {token}
* */
cookiePrefix?: string;
}
interface ModuleOptionsToken {
/* Lifetime token in seconds. Default: 86400
* number: value in seconds
* * Example: 1 day > value: 86400
* string: path to auth expire key
* * Example #1: { expireIn: 86400 } > value: 'expireIn'
* * Example #2: { data: { expireIn: 86400 } } > value: 'data/expireIn'
* */
lifetime?: number | string;
/* Path to token data. Default: 'token'
* Example #1: { token: '...' } > value: 'token'
* Example #2: { data: { accessToken: '...' } } > value: 'data/accessToken'
* */
path: string;
/* Token type. Default: 'Bearer' */
type?: string;
/* Reading the token from the query parameter of the url string. Default: undefined
* Example #1: https://.../{pages/auth}?token=.... value > 'token'
* Example #2: reading is disabled. value > undefined
* */
queryKey?: string;
}
interface ModuleOptionsRefreshToken {
/* Enabled refresh sessions in app. Default: false */
enabled: boolean;
/* Path to refresh token data. Default: 'refresh'
* Example #1: { refresh: '...' } > value: 'refresh'
* Example #2: { data: { refreshToken: '...' } } > value: 'data/refreshToken'
* */
path?: string;
/* Name of key token in body request. Default: 'refresh'
* Example: { refresh '...' } > value: 'refresh'
* */
bodyKey?: string;
/* Reading the token from the query parameter of the url string. Default: 'refresh'
* Example #1: https://.../{pages/auth}?refresh=.... value > 'refresh'
* Example #2: reading is disabled. value > undefined
* */
queryKey?: string;
}
interface ModuleOptionsEndpoints {
/* Auth config. Default:
* path: 'auth/signIn'
* method: 'POST'
* */
signIn: ModuleOptionsEndpointConfig;
/* Get authorized user info config. Default:
* path: 'users/me'
* method: 'GET'
* */
getMe: ModuleOptionsEndpointConfig;
/* Refresh token config. Default:
* path: 'auth/refresh
* method: 'POST'
* */
refreshToken?: ModuleOptionsEndpointConfig;
/* Registration user config. Default: undefined -> disabled */
signUp?: ModuleOptionsEndpointConfig;
/* Logout config. Default: undefined -> disabled */
signOut?: ModuleOptionsEndpointConfig;
}
interface ModuleOptionsPages {
/* Page for authorization in the system. Default: '/login' */
auth?: string;
/* The standard page where to redirect the user after logging in. Default: '/' */
defaultRedirect?: string;
/* A page for catching a server shutdown when it is impossible to
* get session data due to a timeout. Default: false
* Example #1: use error.vue. value > true
* Example #2: use handler is disabled. value > false
* */
handleIsServerDown?: boolean;
/* Protecting all pages from guests. Default: false */
protectAllPages?: boolean
}
interface ModuleOptionsEndpointConfig {
path: string;
method: 'POST' | 'GET';
}
interface UseLocalAuthReturn extends UseLocalAuthReturnData, UseLocalAuthReturnMethods {}
interface UseLocalAuthReturnData {
data: ComputedRef<UseLocalAuthCredentials>;
meta: Ref<UseLocalAuthSession>;
token: ComputedRef<string | null>;
}
interface UseLocalAuthReturnMethods {
signIn<T extends UseLocalAuthResponse = {}>(data: UseLocalAuthData, config?: UseLocalAuthConfig): Promise<T>;
signUp<T extends UseLocalAuthResponse = {}>(data: UseLocalAuthData, config?: UseLocalAuthConfig): Promise<T>;
signOut<T extends UseLocalAuthResponse = {}>(config?: UseLocalAuthConfig): Promise<T>;
getMe<T extends UseLocalAuthResponse = {}>(): Promise<T>;
refreshToken<T extends UseLocalAuthResponse = {}>(): Promise<T>;
refreshTokenWithCheck<T extends UseLocalAuthResponse = {}>(): Promise<T | null>;
checkAndSaveQueryAuth(): Promise<void>;
}
type UseLocalAuthData = {
[name: string]: string;
};
type UseLocalAuthResponse = {
[name: string]: any;
};
type UseLocalAuthCredentials = {
[name: string]: any;
};
type UseLocalAuthConfig = {
redirectTo: string;
};
type UseLocalAuthStatus =
| 'authorized'
| 'unauthorized'
| 'unknown'
| 'timeout';