|
10 | 10 | If you are using the default options, setting up JWT auth for your Feathers app is as simple as the below example. Note: You must set up the `body-parser` module before setting up `feathers-authentication`. |
11 | 11 |
|
12 | 12 | ```js |
| 13 | +/* * * Import Feathers and Plugins * * */ |
13 | 14 | var feathers = require('feathers'); |
14 | 15 | var hooks = require('feathers-hooks'); |
15 | 16 | var bodyParser = require('body-parser'); |
16 | 17 | var feathersAuth = require('feathers-authentication').default; |
17 | 18 | var authHooks = require('feathers-authentication').hooks; |
| 19 | + |
| 20 | +/* * * Prepare the Mongoose service * * */ |
18 | 21 | var mongooseService = require('feathers-mongoose'); |
| 22 | +var mongoose = require('mongoose'); |
| 23 | +var Schema = mongoose.Schema; |
| 24 | +var UserSchema = new Schema({ |
| 25 | + username: {type: String, required: true, unique: true}, |
| 26 | + password: {type: String, required: true }, |
| 27 | + createdAt: {type: Date, 'default': Date.now}, |
| 28 | + updatedAt: {type: Date, 'default': Date.now} |
| 29 | +}); |
| 30 | +var UserModel = mongoose.model('User', UserSchema); |
| 31 | + |
| 32 | +/* * * Connect the MongoDB Server * * */ |
| 33 | +mongoose.Promise = global.Promise; |
| 34 | +mongoose.connect('mongodb://localhost:27017/feathers'); |
19 | 35 |
|
| 36 | +/* * * Initialize the App and Plugins * * */ |
20 | 37 | var app = feathers() |
21 | 38 | .configure(feathers.rest()) |
22 | 39 | .configure(feathers.socketio()) |
23 | 40 | .configure(hooks()) |
| 41 | + .use(bodyParser.json()) |
24 | 42 | .use(bodyParser.urlencoded({ extended: true })) |
| 43 | + |
25 | 44 | // Configure feathers-authentication |
26 | 45 | .configure(feathersAuth({ |
27 | 46 | secret: 'feathers-rocks' |
28 | | - })) |
29 | | - .use('/api/users', new mongooseService('user', { |
30 | | - schema: { |
31 | | - email: {type: String, required: true, unique: true }, |
32 | | - password: {type: String, required: true }, |
33 | | - admin: {type: Boolean, default: false } |
34 | | - }, |
35 | | - before:{ |
36 | | - create: [authHooks.hashPassword('password')] |
37 | | - } |
38 | | - })) |
39 | | - |
| 47 | + })); |
| 48 | + |
| 49 | +/* * * Setup the User Service and hashPassword Hook * * */ |
| 50 | +app.use('/api/users', new mongooseService('user', UserModel)) |
| 51 | +var service = app.service('/api/users'); |
| 52 | +service.before({ |
| 53 | + create: [authHooks.hashPassword('password')] |
| 54 | +}); |
| 55 | + |
| 56 | +/* * * Start the Server * * */ |
| 57 | +var port = 3030; |
| 58 | +var server = app.listen(port); |
| 59 | +server.on('listening', function() { |
| 60 | + console.log(`Feathers application started on localhost:3030); |
| 61 | +}); |
40 | 62 | ``` |
41 | 63 |
|
42 | | -### REST Requests |
43 | | -Authenticated REST requests must have an `Authorization` header in the format `'Bearer <token>'`, where the <token> is the JWT token. For example: |
| 64 | +Please note that the above User service does not include any kind of authorization or access control. That will require setting up additional hooks, later. For now, leaving out the access control will allow us to easily create a user. Here's an example request to create a user (make sure your server is running): |
| 65 | +
|
| 66 | +```js |
| 67 | +// Create User (POST http://localhost:3030/api/users) |
| 68 | +jQuery.ajax({ |
| 69 | + url: 'http://localhost:3030/api/users', |
| 70 | + type: 'POST', |
| 71 | + headers: { |
| 72 | + 'Content-Type': 'application/json', |
| 73 | + }, |
| 74 | + contentType: 'application/json', |
| 75 | + data: JSON.stringify({ |
| 76 | + 'username': 'feathersuser', |
| 77 | + 'password': 'fowlplay' |
| 78 | + }) |
| 79 | +}) |
| 80 | +.done(function(data, textStatus, jqXHR) { |
| 81 | + console.log('HTTP Request Succeeded: ' + jqXHR.status); |
| 82 | + console.log(data); |
| 83 | +}) |
| 84 | +.fail(function(jqXHR, textStatus, errorThrown) { |
| 85 | + console.log('HTTP Request Failed', arguments); |
| 86 | +}); |
| 87 | +``` |
| 88 | +
|
| 89 | +Once you've created a user, logging in is as simple as `POST`ing a request to the `loginEndpoint`, which is `/api/login` by default. Here's an example request for logging in: |
| 90 | +
|
| 91 | +```js |
| 92 | +// Login by email (POST http://localhost:3030/api/login) |
| 93 | +jQuery.ajax({ |
| 94 | + url: 'http://localhost:3030/api/login', |
| 95 | + type: 'POST', |
| 96 | + headers: { |
| 97 | + 'Content-Type': 'application/json', |
| 98 | + }, |
| 99 | + contentType: 'application/json', |
| 100 | + data: JSON.stringify({ |
| 101 | + 'username': 'feathersuser', |
| 102 | + 'password': 'fowlplay' |
| 103 | + }) |
| 104 | +}) |
| 105 | +.done(function(data, textStatus, jqXHR) { |
| 106 | + console.log('HTTP Request Succeeded: ' + jqXHR.status); |
| 107 | + console.log(data); |
| 108 | +}) |
| 109 | +.fail(function(jqXHR, textStatus, errorThrown) { |
| 110 | + console.log('HTTP Request Failed', arguments); |
| 111 | +}); |
| 112 | +``` |
| 113 | +The server will respond with an object that contains two properties, `user` and `token`. The `user` property contains an object with whatever data was returned from your user service. You'll notice that it currently includes the password. You really don't want it exposed, so when you're ready to secure the service, you'll need an additional feathers-hook to remove the password property from the response. |
| 114 | +
|
| 115 | +The `token` property contains a JWT token that you can use to authenticate REST requests or for socket connections. You can learn more about how JWT tokens work on [jwt.io](http://jwt.io/). |
| 116 | +
|
| 117 | +
|
| 118 | +### Authenticating REST Requests |
| 119 | +
|
| 120 | +Authenticated REST requests must have an `Authorization` header in the format `'Bearer <token>'`, where the <token> is the JWT token. The header should have the following format: |
44 | 121 | ``` |
45 | 122 | Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IklseWEgRmFkZWV2IiwiYWRtaW4iOnRydWV9.YiG9JdVVm6Pvpqj8jDT5bMxsm0gwoQTOaZOLI-QfSNc |
46 | 123 | ``` |
47 | 124 |
|
48 | | -### Websocket Connections |
| 125 | +Assuming you've set up a todos service, here is full request example you can try out. Be sure to replace `<token>` with a token you've retrieved from your `loginEndpoint`: |
| 126 | +
|
| 127 | +```js |
| 128 | +// List Accounts (GET http://localhost:3030/api/todos) |
| 129 | +jQuery.ajax({ |
| 130 | + url: 'http://localhost:3030/api/todos', |
| 131 | + type: 'GET', |
| 132 | + headers: { |
| 133 | + "Authorization": "Bearer <token>", |
| 134 | + "Accept": "application/json", |
| 135 | + }, |
| 136 | +}) |
| 137 | +.done(function(data, textStatus, jqXHR) { |
| 138 | + console.log("HTTP Request Succeeded: " + jqXHR.status); |
| 139 | + console.log(data); |
| 140 | +}) |
| 141 | +.fail(function(jqXHR, textStatus, errorThrown) { |
| 142 | + console.log("HTTP Request Failed", arguments); |
| 143 | +}); |
| 144 | +``` |
| 145 | +
|
| 146 | +### Authenticating Socket.io Connections |
| 147 | +
|
49 | 148 | In order to authenticate a Websocket connection, you must first obtain a token using an Ajax request to your `loginEndpoint`. You then include that token in the request. The example below is for Socket.io, but the same `query` key can be passed to Primus. |
50 | 149 |
|
51 | 150 | ```js |
52 | 151 | socket = io('', { |
53 | | - // Assuming you've already saved a token to localStorage. |
54 | | - query: 'token=' + localStorage.getItem('featherstoken'), |
55 | | - transports: ['websocket'], // optional, see below |
56 | | - forceNew:true, // optional, see below |
| 152 | + // Assuming you've already saved a token to localStorage. |
| 153 | + query: 'token=' + localStorage.getItem('featherstoken'), |
| 154 | + transports: ['websocket'], // optional, see below |
| 155 | + forceNew:true, // optional, see below |
57 | 156 | }); |
58 | 157 | ``` |
59 | 158 |
|
60 | | -In the above example, the `transports` key is only needed if you for some reason need to force the browser to only use websockets. The `forceNew` key is only needed if you have previously connected an *unauthenticated* Websocket connection and you now want to start an authenticated request. |
| 159 | +In the above example, the `transports` key is only needed if you, for some reason, need to force the browser to only use websockets. The `forceNew` key is only needed if you have previously connected an *unauthenticated* Websocket connection and you now want to start an *authenticated* request. |
| 160 | +
|
61 | 161 |
|
62 | 162 | ## Options |
63 | 163 |
|
|
0 commit comments