@tapgiants/auth provides authentication and session management functionality.
Install @tapgiants/auth
yarn add @tapgiants/auth
Renders AuthComponent
with auth
property instance of the AuthService
class if AuthService.loggedIn
returns true
. Otherwise calls onLoginFailed
.
AuthComponent: React.Component - The component that will be rendered if the authentication is successful.
onLoginFailed: Function - A callback function. It is called when AuthService.loggedIn
returns false
.
import React from 'react';
import Router from 'next/router';
import { withAuth } from '@tapgiants/auth';
const PrivatePage = ({ auth }) => {
console.log('Logged in?', auth.loggedIn());
console.log('User token', auth.getToken());
return (
<div>
Private Content
</div>
);
};
export default withAuth(PrivatePage, () => Router.push('/login'));
All of the authentication and session managment logic is handled by AuthService class. If the authentication is successful stores provided user token in a cookie.
login(login: Function, email: String, password: String, onSuccess: Function, onError: Function):void
Authenticates an user if passed user credentials are valid and calls onSuccess
callback, otherwise calls onError
.
login: Function: Promise - A callback function that performs login request against authentication service. It can be an Apollo mutate function from render prop function
or a custom function that returns a promise.
The function receives the following json shape as an argument:
{
variables: {
input: {
email,
password
}
}
}
Should return a promise that resolves the server response in the following shape:
new Promise(
(resolve) => resolve({
data: {
login: {
user: {
token: 'user-token'
}
}
}
}
)).then(serverResponse => console.log(serverResponse))
Check the GraphQL input type and response type conventions described in the GraphQL conventions section
email: String - E-mail address.
password: String - Password.
onSuccess: Function - It is called when the authentication is successful.
onError: Function - It is called when the authentication fails. Receives an array with errors as an argument. Check GraphQL conventions section for errors format reference.
import React from 'react';
import { Mutation } from 'react-apollo';
import gql from 'graphql-tag';
import { ApolloWrapper, formatGQLErrors } from '@tapgiants/graphql';
import { AuthService } from '@tapgiants/auth';
const LOGIN = gql`
mutation($input: LoginInput!) {
login(input: $input) {
user {
id
email
firstName
lastName
token
}
errors {
key
message
}
}
}
`;
class Login extends React.Component {
state = {
email: '',
password: ''
}
handleLogin = (login) => {
const auth = new AuthService();
const onSuccess = () => {
console.log('User token', auth.getToken());
// User token eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9
console.log('loggedIn', auth.loggedIn());
// loggedIn true
};
const onError = (errors) => {
console.log('Errors', formatGQLErrors(errors));
// Errors { generalError: "Incorrect login credentials" }
console.log('loggedIn', auth.loggedIn());
// loggedIn false
};
auth.login(
login,
this.state.email,
this.state.password,
onSuccess,
onError
);
}
setCredential(name, e) {
const currentState = this.state;
this.setState({ ...currentState, ...{ [name]: e.target.value } });
}
render() {
const { email, password } = this.state;
return (
<ApolloWrapper uri="http://localhost:4000/api">
<Mutation mutation={LOGIN}>
{(login) => {
return (
<form>
<label htmlFor="email">E-mail</label>
<input
id="email"
type="email"
name="email"
value={email}
onChange={(e) => this.setCredential('email', e)}
/>
<label htmlFor="password">Password</label>
<input
id="password"
type="password"
name="password"
value={password}
onChange={(e) => this.setCredential('password', e)}
/>
<button type="button" onClick={() => this.handleLogin(login)}>Login</button>
</form>
)
}}
</Mutation>
</ApolloWrapper>
);
}
}
export default Login;
Returns true if there is a stored token in the cookie.
Sets a token in the cookie.
token: String - token string.
Returns true if the token is successfully stored in the cookie. Otherwise returns false.
Returns the user's token.
Registers an user on a remote service.
register: Function: Promise - A callback function that performs registration request on a remote server. It can be an Apollo mutate function from render prop function
or a custom function that returns a promise.
The function receives the following json shape as an argument:
{
variables: {
input: userData
}
}
Should return a promise that resolves the server response in the following shape:
new Promise(
(resolve) => resolve({
data: {
createUser: {
user: {
token: 'user-token'
},
errors: []
}
}
}
)).then(serverResponse => console.log(serverResponse))
Check the GraphQL input type and response type conventions described in the GraphQL conventions section
userData: Object - User data. Example:
{
email: '[email protected]',
password: '123456',
firstName: 'John',
lastName: 'Doe'
}
onSuccess: Function - It is called when the registration is successful.
onError: Function - It is called when the authentication fails. Receives an array with errors as an argument. Check GraphQL conventions section for errors format reference.
import React from 'react';
import { Mutation } from 'react-apollo';
import gql from 'graphql-tag';
import { ApolloWrapper, formatGQLErrors } from '@tapgiants/graphql';
import { AuthService } from '@tapgiants/auth';
const CREATE_USER = gql`
mutation($input: CreateUserInput!) {
createUser(input: $input) {
user {
id
email
firstName
lastName
token
}
errors {
key
message
}
}
}
`;
class Register extends React.Component {
state = {
email: '',
password: '',
firstName: '',
lastName: ''
}
handleRegistration = (register) => {
const auth = new AuthService();
const onSuccess = () => {
console.log('User token', auth.getToken());
// User token eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9
console.log('loggedIn', auth.loggedIn());
// loggedIn true
};
const onError = (errors) => {
console.log('Errors', formatGQLErrors(errors));
// Errors { email: "can't be blank", firstName: "can't be blank", lastName: "can't be blank", password: "can't be blank" }
console.log('loggedIn', auth.loggedIn());
// loggedIn false
};
auth.register(
register,
{
email: this.state.email,
password: this.state.password,
firstName: this.state.firstName,
lastName: this.state.lastName
},
onSuccess,
onError
);
}
setCredential(name, e) {
const currentState = this.state;
this.setState({ ...currentState, ...{ [name]: e.target.value } });
}
render() {
const { email, password, firstName, lastName } = this.state;
return (
<ApolloWrapper uri="http://localhost:4000/api">
<Mutation mutation={CREATE_USER}>
{(register) => {
return (
<form>
<label htmlFor="firstName">First Name</label>
<input
id="firstName"
type="firstName"
name="firstName"
value={firstName}
onChange={(e) => this.setCredential('firstName', e)}
/>
<label htmlFor="lastName">Last Name</label>
<input
id="lastName"
type="lastName"
name="lastName"
value={lastName}
onChange={(e) => this.setCredential('lastName', e)}
/>
<label htmlFor="email">E-mail</label>
<input
id="email"
type="email"
name="email"
value={email}
onChange={(e) => this.setCredential('email', e)}
/>
<label htmlFor="password">Password</label>
<input
id="password"
type="password"
name="password"
value={password}
onChange={(e) => this.setCredential('password', e)}
/>
<button
type="button"
onClick={() => this.handleRegistration(register)}
>Register</button>
</form>
)
}}
</Mutation>
</ApolloWrapper>
);
}
}
export default Register;
Deletes the token from the cookie.
logout: Function: Promise - A callback function that performs logout request on a remote server. It can be an Apollo mutate function from render prop function
or a custom function that returns a promise.
The function receives the following json shape as an argument:
{
variables: {
token: 'token-from-the-cookie'
}
}
Should return a promise.
Check the GraphQL input type conventions described in the GraphQL conventions section
onSuccess: Function - It is called when the logout is successful.
import React from 'react';
import Router from 'next/router';
import { Mutation } from 'react-apollo';
import gql from 'graphql-tag';
import { ApolloWrapper } from '@tapgiants/graphql';
import { withAuth } from '@tapgiants/auth';
const LOGOUT = gql`
mutation($token: String!) {
logout(token: $token) {
user {
id
email
firstName
lastName
token
}
errors {
key
message
}
}
}
`;
const LogoutButton = ({ auth }) => (
<Mutation mutation={LOGOUT}>
{(logout) => {
return (
<button
type="button"
onClick={() => {
auth.logout(
logout,
() => Router.push('/login')
)
}}
>Logout</button>
);
}}
</Mutation>
);
const PrivatePage = ({ auth }) => {
console.log('Logged in?', auth.loggedIn());
console.log('User token', auth.getToken());
return (
<ApolloWrapper uri="http://localhost:4000/api">
Private Content
<LogoutButton auth={auth} />
</ApolloWrapper>
);
};
export default withAuth(PrivatePage, () => Router.push('/login'));
Add link to an external repo that describes all the conventions.
Link the package from your target project and run yarn start
. This will start the webpacker watcher.
Once you are satisfied with your changes, use yarn publish
to push the new version to npmjs.org.