UNPKG

10.1 kBMarkdownView Raw
1@fusion.io/authenticate
2-----------------------
3
4Better Authentication for better Geeks.
5
6
7In short, this is an authentication framework for Node.JS
8
9Much like [PassportJS](http://www.passportjs.org/). 😛
10
11# GETTING STARTED
12
13*For quick and dirty and lazy work with this package. Please check our [supported Gateways](docs/GATEWAYS.md)*
14
15To get start, please follow these steps:
16
171. [Installation](#installation).
182. [Determine the authentication Protocol(s)](#determine-the-authentication-protocols).
193. [Making Identity Provider(s)](#making-identity-providers).
204. [Register your gateway with Protocol and Identity Provider](#register-your-gateway-with-protocol-and-identity-provider).
215. [Guard your resources](#guard-your-resources).
22
23For further topics, please checkout:
24
25- [Some best practices about authentications](docs/BEST_PRACTICES.md).
26- [Document about making a Protocol](docs/PROTOCOLS.md#writing-custom-protocol).
27- [Our core concepts when building this package](docs/CONCEPTS_AND_DEFINITIONS.md).
28
29
30## Installation
31
32To install this package, please run:
33
34```javascript
35npm install --save @fusion.io/authenticate
36```
37
38## Determine the authentication Protocol(s)
39
40`Hey! hey! What is protocol?`
41
42*If you're asking, a Protocol is just a service that can read the user's authentication
43information (`Credential`) from your app. Just it!*
44
45There are variety protocols out there and it is hard to choose!
46But not so many that are widely accepted and adopted.
47
48So we are here to help you go shopping!
49
50- If you just want to authenticate your user by `email`/`username`/`phone number`/`whatever...` and password.
51You should use the `Local` protocol.
52
53- If you also want to let the user can authenticate and login to your application via social networks.
54Like Facebook, Google, Linkedin, ...
55Most of them are supporting `OAuth2` protocol. So it will be your choice.
56
57- If you also provide API endpoints and you want to protect that resources, we suggest that you should use
58token. So let's add `Token` into your shopping cart!
59
60This step is just it. No code! Just cheap talk! :D
61
62## Making Identity Provider(s).
63
64`Hey! hey! What is Identity Provider?`
65
66*Again, if you're asking, an Identity Provider is just a service that translates the credential of the above step
67into user's `Identity` (or user id or something that you can use to distinguish one user to others).*
68
69Let's check your shopping cart.
70
71If you are using `Local` protocol. Your Identity Provider should look like:
72
73```javascript
74
75class MyLocalUserProvider {
76
77 async provide({username, password}) {
78 // Here you can find your user
79 // Do some password verification.
80
81 // and the last thing is:
82
83 return user.id; // Or .email .phonenumber .whatever...
84 }
85}
86```
87
88If you are using `OAuth2` protocol, your Identity Provider should look like:
89
90```javascript
91
92class MyOAuth2kUserProvider {
93
94 async provide({access_token}) {
95 // Here you can use the access_token to ask
96 // the related social network for the user's
97 // profile and of course, user id.
98
99 // and ...
100 return user.id;
101 }
102}
103
104```
105
106If you are using `Token` protocol, your Identity Provider should look like:
107
108```javascript
109
110class MyApiUserProvider {
111
112 async provide({token}) {
113 // Here you can use the token to find your user.
114
115 // and again:
116
117 return user.id;
118 }
119}
120
121```
122
123In general, your Identity provider is nothing special but a class with an `async provide(credential)` method.
124
125Where `credential` is the information that you'll get from the protocol.
126
127## Register your gateway with Protocol and Identity Provider
128
129Now let's mixed up your Identity Provider and protocol.
130
131```javascript
132
133const { authenticator, HeadlessLocal } = require('@fusion.io/authenticate');
134
135// or ES6:
136
137import { authenticator, HeadlessLocal } from "@fusion.io/authenticate";
138
139authenticator.gate('local', new HeadlessLocal(), MyLocalUserProvider());
140```
141
142In the example code above, we've registered a gateway called `local` with [`HeadlessLocal`](docs/PROTOCOLS.md#headlesslocal) protocol and your `MyLocalUserProvider` identity provider.
143
144We supports 3 basic protocols for you:
145
146[`HeadlessLocal`](docs/PROTOCOLS.md#headlesslocal), [`HttpOAuth2`](docs/PROTOCOLS.md#httpoauth2) and [`HttpTokenBearer`](docs/PROTOCOLS.md#httptokenbearer)
147. You can replace the above [`HeadlessLocal`](docs/PROTOCOLS.md#headlesslocal) to any one of them.
148
149*For more usage of Protocol, please check out the [Protocols documentation](docs/PROTOCOLS.md).*
150
151You can have as many gates as you want.
152Just use the `authenticator.gate(gateName, protocol, identityProvider);` to register a new gate.
153
154## Guard your resources
155
156Now, your gate is ready, let's authenticate your resource with your gate.
157
158```javascript
159
160const { UnAuthenticated, Aborted } = require('@fusion.io/authenticate');
161
162// or ES6
163
164import { UnAuthenticated, Aborted } from "@fusion.io/authenticate";
165
166...
167
168// Some where inside your code.
169
170try {
171 let userIdentity = await authenticator.authenticate('local', {username: 'rikky', password: 'Won\'t tell ya!'} );
172
173 // Here is a safezone. User already authenticated
174 // You can perform any thing on your resource here!
175
176} catch (error) {
177 if (error instanceof UnAuthenticated) {
178 // Here is not a safe zone. User is unauthenticated.
179 }
180
181 if (error instanceof Aborted) {
182 // Here is weird zone. The Protocol decided to abort
183 // authentication step.
184 }
185
186 // Here is crazy zone. Some thing went wrong! you better throw the
187 // error out for debugging.
188 throw error;
189}
190
191```
192
193### Good news for `Koa`, `Express`, `Socket.IO` users!
194
195We love `middleware` style! If you are using above frameworks,
196you'll have a very nice place to authenticate your resources. The mighty `middleware`:
197
198```javascript
199
200// For example, here we'll wrap the `.authenticate()` method inside a Koa middleware.
201
202const localAuthentication = async (context, next) => {
203 try {
204 let userIdentity = await authenticator.authenticate('local', context.request.body);
205
206 context.identity = userIdentity;
207 await next();
208
209 } catch (error) {
210 if (error instanceof Aborted) {
211 return;
212 }
213 throw error;
214 }
215}
216
217
218// So now, we can do something like:
219
220
221app.use(localAuthentication);
222
223```
224
225
226And for your laziness, we also wrapped it. So beside [`HeadlessLocal`](docs/PROTOCOLS.md#headlesslocal), [`HttpOAuth2`](docs/PROTOCOLS.md#httpoauth2) and [`HttpTokenBearer`](docs/PROTOCOLS.md#httptokenbearer) we have
227[`ExpressLocal`](docs/PROTOCOLS.md#expresslocal),
228[`KoaLocal`](docs/PROTOCOLS.md#koalocal),
229[`SocketIOLocal`](docs/PROTOCOLS.md#socketiolocal),
230[`KoaOAuth2`](docs/PROTOCOLS.md#koaoauth2-and-expressoauth2),
231[`ExpressOAuth2`](docs/PROTOCOLS.md#koaoauth2-and-expressoauth2),
232[`KoaToken`](docs/PROTOCOLS.md#koatoken-and-express-token),
233[`ExpressToken`](docs/PROTOCOLS.md#koatoken-and-express-token),
234[`SocketIOToken`](docs/PROTOCOLS.md#socketiotoken),
235[`KoaSession`](docs/PROTOCOLS.md#koasession-and-expresssession),
236[`ExpressSession`](docs/PROTOCOLS.md#koasession-and-expresssession).
237
238These are framework specific protocols.
239It have ability to `mount` to your framework as a middleware and `authenticate` its endpoints.
240
241You can replace the above code by simple `authenticator.authenticate()` method:
242
243```javascript
244
245// For koa:
246//
247// app or router
248app.use(authenticator.authenticate('local'));
249// Then you can get the identity by accessing `context.identity`.
250
251// For express:
252//
253// app or router
254app.use(authenticator.authenticate('local'));
255// Then you can get the identity by accessing `request.identity`.
256
257// For Socket.IO:
258//
259// socket or namespace
260socket.use(authenticator.authenticate('local'));
261// Then you can get the identity by accessing `socket.identity`.
262
263```
264
265
266### Good news for users don't find a suitable protocol.
267
268So if you don't think these above protocols are suitable, and you decided to write one for you.
269That's great! Now you are becoming seriously! Please check the [CUSTOM PROTOCOL](docs/PROTOCOLS.md#writing-custom-protocol) part.
270
271
272### Tips:
273
274- **Gateway** is a unit of work that combines a protocol and an identity provider together.
275It's the building block of authentication process.
276**Authenticator** is just a service that managing gates. Just it!
277- Relationship between **Protocol** and **IdentityProvider** is many-to-many.
278**Gateway** is a pivot representing that relationship.
279- You can have many **Protocols** that sharing the same **Identity Provider** if they providing the same `Credential`.
280
281 For example: *your application may support `token` authentication via web APIs.
282And you also want to support `token` authentication via WebSocket.
283But no matter what the transport layer is, they still returning a `token` as a `Credential`,
284using the same **Identity Provider** in this case will enable your ability to authenticate the same user over multiple transport layers.*
285- In reverse, you can also have many **Identity Providers** that sharing the same **Protocol** when we have more than one **Type Of User**,
286but sharing the same way of authentication (same way of providing `Credential`).
287
288 For example: *your application may want to authenticate **users** and **organizations** account.
289In both cases, they will provide **email** and **password** as `Credential`.
290Using the same **Protocol** will help your code DRY by not providing 2 **Protocols** that are identical to each other.*
291
292
293# BEST PRACTICES
294
295Please checkout some [best practices](docs/BEST_PRACTICES.md) about authentication.
296
297# FOR YOUR LAZINESS:
298
299We ship some common social authentication services:
300`Facebook`,
301`Google`,
302`Instagram`,
303`Slack`,
304`GitHub`
305out of the box. So you may wants to check out [how to have the `Login via XXX` button](docs/GATEWAYS.md).
306
307# CUSTOM PROTOCOL
308
309Please checkout the [document about making a Protocol](docs/PROTOCOLS.md#writing-custom-protocol).
310
311# CONCEPTS AND DEFINITIONS
312
313Please check out [our concepts](docs/CONCEPTS_AND_DEFINITIONS.md) when building this package.