@teku/react-auth
v1.0.10
Published
Teku's react authentication
Downloads
5
Readme
@teku/react-auth
Simple solution to make your React web application authentication / authorization. Designed to work with Auth0, Firebase v8 and Firebase v9. Supports Preact too.
Table of contents
Installation
npm install --dev @teku/react-auth
Concept
There are 3 supported auth drivers:
- Auth0: Using auth0, or even in combination with Firebase Auth
- FirebaseAuth: Using Google Firebase Auth
- FireseProfile: Fetching user profile from Google [Firestore][service-firestore]
After initialization, these drivers will automatically handle authentication / authorization logic for you, the resolved profiles will be pushed into AuthContext through their driver ids and even trigger event handlers for us.
How To Use
Handle auth with AuthProvider
We provide AuthProvider
for wrapping your components / pages, which will automatically handle authentication process for you.
import { AuthProvider } from '@teku/react-auth'
<AuthProvider {...options}>
{children}
</AuthProvider>
There are 2 types of options:
All of options are optional, but as least 1 driver options should be provided. Option syntaxes / signatures are described using Typescript style or detailed tables in following sections.
Callbacks
onUserChanged
(driver: AuthDrivers, user: any | null) => void
This callback is fired everytime auth data changed, when the users are logged in, or logged out (null
).
The driver
param are driver id (like auth0, firebase...) that has auth data updated.
onError
(driver: AuthDrivers, err: Error) => void
This callback is only fired when error happens.
Driver options
The driver options (objects) will be used to initialize authentication clients.
withAuth0
These are only options which is required or provided with default values. More auth0 options can be found at Auth0 options
Option | Type | Description | Default
-------------------|-------------------------|----------------------------------------------------------------------------|-------------------------
domain | string | required
Domain registed with Auth0 more info |
clientId | string | required
Auth0 client id more info |
loginRedirectUri | string | required
Callback URL after Auth0 authentication more info |
logoutRedirectUri | string | required
Callback URL after Auth0 SSO logout more info |
responseType | string | Response type | token id_token
scope | string | Scope | openid profile email
useRefreshTokens | boolean | Should we use Auth0's refresh token rotation | true
ssoCheckInterval | integer | Delay to call for rechecking SSO status, in seconds. If not set, sso checks will be triggered based on token's expire time (timer only start on page load) |
Authenticated Auth0 profile contains these fields:
_token
: auth token_tokenExpiresAt
: token expiration timestampuid
: user id / subemail
: user emailemailVerified
: where the user email has been verifiedname
: user namepicture
: URL to user picture
withFirebaseAuth
These are options of Firebase auth driver:
| Option | Type | Description | Default |
|---------------------|---------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------|
| auth | [Auth][#firebase-auth] | required
Firebase auth instance | |
| onAuthStateChanged | (user: any or null
) => void | required
Callback whenever firebase auth user logged in / logged out (null
) | |
| customClaimMap | any | Map fields from custom claims into solved user | {}
|
| customTokenMap | any | Provide fields to be used during custom token exchanges when you combine firebase with auth0 more info | { inputName: 't', outputName: 'ct' }
|
| getCustomToken | (token: string) => Promise<string> | Only required when you combine firebase with auth0, async
function to resolve with custom token more info | |
| boundToAuth0 | boolean | Whether should firebase combine with auth0 | true
|
Authenticated FirebaseAuth profile contains these fields:
_token
: auth tokenuid
: user's uidemail
: user emailemailVerified
: where the user email has been verifiedphoneNumber
: user associated phone numbername
: user namecustom
claim fieldspicture
: URL to user picture
Apart from _token
, uid
and picture
, other fields are standardized to be used as Firebase security rules more info.
withFirebaseProfile
This driver requires withFirebaseAuth
to be setup, it will watch for firebase auth data changed to determine when to fetch necessary profile, to login and logout.
| Option | Type | Description | Default |
|-------------|--------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
| getQuery | (conditions: any) => Query | required
A function to return a Firestore Query for filter user profile, since we only take first found document, a query with limit(1)
is recommended | |
| getSnapshot | (query: Query, onChange: Function, onError: Function) => Unsubscribe | required
A function to start watching profiles query snapshot. Usually we will need to bind onChange
and onError
to snapshot creator. For example query.onSnapshot(onChange, onError)
| |
| userIdField | string | User id field for adding into conditions | uid
|
| criteria | any | Additional criteria to filter profile data with firebase user id | |
Access auth data with AuthContext
We profile a React hook to listen for auth data context changes
import { useAuth } from '@teku/react-auth`
const auth = useAuth()
The auth
context value presents authentication state of all available drivers:
{[key in AuthDrivers]}: any}
Render based on authentication status
We provide a handy AuthGate
ultility component for toggling display based on authentication state. In this example, FallbackComponent
is displayed if user isn't authenticated yet:
import { AuthGate } from '@teku/react-auth`
<AuthGate FallbackComponent={() => 'Please login'}>
{/* something to hide if user not authenticated */}
</AuthGate>
If you want to show something else instead of FallbackComponent
while the application is determining if user is authenticated or not (due to async flow), the MaskComponent
option can be used as a placeholder during this process:
import { AuthGate } from '@teku/react-auth`
<AuthGate
FallbackComponent={() => 'Please login'}
MaskComponent={() => 'Verifying your authentication ...'}
>
{/* something to hide if user not authenticated */}
</AuthGate>
List of available driver ids
The full list of supported driver ids can be found in AuthDrivers
enum. You can use them to determine with part of auth data is being initalized
enum AuthDrivers {
AUTH0 = 'auth0',
FIREBASE_AUTH = 'firebase',
FIREBASE_PROFILE = 'profile'
}
Advanced usage
Using Auth0 with Firebase
For combine Auth0 with Firebase, we need to setup a cloud function for using Firebase Admin SDK to create custom tokens.
Here is an example of getCustomToken
function:
const getCustomToken = async token => {
const exchangeToken = firebase.functions().httpsCallable('auth')
const { data } = exchangeToken({ t: token })
return data.token
}
After auth0 done authenticated a user, if the user's email has been verified, react-auth
will try to authenticate the user through custom tokens, hence allow the user to access firebase resources.
Use with Preact
We also provide a Preact compat build. Switching between React and Preact builds is really simple, using webpack resolve.alias
option:
resolve: {
alias: {
'@teku/react-auth': '@teku/react-auth/preact'
}
}
SSO on Safari
Recently, we moved to Auth0 SPA SDK for better security and browser compatibility with Refresh Token Rotation. This partly avoid the third party cookies, with is considered bad for browsers' future privacy policy.
Safari is more strict on that road, providing with their adaption of Intelligent Tracking Prevention (ITP), will prevents SSO functions from working properly (see).
To fix this, we need to add specific option to auth0 driver to enable localstorage
for storing auth0 tokens (not the best but the only option left):
withAuth0 = {
...
cacheLocation: 'localstorage'
}
Contribution
All contributions are welcome. Feel free to open PR or share your ideas of improvement.
Thank you.