Devise Token Auth Client
Installation
``
yarn add devise-token-auth-client
`
Usage
This client is based on Axios. See the Axios
Docs for basic usage instructions.
The instructions that follow show the usage of this client with Devise Token Auth.
$3
The ApiClient during the setup phase of your app.
`js
import ApiClient from 'devise-token-auth-client';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
async function render = Component => {
// create the client instance
const client = new ApiClient({
baseUrl: 'https://my-api.com'
});
// wait for the client to initialize before use. this will ensure that the
// user session is available for the initial render.
await client.isInitialized;
ReactDOM.render(
,
document.getElementById('app')
);
}
render(App);
`
$3
#### Client Instance Methods
##### emailSignUp
Create a new user account.
When email confirmation is not enabled, this will also authenticate the new user.
Usage |
try { await client.emailSignUp({ email: 'test@test.com', password: 'secret123', passwordConfirmation: 'secret123' }); } catch (e) { console.error(e); }
|
Params |
param | type | description |
|---|
email | string | The email address and for the new account. This will serve as the user ID for subsequent sign-ins. | password | string | The password for the new account | passwordConfirmation | string | The password param repeated exactly |
|
Return |
This method returns a Promise. The success and error resolutions are described below. |
Success |
{ id: 123, provider: "email", uid: "test@test.com", email: "test@test.com", ... }
|
Error |
{ _error: ["Top level errors"], email: "Invalid email address", password: "Password too short", passwordConfirmation: "Password does not match confirmation" }
|
---
##### emailSignIn
Authenticate an existing user.
Usage |
try { await client.emailSignIn({ email: 'test@test.com', password: 'secret123' }); } catch (e) { console.error(e); }
|
Params |
param | type | description |
|---|
email | string | The email used to create the existing user's account | password | string | The password for the existing user's account |
|
Return |
This method returns a Promise. The success and error resolutions are described below. |
Success |
{ id: 123, provider: "email", uid: "test@test.com", email: "test@test.com", ... }
|
Error |
{ _error: ["Top level errors"] }
|
---
##### oAuthSignIn
Sign in using a 3rd party OAuth provider (i.e. Github, Facebook, etc.). This
method will open a popup window that allows the user to authenticate using the
3rd party service. Once the 3rd party authentication is complete, the user will
be signed in to our own API and a session will be created in the browser. A new
user will be created if no user exists matching the ID and provider of the 3rd
party account.
Usage |
try { await client.oAuthSignIn('github'); } catch (e) { console.error(e); }
|
Params |
param | type | description |
|---|
provider | string | The name of the OAuth provider as configured on the API. |
|
Return |
This method returns a Promise. The success and error resolutions are described below. |
Success |
{ id: 123, provider: "email", uid: "test@test.com", email: "test@test.com", ... }
|
Error |
{ _error: ["Top level errors"] }
|
---
##### signOut
Clear the current user's session and user state. This method attempts to sign
out with the API, but the browser session and state is always cleared, even in
the case of API failure.
Usage |
try { await client.signOut(); } catch (e) { console.error(e); }
|
Params |
None |
Return |
This method returns a Promise. This promise should always resolve with no payload. |
Success |
undefined
|
---
##### passwordResetRequest
Sends an email to a user that has forgotten their password. The email will
contain a link that allows them to reset their password.
Usage |
try { await client.passwordResetRequest({ email: 'test@test.com' }); } catch (e) { console.error(e); }
|
Params |
param | type | description |
|---|
email | string | The email used to create the existing user's account |
|
Return |
This method returns a Promise. The success and error resolutions are described below. |
Success |
true
|
Error |
{ _error: ["Unable to find user with email 'test@test.com'"] }
|
---
#### Dispatch Actions
When configured to work with a dispatch action, the following actions will be
dispatched at the given times.
Action Type |
Example |
|---|
AUTH_INITIALIZED Dispatched after the client has initialized. At this point, the client.isInitialized will have been resolved.
|
{ type: "@@dtaClient:AUTH_INITIALIZED", userType: "user", payload: { access-token: "O-XixSZImcIriatjh3bamw" uid: "38051087" client: "gPYpfYpCdy7_nQujZXpRXg" expiry: "1524594344" } }
|
UPDATE_AUTH_CREDS Dispatched whenever the client credentials have been updated.
|
{ type: "@@dtaClient:UPDATE_AUTH_CREDS", userType: "user", payload: { access-token: "O-XixSZImcIriatjh3bamw" uid: "38051087" client: "gPYpfYpCdy7_nQujZXpRXg" expiry: "1524594344" } }
|
CLEAR_AUTH_CREDS Dispatched when the auth creds are cleared. This will happen on sign-out, or when a token is returned as invalid.
|
{ type: "@@dtaClient:CLEAR_AUTH_CREDS" userType: "user" }
|
INVALID_CREDS Dispatched when a validateToken call fails.
|
{ type: "@@dtaClient:INVALID_CREDS", userType: "user", payload: { message: "Invalid credentials.", config: { // ...the axios request config // https://github.com/axios/axios#request-config }, response: { // ...the axios response // https://github.com/axios/axios#response-schema } } }
|
UPDATE_USER Dispatched when the current user data is updated. This will happen on login.
|
{ type: "@@dtaClient:UPDATE_USER", userType: "user", payload: { id: 123, provider: "email", uid: "test@test.com", email: "test@test.com", // ... } }
|
VALIDATE_TOKEN_START Dispatched before the request to validate the user's session credentials with the API starts.
|
{ type: "@@dtaClient:VALIDATE_TOKEN_START" userType: "user" }
|
VALIDATE_TOKEN_SUCCESS Dispatched when the user's session credentials are successfully validated with the API.
|
{ type: "@@dtaClient:VALIDATE_TOKEN_SUCCESS" userType: "user" }
|
VALIDATE_TOKEN_ERROR Dispatched when the user's session credentials are rejected by the API.
|
{ type: "@@dtaClient:VALIDATE_TOKEN_ERROR" userType: "user" }
|
EMAIL_SIGNUP_START Dispatched at the start of an emailSignUp method call.
|
{ type: "@@dtaClient:EMAIL_SIGNUP_START" userType: "user" }
|
EMAIL_SIGNUP_SUCCESS Dispatched when the emailSignUp method succeeds.
|
{ type: '@@dtaClient:EMAIL_SIGNUP_SUCCESS', userType: 'confirmableUser' }
|
EMAIL_SIGNUP_ERROR Dispatched when the emailSignUp method fails.
|
{ type: '@@dtaClient:EMAIL_SIGNUP_ERROR', payload: { errors: { _error: [ "Password confirmation doesn't match Password", 'Password is too short (minimum is 8 characters)' ], password: [ 'is too short (minimum is 8 characters)' ], passwordConfirmation: [ "doesn't match Password" ] } }, userType: 'confirmableUser' }
|
EMAIL_SIGNUP_CONFIRMATION_SUCCESS Dispatched when a user arrives from an email confiramtion link, and the confirmation is successful.
|
{ type: '@@dtaClient:EMAIL_SIGNUP_CONFIRMATION_SUCCESS', userType: "user" }
|
EMAIL_SIGNUP_CONFIRMATION_ERROR Dispatched when a user arrives from an email confiramtion link, and the confirmation fails.
|
{ type: '@@dtaClient:EMAIL_SIGNUP_CONFIRMATION_ERROR', userType: "user" }
|
EMAIL_SIGNIN_START Dispatched at the start of the emailSignIn method call.
|
{ type: "@@dtaClient:EMAIL_SIGNIN_START", userType: "confirmableUser" }
|
EMAIL_SIGNIN_SUCCESS Dispatched when emailSignIn successfully authenticates with the API and the new user session is in place.
|
{ type: "@@dtaClient:EMAIL_SIGNIN_SUCCESS", userType: "confirmableUser" }
|
EMAIL_SIGNIN_ERROR Dispatched when emailSignIn calls fail.
|
{ type: "@@dtaClient:EMAIL_SIGNIN_ERROR", errors: { _error: [ "Invalid login credentials. Please try again.", ] }, userType: "user" }
|
SIGN_OUT_START Dispatched when the signOut method is initially called.
|
{ type: "@@dtaClient:SIGN_OUT_START" userType: "user" }
|
SIGN_OUT_SUCCESS Dispatched at the end of a successful signOut API request.
|
{ type: "@@dtaClient:SIGN_OUT_SUCCESS" userType: "user" }
|
SIGN_OUT_ERROR Dispatched when a signOut API request fails. The user's session will still be terminated on the client.
|
{ type: "@@dtaClient:SIGN_OUT_ERROR", payload: { errors: { // errors returned from the API } }, userType: "user" }
|
PASSWORD_RESET_REQUEST_START Dispatched at the start of the passwordResetRequest method call.
|
{ type: "@@dtaClient:PASSWORD_RESET_REQUEST_START", userType: "user" }
|
PASSWORD_RESET_REQUEST_SUCCESS Dispatched at the end of a successful passwordResetRequest method call.
|
{ type: "@@dtaClient:PASSWORD_RESET_REQUEST_SUCCESS", userType: "user" }
|
PASSWORD_RESET_REQUEST_ERROR Dispatched on failure of the passwordResetRequest method.
|
{ type: "@@dtaClient:PASSWORD_RESET_REQUEST_ERROR", userType: "user", payload: { errors: { _error: [ "Unable to find user with email 'test@test.com'" ] } } }
|
PASSWORD_RESET_CONFIRMATION_SUCCESS Dispatched when a user arrives from a password reset link, and the confirmation is successful.
|
{ type: '@@dtaClient:PASSWORD_RESET_CONFIRMATION_SUCCESS', userType: "user" }
|
PASSWORD_RESET_CONFIRMATION_ERROR Dispatched when a user arrives from a password reset link, and the confirmation fails.
|
{ type: '@@dtaClient:PASSWORD_RESET_CONFIRMATION_ERROR', userType: "user" }
|
OAUTH_SIGNIN_START Dispatched at the start of oAuthSignIn method calls.
|
{ type: "@@dtaClient:OAUTH_SIGNIN_START" userType: "user" }
|
OAUTH_SIGNIN_SUCCESS Dispatched when the user has successfully authenticated with a 3rd party OAuth provider and the new user session has been created.
|
{ type: "@@dtaClient:OAUTH_SIGNIN_SUCCESS", userType: "confirmableUser" }
|
OAUTH_SIGNIN_ERROR Dispatched on failed oAuthSignIn calls, or when the user closes the popup-window before authentication is complete.
|
{ type: "@@dtaClient:OAUTH_SIGNIN_ERROR" userType: "user" }
|
PERSIST_THROUGH_REDIRECT Dispatched when the client visits a confirmation redirect with the auth creds appended to the URL as querystring params. The auth creds are stored into the current session, and the browser is redirected to the same url without the auth querystring params.
|
{ type: "@@dtaClient:PERSIST_THROUGH_REDIRECT", userType: "user" }
|
LOAD_AFTER_REDIRECT Dispatched following a confirmation redirect. See the href="#PERSIST_THROUGH_REDIRECT">PERSIST_THROUGH_REDIRECT action above.
Note: this will only be called when using server-side rendering.
|
{ type: "@@dtaClient:UPDATE_USER", userType: "user", payload: { id: 123, provider: "email", uid: "test@test.com", email: "test@test.com", // ... } }
|
---
$3
$3
To sync with a redux store, simply pass the dispatch and getState methods
to the initializer.
`js
import { createStore } from 'redux';
import ApiClient from 'devise-token-auth-client';
import reducers from './reducers';
// ...
const store = createStore(reducers);
const client = new ApiClient({
baseUrl: 'https://my-api.com',
dispatch: store.dispatch,
getState: store.getState
});
`
$3
The goal of SSR is to pre-render the initial page load of a single-page app
(SPA). This is helpful to search engine crawlers that can't parse SPAs, and in
some cases it offers better performance and a better user experience.
Devise Token Client supports server-side rendering (SSR). But SSR does
complicate the setup. We will need to pass additional configuration params to the
initializer on both the server and the client.
#### SSR Step 1: Initialize on the server
The server needs the following additional params for SSR:
| param | type | description |
|===|===|===|
| location | (string) | The url for the initial render |
| redirect | (function) | A function used by the server to redirect to a new page |
| requestCookies | (object) | An object representation of the cookies contained in the initial request |
| setResponseCookie | (function) | A method used to set response cookies on the server |
| clearResponseCookie | (function) | A method used to clear a response cookie on the server |
##### SSR Server Config Example
This example uses Express. This example is also not
sufficient to set up an actual SSR app - it only calls out the steps necessary
for authentication. See [here] for a complete, working setup.
`js
import Express from 'express';
import cookieParser from 'cookie-parser';
import { renderToStaticMarkup } from 'react-dom/server';
import { StaticRouter } from 'react-router';
import createStore from './create-store';
import ApiClient from 'devise-token-auth-client';
import HTML from './html';
import App from './app';
// init the app
const app = new Express();
// this middleware will convert the cookie string into an object
app.use(cookieParser());
app.use(async (req, res) => {
// if this is the result of an OAuth redirect, don't render anything
if (req.query.blank) {
return res.send(\nAUTHENTICATING...);
}
const store = createStore();
const client = new ApiClient({
baseUrl: 'https://my-api.com/api',
dispatch: store.dispatch,
getState: store.getState
// SSR-specific params
requestCookies: req.cookies,
setResponseCookie: (key, val) => res.cookie(key, val),
clearResponseCookie: key => res.clearCookie(key),
redirect: url => { context.url = url },
});
// wait until auth session has loaded before rendering the page
await client.isInitialized;
// do an initial render to check for redirects
const { state: serverState, html: content } = await renderToString(
,
);
// if the redirect was called anywhere in the initial render, actually
// perform the redirect here
if (context.url) {
return res.redirect(context.url);
}
// serve the rendered content to the browser
return res.send(\n${html});
});
`
#### SSR Step 2: Initialize on the client
The client needs the following additional params for SSR:
| param | type | description |
|===|===|===|
| location | (string) | The url for the initial render |
| redirect | (function) | A function used by the browser to redirect to a new page |
##### SSR Client Config Example
`js
import { createStore } from 'redux';
import ApiClient from 'devise-token-auth-client';
import reducers from './reducers';
// ...
const store = createStore(reducers);
const client = new ApiClient({
baseUrl: 'https://my-api.com/api',
dispatch: store.dispatch,
getState: store.getState
});
``