UNPKG

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