Make sure to register for free to get an app token to use the interface.
React
In it's most basic form the React plugin only requires an app token and an onSuccess
callback so that something can happen once the user has authenticated.
import { Authentication } from 'iltio/react' export const MyAuthentication = () => ( <Authentication configuration={{ token: APP_TOKEN }} onSuccess={() => { redirect('/overview') }} /> )
The interactive example below can be used to try out and configure the authentication flow.
Form Customization
While the above is the most basic integration of the form there are many options to configure the form to seamlessly integrate with your application. Below is an example with all available properties and an example value.
import { Authentication } from 'iltio/react' export const MyAuthentication = () => ( <Authentication configuration={{ token: APP_TOKEN }} onSuccess={(name, token, registration) => { redirect('/overview') }} labels={{ submit: 'Login or Register' }} allowPhone={false} allowMail={true} Components={{ Button: MyButton, Input: MyInput, Form: MyForm, Tab: MyTab }} initialCountryCode="ch" variables={{ color: 'blue', contrast: 'white', borderRadius: 10 }} style={{ form: { padding: 5 }, inputMail: { background: 'red' }, button: { cursor: 'pointer' }, tab: { fontSize: 12 } }} /> )
All Form
props are optional and the above values merely serve as examples.
Here are all the available options for the more complex properties.
export default () => ( <Authentication labels={{ submit?: string, // Label of the submit button. tabPhone?: string, // Tab phone label text. tabMail?: string, // Tab mail label text. resend?: string, // Resend code button label. }} variables={{ color?: string, // General color used. colorError?: string, // Color used to highlight erroneous parts. contrast?: string, // Contrast color for dark backgrounds (button). borderRadius?: number | string, // Border radius of various elements. smallSpace?: number | string, // Smaller space used. space?: number | string, // Larger space used. fontSize?: number | string, // General font size. fontFamily?: string, // General font family. }} style={{ form?: CSSProperties, // Wrapper element. tabWrapper?: CSSProperties, // Wrapper for tabs (if multiple methods). tab?: CSSProperties, inputMail?: CSSProperties, inputCode?: CSSProperties, // Verification code input in step 2. button?: CSSProperties, // Generic button. error?: CSSProperties, // Error message text. message?: CSSProperties, // Information message text. // Various styles to configure the phone number input styles. phoneWrapper?: CSSProperties, phoneTop?: CSSProperties, phoneCountry?: { button?: CSSProperties; flag?: CSSProperties; prefix?: CSSProperties }, phoneInput?: CSSProperties, phoneCountryOptions?: CSSProperties, phoneCountryOption?: { button?: CSSProperties; text?: CSSProperties }, phoneInputCountrySearch?: CSSProperties, }} Components={{ Form?: FunctionComponent, // Wrapper element. TabWrapper?: FunctionComponent, Tab?: FunctionComponent, Input?: FunctionComponent, // Input used for mail, phone and code. Button?: FunctionComponent, // Submit and resend button. Error?: FunctionComponent, // Error message element. Message?: FunctionComponent, // Information message element. // Various elements for the phone number input. PhoneWrapper?: FunctionComponent, PhoneInput?: FunctionComponent, PhoneTop?: FunctionComponent, PhoneCountry?: FunctionComponent, PhoneCountryOptions?: FunctionComponent, PhoneCountryOption?: FunctionComponent, }} configuration={{ url?: string, token: string, storage?: BasicStorage, authenticateUrl?: string, tokenStorageKey?: string, codeTokenStorageKey?: string, nameStorageKey?: string, pollDuration?: number, }} /> )
Most function components will receive the variables
, style: CSSProperties
and the children
. The input element also receives a valid
attribute that should be used to style the input accordingly when invalid.
Configuration
A separate configure method is used so that the configuration can be shared between the framework component and the various helper methods. If only the Authentication
is used the same configuration can be passed there directly using the configuration
property.
import { MemoryStorage, configure } from 'iltio' configure({ token: APP_TOKEN, storage?: MemoryStorage, url?: 'https://my-server.com/api', authenticateUrl?: 'https://my-server.com/api/authenticate', pollDuration?: 5000, tokenStorageKey?: 'auth-token', codeTokenStorageKey?: 'auth-verify-token', nameStorageKey?: 'auth-name', })
In order for the authentication to work a token
is always required. By default the token will be stored inside window.sessionStorage
. If access is denied MemoryStorage
will be used as a fallback. Any method compatible with the Storage interface including the more permanent window.localStorage
can be used. It's possible to route any requests through your own server by setting a different url
. When the goal is to only keep the APP_TOKEN
private it's possible to reroute only the first request with authenticateUrl
. During the verification stage the interval to poll for verification through link can be set in milliseconds as pollDuration
. When using a key based storage like localStorage all of the address keys can be configured as well.
React Native
This plugin wraps the React version with custom UI components and compatible storage interface. Due to this most of the configurations described above also apply here. The style
property differs for some components as they are made up of more elements. For full customization of the UI of any part the Components
property can be used. To override a component it's best to use the default implementation as a starting point as it shows the available properties. This plugin also requires react-native-localize
to be installed.
import { Authentication, NativeStyles } from 'iltio/native' // Requires "unstable_enablePackageExports" in metro configuration. import { Authentication, NativeStyles } from 'iltio/dist/native/index.js' // Fallback without exports. export const MyNativeAuthentication = () => ( <Authentication configuration={{ token: APP_TOKEN }} onSuccess={(name, token) => { go('Overview') }} style={{ button: { text: { color: 'blue' }}, phoneCountryOption: { touchable: { backgroundColor: 'red' }} }} Components={{ Error: ({ style, variables, children, ...props }) => ( <Text style={{ backgroundColor: 'red', marginBottom: variables.smallSpace, ...style }} {...props}> {children} </Text> ) }} /> )
When importing as iltio/native
make sure to set unstable_enablePackageExports
to true
in the "metro": { "resolver": { ... } }
field in package.json
or in a dedicated configuration file as seen in metro.config.js
used by the plugin. This will require at least React Native 0.72 and will become the default behaviour in 0.73.
All the available style
properties are defined in the NativeStyles
type exported by the plugin. Components
are specified in the ComponentTypes
type exported as well.
The above demo shows three different ways to use and customize the React Native plugin. For this web demo it's using react-native-web to render the native UI on the web.
Native Storage
It's best to use the existing persistent storage solution your app is already using. Do this by only displaying the Form if there is no token yet and store the token from the onSuccess
callback once the user has successfully authenticated.
The storage
interface provided by this plugin will also store the token, as well as the intermediate token for step two to continue there in case the user has left the app. Unlike on the web, with a refresh the data in memory for an app will stay there and there is usually no need for persistent storage. Still, if there is a desire to use the existing storage interface in a persistent way, here is how to do this:
import { Authentication, Store } from 'iltio/native' import AsyncStorage from '@react-native-async-storage/async-storage' const readToken = () => Store.token export const MyNativeAuthentication = () => ( <Authentication configuration={{ token: APP_TOKEN, storage: AsyncStorage }} onSuccess={() => {}} /> )
See details to install AsyncStorage on this link. If you want to make sure the token is stored in an encrypred way consider using react-native-encrypted-storage.
Vue
<script> import Authentication from 'iltio/vue' </script> <template> <Authentication :configuration="{ token: 'demo' }" :on-success="(name) => console.log(name)" /> </template>
The Vue plugin supports the same configurations and customizations as the React version described above in more detail. Any UI component can be overrideen with a custom Vue component.
<script> import Authentication from 'iltio/vue' import { MyButton } from './MyButton.vue' </script> <template> <Authentication :style="{ form: { width: '300px', border: '1px dashed hsl(0, 0%, 78.0%)', padding: '20px' }, }" :variables="{ color: 'hsl(0, 0%, 43.5%)', contrast: 'red' }" :Components="{ Button: MyButton, }" /> </template>
Svelte
<script> import Authentication from 'iltio/svelte' </script> <Authentication configuration={{ token: 'demo' }} onSuccess={(name) => console.log(name)} />
The Svelte plugin supports the same configurations and customizations as the React version described above in more detail. Any UI component can be overrideen with a custom Svelte component. style
requires strings and not objects to configure the inline-styles.
<script> import Authentication from 'iltio/svelte' import { MyInput } from './components/MyInput.svelte' </script> <Authentication style={{ form: 'width: 300px; border: 1px dashed hsl(0, 0%, 78.0%); padding: 20px;', }} variables={{ color: 'blue' }} Components={{ Input: MyInput, }} />
JavaScript 🚧 Coming Soon
With the helpers provided below it should be fairly easy to integrate the login manually into any framework. The following javaScriptForm
method provides a legacy solution to create a form that that will provide the full authentication functionality.
import { javaScriptForm, configure } from 'iltio' configure({ token: APP_TOKEN }) javaScriptForm('#my-authentication')
Helper Methods
The following methods can be helpful before or after the authentication flow as well as when building a custom integration in JavaScript.
Store
import { Store } from 'iltio' // Reads the token from the assigned storage method. Store.token // Manually set the token. Store.token = USER_TOKEN // Remove the token. Store.removeToken() // Similarly, read, write or remove the name. Store.name // Similarly, read, write or remove the code token. Store.codeToken
The token
will be set when the user successfully logs in. The codeToken
on the other hand is set after the first step and will ensure the user continues at the verification step even when the page is accidentially refreshed.
getNameType
import { getNameType } from 'iltio' getNameType('test@testing.com') => 'mail' getNameType('+41799629162') => 'phone'
authenticate
import { authenticate } from 'iltio' // authenticate(name: string) const { error, codeToken, registration } = await authenticate('test@testing.com')
poll
import { poll } from 'iltio' // poll() const { error, token } = await poll()
confirm
import { confirm } from 'iltio' // confirm(code: string) const { error, token } = await confirm('1234')
resendCode
import { resend } from 'iltio' // resend(token = Store.codeToken) const { error, token } = await resend()
authorize
import { authorize } from 'iltio' // authorize(token = Store.token) const { error, role, id, name } = await authorize()
logout
import { logout } from 'iltio' // logout(server = false, token = Store.token) const { error } = await logout(true)
remove
import { remove } from 'iltio' // remove(token = Store.token) const { error } = await remove()