Auth
Auth is an autentication package for react.js client applications. This package works with Hilma servers, like auth-nest or hilma-auth-server (for Loopback
applications.)
-
Auth
- Installation
- Main exports:
- Storage explanation
Installation
npm install --save @hilma/auth @hilma/tools axios react-router-dom
Main exports:
AuthProvider - component
AuthProvider
is the main component needed from this package. It includes all the logic and methods needed for your application. AuhtProvider
is as wrapping component that uses context to pass all its logic to the rest of your application. Before implemetation, let's examine some of the logic in AuthProvider
. There's an object stored in the component called storage
. This object includes 6 fields, all of which are either a string or null. They all come from the browser's cookies:
key | description |
---|---|
kl | an encoded version of the role keys of the authenticated user |
klo | an encoded version of roleAccessConfig. Find more info in Hilma docs |
kloo | a random string |
klk | a random string |
access_token (or what ever you choose) | the current users access token |
two_factor_token (or what ever you choose) | The current JSON Web Token created durring the 2FA process |
Most of the methods and properties stored in AuthProvider
use this object in some way, whether it being for making fetch request, or showing certain components to the client. Further explanation about storage: Storage explanation
Let's look at an example of how to implement AuthProvider
:
App.js
:
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { AuthProvider } from '@hilma/auth';
import Admin from './components/Admin';
import Client from './components/Client';
import Login from './components/Login';
const App = () => (
<Router>
<AuthProvider>
<Switch>
<Route path="/admin" component={Admin} />
<Route path="/client" component={Client} />
<Route path="/login" component={Login} />
</Switch>
</AuthProvider>
</Router>
);
export default App;
If you want to make this shorter you can use provide
from the @hilma/tools
package:
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { AuthProvider } from '@hilma/auth';
import { provide } from '@hilma/tools';
import Admin from './components/Admin';
import Client from './components/Client';
import Login from './components/Login';
const App = () => (
<Switch>
<Route path="/admin" component={Admin} />
<Route path="/client" component={Client} />
<Route path="/login" component={Login} />
</Switch>
);
export default provide(Router, AuthProvider)(App);
AuthProvider Props
prop | type | required | description | default |
---|---|---|---|---|
logoutOnUnauthorized | boolean |
false | If true, when a fetch request is made via superAuthFetch or authFetch and the user is unauthorized, the logout function will invoked | false |
ref | React.Ref<HilmaAuth> |
false | If you want a reference to the auth object pass a ref. This will be explored later on | |
accessTokenCookie | string |
false (if your'e using loopback don't use this prop) | the key of your access token. make sure its the same in your server (in nestjs its in configuration.ts) every application should have a different key. make sure its not obvious that its the access token. make its similar to your other cookies like kloook | 'access_token' |
basename | string |
false | this will be put be added to every request that you make, including the proxy of your app | '' |
inactivityTime | boolean |
false | if true, if your app has not been interacted with after ten minutes, the logout function will be invoked. this is needed in some project | false |
twoFactorCookie | string |
false | The cookie name in which a two factor cookie is stored | 'two_factor_token' |
Auth Properties
Now let's look at whats included in the auth object:
property | type | description |
---|---|---|
kls | { kl: string | null; klo: string | null; }; |
includes the kl and klo stored in AuthProvider (from the browser's cookies). You will most likely not need to access this property |
setAuthItem | setAuthItem(key: keyof Storage, value: string, setLocalStorage?: boolean, setCookies?: boolean, changeStorage?: boolean): Promise<Storage>; |
Sets the key value pair in AuthProvider and cookies |
multiSetAuthItem | multiSetAuthItem(keyValuePairs: string[][], setLocalStorage?: boolean, setCookies?: boolean, changeStorage?: boolean): Promise<Storage>; |
Sets multiple key value pairs in storage |
getAuthItem | getAuthItem(key: keyof Storage): string | null; |
Returns the auth storage item |
removeAuthItem | removeAuthItem(key: keyof Storage): void; |
Removes the item from AuthProvider and cookies |
getAccessToken | getAccessToken(): string | null; |
Returns the acces token |
isAuthenticated | boolean |
If true, the user is authenticated |
hasTwoFactorToken | boolean |
If true, the user has a two factor token |
logout | logout(deleteTwoFactorToken?: boolean): Promise<Storage>; |
Removes all storage in AuthProvider |
superAuthFetch | superAuthFetch(input: RequestInfo, init?: RequestInit | undefined): Promise<[any, any]>; |
Will fetch from data from the server. @param input the url. @param init. @returns A Promise with the resloved value being a tuple of the response and the error (if one accured) |
authFetch | authFetch(input: RequestInfo, init?: RequestInit | undefined): Promise<any>; |
Will fetch from data from the server. @param input the url. @param init. @returns A Promise with the resloved value being the response. the response will already be in json format |
login | login(input: string, body: Record<'password' | 'username' | 'email', string>): Promise<{ success: boolean; user?: any; msg?: any; }>; |
Log in function @param body The body you want to send to the server. example: { email: hilma@gmail.com , password: somepassword } @param input The login endpoint. @returns A Promise with the resolved value being an object: { success: boolean; user?: any; msg?: any; }
|
sendCode | sendCode(input: string, body: Partial<Record<'password' | 'username' | 'email', string>>): Promise<{ success: boolean; data?: any; msg?: any; }>; |
Send a code to a user in a 2FA process |
loginWithCode | loginWithCode(input: string, code: string): Promise<{ success: boolean; user?: any; msg?: any; }>; |
login with a code in a 2FA process |
interceptors | `Record<'proxyAndHeadersId' | 'capacitorHeadersId' |
Accessing the auth object:
Now let's see how we actually access all these properties. There are a few ways to access all these propeties:
via Context:
AuthProvider
is mainly built on React's Context API which allows you to access a certain value in any part of an application. There are two ways to access via The Context API:
-
Recommended: Each property has its own context object (kls:
KlsContext
, superAuthFetch:SuperAuthFetchContext
, and so on...). Each one of these context objects also include a custom hook that returns the property (kls:useKls
, superAuthFetch:useSuperAuthFetch
, and so on...).
import { useSuperAuthFetch } from '@hilma/auth';
// in some functional component
const superAuthFetch = useSuperAuthFetch();
if you are using class-based components you can use the withContext
HOC from @hilma/tools
:
import React, { Component } from 'react';
import { SuperAuthFetchContext, LoginContext } from '@hilma/auth';
import { withContext } from '@hilma/tools';
class MyComp extends Component {
async doSomething() {
const [res, err] = await this.props.superAuthFetch('...');
const loginRes = await this.props.login(res, '/api/....');
}
render() {
return <div></div>;
}
}
// this object represents how the values will be passed via props, the key being the prop name and the value being the context object.
const mapContextToProps = {
superAuthFetch: SuperAuthFetchContext,
login: LoginContext
}
export default withContext(mapContextToProps)(MyComp);
-
Not Recommended: You can access the whole auth object via the
AuthContext
context object. You can also use theuseAuth
hook or thewithAuth
HOC. The reason this method is not recommended is because each time you access this context object, you are recieving the whole object. It is very unlikeky you'll need to access the whole object. The performance of your application will drop significantly. So please use the first method.
useAuth:
import { useAuth } from '@hilma/auth';
// in some functional component
const { superAuthFetch } = useAuth();
withAuth:
import React, { Component } from 'react';
import { withAuth } from '@hilma/auth';
class MyComp extends Component {
async doSomething() {
const [res, err] = await this.props.auth.superAuthFetch('...');
const loginRes = await this.props.auth.login(res, '/api/....');
}
render() {
return <div></div>;
}
}
export default withAuth(MyComp);
via Refs:
Another way you can access the auth object is via React's refs. This method is useful if you want to access auth outside of components, like in redux middleware or mobx stores.
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { AuthProvider, createAuthRef } from '@hilma/auth';
import Admin from './components/Admin';
import Client from './components/Client';
import Login from './components/Login';
export const authRef = createAuthRef();
const App = () => (
<Router>
<AuthProvider ref={authRef}>
<Switch>
<Route path="/admin" component={Admin} />
<Route path="/client" component={Client} />
<Route path="/login" component={Login} />
</Switch>
</AuthProvider>
</Router>
);
export default App;
In the file where you use AuthProvider
import createAuthRef
, invoke the function. this returns a ref object. A ref object is an object that includes one property which is current
. current
holds the value stored in the ref object. In AuthProvider we use forwardRef's to pass the auth object to the provided ref. Now when you want to access the auth object you can export the ref and access the properties via authRef.current:
import { authRef } from './App';
class ErrorStore {
async addError() {
const [res, err] = await authRef.current.superAuthFetch('....');
}
}
Making http requests
An important part of an application is making requests to a server. The process of making a request with the fetch
api provided by the browser is very limited and doesn't provide much customization. In this package there are two main ways you can make requests: Axios
and superAuthFetch
. Let's take a look at these methods:
before we get in to that, make sure in package.json
your proxy is set to your server. example:
"proxy": "http://127.0.0.1:8080"
Axios - new approach (recommended)
Axios
is a Promise based HTTP client for the browser and node.js. It's recommended that you read the docs first: https://github.com/axios/axios. Axios
is a very simple package but it also comes with a lot of very useful features. The main feature we use in auth is interceptors. Interceptors can intercept requests or responses before they are handled by then or catch. That allows us to add some very useful functionality. There a three interceptors that we create in auth. their ids are stored in AuthProvider
in the interceptors
key so you can cancel them at any time (although there should be no reason to do so):
- proxyAndHeadersId: this interceptor adds before every request the proxy of the server so you don't have to write 'http://localhost:8080/...' every time, and it adds some basic headers to requests: 'Content-Type': 'application/json', 'Accept': 'application/json'.
-
capacitorHeadersId: this interceptor adds two headers to a request if the application is running in
Capacitor
: 'Authorization', 'Cookie'. In aCapacitor
environment, there's no browser cookies so you need to store information inlocalStorage
and send them in every request in theCookie
header. -
logoutId: this interceptor checks if the status code of a response is 401 (Unauthorized) and if so, dispatches the
logout
function. It also changes the default error given byAxios
: the default error object thrown byAxios
has a lot of fields that are not very useful and rarely needed. The error this interceptor throws has only the important stuff in it.
A very big benefit of using Axios
over the next approach is that there is nothing special you need to import or do. Just use it as if noting has changed. It can be easily used in mobx
or redux
.
example:
import Axios from 'axios';
const MyComp = () => {
const [user, setUser] = useState(null);
useEffetct(() => {
(async () => {
try {
const res = await Axios.get('/api/users/1');
setUser(res.data);
} catch (error) {
console.error(error);
}
})();
}, [);
return <div></div>;
}
superAuthFetch - old approach (not recommended)
This approach is based on the fetch API given by the browser. superAuthFetch is very similar to fetch
: It calls fetch with the same parameters but instead of returning the default response object, it returns an array: The first item being the json response of the request, and the second item being the error of the request (if there was one). This function also adds default headers, logs out on 401 statuses, and adds cookie headers if your using it in a Capacitor
environment, just like in Axios
Accessing superAuthFetch
:
superAuthFetch
is stored in AuthProvider
and therefore can only be accessed thrhough its equivalent Context object or a ref object passed to AuthProvider
. If you need a reminder, go back to the 'Accessing the auth object' section. In short, for using Context you have the SuperAuthFetchContext
Context object, the useSuperAuthFetch
hook that returns that object, and withContext
from @hilma/tools
for class components.
useSuperAuthFetch
example:
import { useSuperAuthFetch } from '@hilma/auth';
const MyComp = () => {
const [user, setUser] = useState(null);
const superAuthFetch = useSuperAuthFetch();
useEffetct(() => {
(async () => {
const [res, err] = await superAuthFetch('/api/users/1');
if (err) return console.error(err);
setUser(res);
})();
}, [);
return <div></div>;
}
Private Routes
A very important part of the auth package is private routes. What are private routes? the are different routes in an application that we only want certain uesrs to be able to access. say we have a route that shows a list of a teacher's students, we only want to expose that route if ah user is authenticated. There are four different private route components and they all extend the functionality of the Route
component from react-router-dom
therefore all the props of that components apply to these components (except the render
and children
prop):
react-router-dom@^5
and below -> @hilma/auth < 1.*.*
.
Examples for PrivateRoute:
You would use this component if you want your component to only accessible when a user is logged in and authenticated.
There are two version, and you should check that you are using the right version of react-router-dom
.
PrivateRoute Props:
prop | type | required | description | default |
---|---|---|---|---|
componentName | string |
true | if the user is authenticated and its roleAccessConfig includes this string you can access this component | |
redirectComponent | Required<RouteProps>['component'] |
false | if the client is not allowed to access the route then this component will be rendered instead | |
redirectPath | string |
false | if the redirectComponent is not provided, this prop will be navigated to |
"/" |
path | string |
true | regular route path | |
component |
React.Component or function
|
true | component to display for authorized users |
MultipleRoute:
If you want components rendered under the same route name but render different components per role. For example: if we have 2 components: TeacherSchedule
and StudentSchedule
, now you want them to be rendered under the same route: /schedule
, You want that when a user with a Teacher
role is logged in, they will see the TeacherSchedule
component and for a Student
role, StudentSchedule
. MultipleRoute
was made just for this. Note that this component doesn't recieve a component
prop.
MultipleRoute Props:
prop | type | required | description | default |
---|---|---|---|---|
components | Record<string, Required<RouteProps>['component']> |
true | an object where the key being the component name that appears in roleAccessConfig and the value the component that you want to render | |
redirectComponent | Required<RouteProps>['component'] |
false | if the client is not allowed to access the route then this component will be rendered instead | |
redirectpath | string |
false | if the redirectComponent is not provided, this prop will be navigated to |
"/" |
path | string |
true | regular route path |
HomeRoute:
Similar to Multiple route but instead of going to see if the component names are in the components
in roleAccessConfig, it goes to defaultHomePage
. This compnent is good if you want a main route per role.
HomeRoute Props:
prop | type | required | description | default |
---|---|---|---|---|
components | Record<string, Required<RouteProps>['component']> |
true | an object where the key being the component name that appears in roleAccessConfig and the value the component that you want to render | |
redirectComponent | Required<RouteProps>['component'] |
false | if the client is not allowed to access the route then this component will be rendered instead | |
redirectPath | string |
false | if the redirectComponent is not provided, this prop will be navigated to |
"/" |
path | string |
true | regular route path |
PublicOnlyRoute:
When a user is authenticated, a PrivateRoute
will be rendered and if not a regular Route
will be rendered. That means that if a user is not authenticated the component will be rendered and when not will be redirected
PublicOnlyRoute Props:
The props are the exact same as PrivateRoute
.
Example
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { AuthProvider, PrivateRoute, HomeRoute, MultipleRoute } from '@hilma/auth';
import Admin from './components/Admin';
import AdminComp from './components/AdminComp';
import Client from './components/Client';
import ClientComp from './components/ClientComp';
import Login from './components/Login';
import NotFound from './components/NotFound';
const App = () => (
<Router>
<AuthProvider>
<Switch>
<PrivateRoute path="/admin" component={Admin} componentName="adminComp" redirectComponent={NotFound} />
<HomeRoute path="/" components={{ adhome:Admin, clientHome:Client}} redirectPath="/login">
<MultipleRoute path="/pathToSomewher" components={{ comp:ClientComp, AdminComp:Client}} redirectPath="/login">
<Route path="/login" component={Login} />
</Switch>
</AuthProvider>
</Router>
);
export default App;
react-router-dom@^6
-> @hilma/auth@^1
.
Examples for Because Routes
component insists on having only Route
s or Fragment
as children- instead of rendering routes the auth-routes will render the component if access is allowed, and redirect otherwise .
PrivateRoute:
PrivateRoute Props:
prop | type | required | description | default |
---|---|---|---|---|
componentName | string |
true | if the user is authenticated and its roleAccessConfig includes this string you can access this component | |
redirectComponent | ReactElement<any, any> | React.FC |
false | if the client is not allowed to access the route then this component will be rendered instead | |
redirectPath | string |
false | if the redirectComponent is not provided, this prop will be navigated to |
"/" |
component | ReactElement<any, any> | React.FC |
true | component to display for authorized users |
MultipleRoute:
If you want components rendered under the same route name but render different components per role. For example: if we have 2 components: TeacherSchedule
and StudentSchedule
, now you want them to be rendered under the same route: /schedule
, You want that when a user with a Teacher
role is logged in, they will see the TeacherSchedule
component and for a Student
role, StudentSchedule
. MultipleRoute
was made just for this. Note that this component doesn't recieve a component
prop.
MultipleRoute Props:
prop | type | required | description | default |
---|---|---|---|---|
components | Record<string, ReactElement<any, any> | React.FC> |
true | an object where the key being the component name that appears in roleAccessConfig and the value the component that you want to render | |
redirectComponent | ReactElement<any, any> | React.FC |
false | if the client is not allowed to access the route then this component will be rendered instead | |
redirectpath | string |
false | if the redirectComponent is not provided, this prop will be navigated to |
"/" |
HomeRoute:
Similar to Multiple route but instead of going to see if the component names are in the components
in roleAccessConfig, it goes to defaultHomePage
. This compnent is good if you want a main route per role.
HomeRoute Props:v1
prop | type | required | description | default |
---|---|---|---|---|
components | Record<string, ReactElement<any, any> | React.FC> |
true | an object where the key being the component name that appears in roleAccessConfig and the value the component that you want to render | |
redirectComponent | ReactElement<any, any> | React.FC |
false | if the client is not allowed to access the route then this component will be rendered instead | |
redirectPath | string |
false | if the redirectComponent is not provided, this prop will be navigated to |
"/" |
PublicOnlyRoute:
When a user is authenticated, a PrivateRoute
will be rendered and if not a regular Route
will be rendered. That means that if a user is not authenticated the component will be rendered and when not will be redirected
PublicOnlyRoute Props:v1
The props are the exact same as PrivateRoute
.
Example - react-router-dom v6
Notice- you can pass the component as jsx
element, or by component name.
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { AuthProvider, PrivateRoute, HomeRoute, MultipleRoute } from '@hilma/auth';
import Admin from './components/Admin';
import AdminComp from './components/AdminComp';
import Client from './components/Client';
import ClientComp from './components/ClientComp';
import Login from './components/Login';
import NotFound from './components/NotFound';
const App = () => (
<AuthProvider>
<Router>
<Routes>
<Route path="admin" element={<PrivateRoute component={<Admin/>} componentName="adminComp" redirectComponent={NotFound} />} />
<Route path="/" element={<HomeRoute components={{ adhome:Admin, clientHome:Client}} redirectPath="/login"/>} />
<Route path="pathToSomewhere" element={<MultipleRoute components={{ comp:ClientComp, AdminComp:Client}} redirectPath="/login"/>} />
<Route path="/login" component={Login} />
</Routes>
</Router>
</AuthProvider>
);
export default App;
UserProvider - components
A very useful component if you would like to get a current authenticated user. What this component will do is the following: Each time your access token changes, a new request will be made. It is up to you to decide what that request is. The request will be made with Axios
. When the request is completed, the response will be stored in the UserContext
context object:
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { AuthProvider, UserProvider } from '@hilma/auth';
import Admin from './components/Admin';
import Client from './components/Client';
import Login from './components/Login';
const App = () => (
<Router>
<AuthProvider>
<UserProvider url="/api/users/getUser">
<Switch>
<Route path="/admin" component={Admin} />
<Route path="/client" component={Client} />
<Route path="/login" component={Login} />
</Switch>
</UserProvider>
</AuthProvider>
</Router>
);
export default App;
UserProvider Props:
prop | type | required | description | default |
---|---|---|---|---|
url | string |
ture | The url that you want to make a request to | |
config | AxiosRequestConfig |
false | the request payload for Axios
|
|
onFinish | onFinish?<U extends any>(user: U): void; |
false | will be invoked with the response | |
onNoAccessToken | onNoAccessToken?(): void; |
false | will be invoked when there is no access token | |
onError | onError?(error: any): void; |
false | will be invoked when an error occurred | |
ref | React.Ref<any> |
false | will inject the user into the ref |
Accessing the user value:
The way the user is stored is almost identical to the auth object:
via Context:
UserProvider
is mainly built on React's Context API which allows you to access a certain value in any part of an application. You can use the UserContext
context object however you want.
There is a custom hook that accesses the UserContext
value: useUser
:
import { useUser } from '@hilma/auth';
// in some functional component
const user = useUser();
There is also a HOC that can pass the user via props called withUser
:
import React, { Component } from 'react';
import { withUser } from '@hilma/auth';
class MyComp extends Component {
render() {
<div>{this.props.user}</div>
}
}
export default withUser(MyComp);
via Refs:
Another way you can access the user object is via React's refs. This method is useful if you want to access auth outside of components, like in redux middleware or mobx stores.
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { AuthProvider, UserProvider, createUserRef } from '@hilma/auth';
import Admin from './components/Admin';
import Client from './components/Client';
import Login from './components/Login';
export const userRef = createUserRef();
const App = () => (
<Router>
<AuthProvider>
<UserProvider url="/api/users/getUser" ref={userRef}>
<Switch>
<Route path="/admin" component={Admin} />
<Route path="/client" component={Client} />
<Route path="/login" component={Login} />
</Switch>
</UserProvider>
</AuthProvider>
</Router>
);
export default App;
In the file where you use UserProvider
import createUserRef
, invoke the function. this returns a ref object. A ref object is an object that includes one property which is current
. current
holds the value stored in the ref object. In UserProvider we use forwardRef's to pass the user value to the provided ref. Now when you want to access the auth object you can export the ref and access the properties via userRef.current:
import { userRef } from './App';
class ErrorStore {
async addError() {
const id = userRef.current.id;
///....
}
}
privatize - HOC (function)
A HOC that renders a component only if the user is authenticated and the component is in roleAccessConfig. If the component is not in roleaccessconfig then nothing is rendered.
privatize params:
param | type | required | description | default |
---|---|---|---|---|
Component | React.ComponentType<P> |
ture | The Component you want to privatize | |
componentName | string |
true | The component's name to look up in roleaccessconfig | |
DefaultComponent | React.ComponentType<any> |
false | The component that's rendered if you cant access the component | () => null |
example:
import React from 'react';
import { privatize } from '@hilma/auth';
const MyComp = () => {
return <div>Im private</div>;
}
export default privatize(MyComp);
import React from 'react';
import MyComp from './MyComp';
const App = () => {
// will only be rendered if the name is in roleaccessconfig
return <div><MyComp /></div>;
}
export default App;
useKlskDhp - hook
import { useKlskDhp } from '@hilma/auth';
// in some functional component
const klskDhp = useKlskDhp();
use this hook if you want to know the current roleaccessconfig thats decoded. this is more part of the private api but you can still use it.
the hook returns an object. here are the key value pairs:
key | type | description |
---|---|---|
klsk | string[] |
this represents the components from roleaccessconfig |
dhp | string |
this represents the defaultHomePage from roleaccessconfig |
useRoleKeys - hook
import { useRoleKeys } from '@hilma/auth';
// in some functional component
const roleKeys = useRoleKeys();
use this hook if you want to get the decoded version of the kl
cookie.
the hook returns an array of strings.
Storage explanation
In AuthProvider
there is a state object named storage
. This object is a copy of some of your browser's cookies (or localStorage if you're using Capacitor). The reason we need the cookies stored in state is we need a stateful representation of the cookies. For example, if we need to redirect a client to a different page because his access token was deleted or if a token was created, then we need to detect that the token was deleted or created.
Every time we expect to receive new cookies from a server, we need to update the storage
object. For example, after logging in we need to add the access token to the object. If you're using the built in login
function from AuthProvider
then the function takes care of this.
The storage
object stores six key value pairs. let's take a look at them:
key | description |
---|---|
kl | an encoded version of the role keys of the authenticated user |
klo | an encoded version of roleAccessConfig. Find more info in Hilma docs |
kloo | a random string to "confuse" hackers |
klk | a random string to "confuse" hackers |
access_token (or what ever you choose) | the current users access token |
two_factor_token (or what ever you choose) | The current JSON Web Token created durring the 2FA process |
Accessing storage items
getAuthItem - function
In AuthProvider
there is a property name getAuthItem
that lets you access a specific property of the storage
object. As every other property in the auth
object, there is a context object for the function, and a custom hook that returns it: GetAuthItemContext
and useGetAuthItem
. Example:
import { useGetAuthItem } from '@hilma/auth';
// later in your component
const getAuthItem = useGetAuthItem();
const accessToken = getAuthItem('access_token');
Somthing to note about getAuthItem
is that the function is generated every time the storage
updates, so you if you want to detect changes to the storage, then you can add the function to a dependency in useEffect.
getAccessToken - function
If you want to access the access token without writing 'access_token', there is another function in the auth
object named getAccessToken
that returns the access token. Example:
import { useGetAccessToken } from '@hilma/auth';
// later in your component
const getAccessToken = useGetAccessToken();
const accessToken = getAccessToken();
kls - object
In the auth
object there's an object name kls
that includes the kl
and klo
properties. Example:
import { useKls } from '@hilma/auth';
// later in your component
const kls = useKls();
const { kl, klo } = kls;
Updating storage items
setAuthItem - function
This function will update one value in both the storage
object and cookies at the same time. Example:
import { useSetAuthItem } from '@hilma/auth';
// later in your component
const setAuthItem = useSetAuthItem();
const updateKlk = async klk => {
await setAuthItem('klk', klk);
}
You can pass more parameters to the function to practice its behavior. Let's look at all the parameters:
Parameter | type | description | default |
---|---|---|---|
key | string | The key in which you would like to store a value | |
value | string | The value you would like to store | |
setLocalStorage | boolean | whether to store the value in localStorage | isCapacitor |
setCookies | boolean | whether to store the value in cookies | !isCapacitor |
changeStorage | boolean | whether to update the storage object |
true |
multiSetAuthItem - function
This function will update multiple values at the same time. Example:
import { useMultiSetAuthItem } from '@hilma/auth';
// later in your component
const multiSetAuthItem = useMultiSetAuthItem();
const updateStorage = async () => {
await multiSetAuthItem([['kl', newKl], ['klk', newKlk]]);
}
You can pass more parameters to the function to practice its behavior. Let's look at all the parameters:
Parameter | type | description | default |
---|---|---|---|
keyValuePairs | string[][] | An array of arrays that represent the key value pairs | |
setLocalStorage | boolean | whether to store the value in localStorage | isCapacitor |
setCookies | boolean | whether to store the value in cookies | !isCapacitor |
changeStorage | boolean | whether to update the storage object |
true |
Deleting storage items
removeAuthItem - function
This function will remove an item from both cookies and the storage
object. Example:
import { useRemoveAuthItem } from '@hilma/auth';
// later in your component
const removeAuthItem = useRemoveAuthItem();
const removeKl = async () => {
await removeAuthItem('kl');
}
logout - function
This function will delete all items stored in the storge
object and respective cookies. Example:
import { useLogout } from '@hilma/auth';
// later in your component
const logout = useLogout();
const deleteStorage = async () => {
await logout();
}
By default, the function will not delete a two factor token. If you want it to, you can pass true
to the function.
More exports that deal with storage
isAuthenticated - boolean
This property determines if you have an access token. Example:
import { useIsAuthenticated } from '@hima/auth';
// later in your component
const isAuthenticated = useIsAuthenticated();
hasTwoFactorToken - boolean
This property determines if you have a two factor token. Example:
import { useHasTwoFactorToken } from '@hima/auth';
// later in your component
const hasTwoFactorToken = useHasTwoFactorToken();
useKlskDhp - hook
import { useKlskDhp } from '@hilma/auth';
// in some functional component
const klskDhp = useKlskDhp();
use this hook if you want to know the current roleaccessconfig thats decoded. this is more part of the private api but you can still use it.
the hook returns an object. here are the key value pairs:
key | type | description |
---|---|---|
klsk | string[] |
this represents the components from roleaccessconfig |
dhp | string |
this represents the defaultHomePage from roleaccessconfig |
useRoleKeys - hook
import { useRoleKeys } from '@hilma/auth';
// in some functional component
const roleKeys = useRoleKeys();
use this hook if you want to get the decoded version of the kl
cookie.
the hook returns an array of strings.