Skip to content
This repository has been archived by the owner on Mar 22, 2022. It is now read-only.

Commit

Permalink
1.0 Pre-release (#336)
Browse files Browse the repository at this point in the history
* cleaning up dependencies

* removing auth redirects and exposing middleware

* expanding express middleware

* moving what I can in services to setup method

* updating dependencies

* cleaning up middleware and adding debug logs

* cleaning up services and adding debug logs

* changing options for populate user hook to conform with other options

* cleaning up main index file

* fixing lint errors

* getting example app working

* fixing options for populate user middlware

* fixing socket logout emitting

* restructuring so you can set hooks to construct your token payload if you want to customize it

* Default to a session cookie instead of 1 day

* Switch to "user" instead of "data" for the response from auth

* Make sure we clear the user out of locals so that you don't end up in a weird state.

* Allow passing options when creating a JWT.

Used to customize the type of token we want to generate (ie. confirmation, password reset, etc.)

* setting version

* don't throw an error in the decode token middleware

* bump version

* clearing cookie if use not found. Setting cookie age to same as JWT

* bump version

* Don’t mix options when signing tokens (#255)

Fixes #254.

* Attempt to get token right away. (#252)

* Attempt to get token right away.

This makes it so that we don’t have to wait for an async response in order to start making authenticated requests.

* Also set up localStorage.

* fix restrict to owner hook methods. Closes #228

* bump version

* cookies should get set regardless of whether it was an xhr request if enabled

* bumping version

* adding migration guide

* reorganizing middleware, hooks and services

* updaing mocha

* updating migration doc of things left to doc/complete

* fixing a bunch of the tests and adding tests for all new middleware

* cleaning up client side tests. Still failing

* getting all tests passing

* updating all middleware to not have default and pull from global config

* finished consolidating options

* bumping version

* adding more details to migration guide

* fix typo missing 'd'

* Fix typo and simplify wording.

* normalize the callbackURL

If the callbackURL doesn’t begin with a slash, the Passport `authenticate()` call will mess up the URL depending on the referrer’s url.  So if the page is `domain.com/auth/github`, the callback URL will become `domain.com/auth/auth/github`.  This normalizes the URL so that relative URLs always begin with a leading slash and absolute URLs don’t get touched.

* Make sure the provider plugin name doesn't overwrite the OAuth provider name

* consistency: `callbackUrl` should be `callbackURL`

* Normalize comparison URL & fix typo

This performs the same normalization to the comparison URL for the callback (as is done for the callbackURL).  Also fixes typo in callbackUrl, updates it to callbackURL.

* Always use service lookup.

Previously, we were setting up this._tokenService and this._userService in the `setup` function.  This was a problem because not all services are registered by the time `setup` runs.  In order to continue to allow the passing of either strings or an actual service object, this PR checks if we only have a string reference to the service stored.  If so, it uses the `app.service` method of service lookup before attempting to use the service.  This also fixes a problem that was occurring when trying to call this._userService or this._tokenService when this was undefined inside the middleware callbacks.

* DRY up the dynamic token and user service lookup.

This moves the dynamic service lookup to a function to be a bit more DRY.

* OAuth require successRedirect with default successHandler

If a successHandler hasn’t been passed, then the default `successHandler` will be used.  The `successRedirect` will now be required in that scenario.

* First cut for authentication middleware (#305)

* First cut for authentication middleware

* Fix service methods

* Allow passing user service and service name

* First cut for authentication middleware (#305)

* First cut for authentication middleware

* Fix service methods

* Allow passing user service and service name

* Cookies will match jwt expiry by default. (#308)

* Cookies will match jwt expiry by default.

* Add missing makeExpiry function.

* Store config at `app.config` (#312)

* Store config at `app.config`

* Use app.set to store config.

* Add test.

* adding instanbul code coverage

* Remove permissions hooks and middleware which will be put into feathers-permissions (#307)

* Started implementation of more modularized module structure

* Some reorganization

* Implement Socket new authentication

* More reorganization and start of integration tests

* eslint fix

* More integration tests and cleanup

* reogranizing

* Applying latest changes and merging with dev other branch

* Socket.io authentication tests and login logout event

* Improving socket tests and adding Primus

* Some cleanup

* Better error verification tests

* Implement login and logout events for REST authentication (#325)

* Fix tests

* wip

* first cut of auth working with passport. Clean up and tests to do

* fixing event middleware resolution

* Keep github together

* Keep twitter together

* getting tests passing. Still a couple more to do

* removing unused hooks for now. May bring some back later

* fixing lint errors

* removing hashPassword hook. It now lives in feathers-authentication-local

* adding a migration guide and new features docs

* adding more detail to migration doc

* cleaning up dependencies

* getting tests passing again

* adding some more tests. Implementing chained strategies

* cleaning up dependencies

* finishing integration tests and handling socket logout timeout

* cleaning up example app

* fixing up example

* updating README

* updating API docs
  • Loading branch information
ekryski committed Nov 16, 2016
1 parent 69cd5f2 commit 97f8004
Show file tree
Hide file tree
Showing 94 changed files with 4,712 additions and 6,508 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Expand Up @@ -28,4 +28,7 @@ node_modules
.lock-wscript

lib/
data.db
coverage/
data.db
_backup/
yarn.lock
3 changes: 2 additions & 1 deletion .jshintrc
Expand Up @@ -13,12 +13,13 @@
"quotmark": "single",
"regexp": true,
"undef": true,
"unused": true,
"unused": false,
"strict": false,
"trailing": true,
"smarttabs": true,
"white": false,
"node": true,
"expr": true,
"globals": {
"window": true,
"it": true,
Expand Down
1 change: 1 addition & 0 deletions .npmignore
@@ -1,5 +1,6 @@
.editorconfig
.jshintrc
.istanbul.yml
.travis.yml
.babelrc
.idea/
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
@@ -1,3 +1,4 @@
sudo: false
language: node_js
node_js:
- node
Expand Down
175 changes: 138 additions & 37 deletions README.md
Expand Up @@ -9,7 +9,7 @@

> Add Authentication to your FeathersJS app.
`feathers-authentication` adds shared [PassportJS](http://passportjs.org/) authentication for Feathers HTTP REST and WebSockets services using [JSON Web Tokens](http://jwt.io/).
`feathers-authentication` adds shared [PassportJS](http://passportjs.org/) authentication for Feathers HTTP REST and WebSockets transports using [JSON Web Tokens](http://jwt.io/).


## Installation
Expand All @@ -20,55 +20,156 @@ npm install feathers-authentication --save

## Documentation

Please refer to the [Authentication documentation](http://docs.feathersjs.com/authentication/readme.html) for more details:
<!-- Please refer to the [Authentication documentation](http://docs.feathersjs.com/authentication/readme.html) for more details. -->

- [Local Auth Tutorial](http://docs.feathersjs.com/authentication/local.html) - How to implement a username and password-based authentication.
- [Use Hooks for Authorization](http://docs.feathersjs.com/authorization/readme.html) - Learn about the bundled hooks.
## API

This module contains:

## Complete Example
1. The main entry function
2. An `authenticate` hook
3. The authentication `service`
4. Socket listeners
5. Express middleware
6. A [Passport](http://passportjs.org/) adapter

### Hooks

Here's an example of a Feathers server that uses `feathers-authentication` for local auth. It includes a `users` service that uses `feathers-mongoose`. *Note that it does NOT implement any authorization.*
There is just 1 hook now called `authenticate`. This can be used to authenticate a service method with a given strategy.

```js
import feathers from 'feathers';
import hooks from 'feathers-hooks';
import bodyParser from 'body-parser';
import authentication from 'feathers-authentication';
import { hooks as authHooks } from 'feathers-authentication';
import mongoose from 'mongoose';
import service from 'feathers-mongoose';

const port = 3030;
const Schema = mongoose.Schema;
const UserSchema = new Schema({
email: {type: String, required: true, unique: true},
password: {type: String, required: true },
createdAt: {type: Date, 'default': Date.now},
updatedAt: {type: Date, 'default': Date.now}
app.service('authentication').hooks({
before: {
create: [
// You can chain multiple strategies
auth.hooks.authenticate(['jwt', 'local']),
],
remove: [
auth.hooks.authenticate('jwt')
]
}
});
let UserModel = mongoose.model('User', UserSchema);
```


### Express Middleware

Just like hooks there is an `authenticate` middleware. It is used the exact same way you would the regular passport express middleware.

```js
app.post('/login', auth.express.authenticate('local', { successRedirect: '/app', failureRedirect: '/login' }));
```

The other middleware are included but typically you don't need to worry about them.

- `emitEvents` - emit `login` and `logout` events
- `exposeCookies` - expose cookies to Feathers so they are available to hooks and services
- `exposeHeaders` - expose headers to Feathers so they are available to hooks and services
- `failureRedirect` - support redirecting on auth failure. Only triggered if `hook.redirect` is set.
- `successRedirect` - support redirecting on auth success. Only triggered if `hook.redirect` is set.
- `setCookie` - support setting the JWT access token in a cookie. Only enabled if cookies are enabled.

### Default Options

mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/feathers');
The following default options will be mixed in with your global `auth` object from your config file. It will set the mixed options back to to the app so that they are available at any time by `app.get('auth')`. They can all be overridden and are depended upon by some of the authentication plugins.

let app = feathers()
.configure(feathers.rest())
.configure(feathers.socketio())
```js
{
path: '/authentication', // the authentication service path
header: 'Authorization', // the header to use when using JWT auth
entity: 'user', // the entity that will be added to the request, socket, and hook.params. (ie. req.user, socket.user, hook.params.user)
service: 'users', // the service to look up the entity
passReqToCallback: true, // whether the request object should be passed to the strategies `verify` function
session: false, // whether to use sessions
cookie: {
enabled: false, // whether the cookie should be enabled
name: 'feathers-jwt', // the cookie name
httpOnly: false, // whether the cookie should not be available to client side JavaScript
secure: true // whether cookies should only be available over HTTPS
},
jwt: {
header: { typ: 'access' }, // by default is an access token but can be any type
audience: 'https://yourdomain.com', // The resource server where the token is processed
subject: 'anonymous', // Typically the entity id associated with the JWT
issuer: 'feathers', // The issuing server, application or resource
algorithm: 'HS256', // the algorithm to use
expiresIn: '1d' // the access token expiry
}
}
```

## Complementary Plugins

The following plugins are complementary but entirely optional:

- [feathers-authentication-client](https://github.com/feathersjs/feathers-authentication-client)
- [feathers-authentication-local](https://github.com/feathersjs/feathers-authentication-local)
- [feathers-authentication-jwt](https://github.com/feathersjs/feathers-authentication-jwt)
- [feathers-authentication-oauth1](https://github.com/feathersjs/feathers-authentication-oauth1)
- [feathers-authentication-oauth2](https://github.com/feathersjs/feathers-authentication-oauth2)
- [feathers-permissions](https://github.com/feathersjs/feathers-permissions)

## Migrating to 1.0
Refer to [the migration guide](./docs/migrating.md).

## Complete Example
Here's an example of a Feathers server that uses `feathers-authentication` for local auth.

**Note:** This does NOT implement any authorization. Use [feathers-permissions](https://github.com/feathersjs/feathers-permissions) for that.

```js
const feathers = require('feathers');
const rest = require('feathers-rest');
const socketio = require('feathers-socketio');
const hooks = require('feathers-hooks');
const memory = require('feathers-memory');
const bodyParser = require('body-parser');
const errors = require('feathers-errors');
const errorHandler = require('feathers-errors/handler');
const local = require('feathers-authentication-local');
const jwt = require('feathers-authentication-jwt');
const auth = require('feathers-authentication');

const app = feathers();
app.configure(rest())
.configure(socketio())
.configure(hooks())
.use(bodyParser.json())
.use(bodyParser.urlencoded({ extended: true }))
// Configure feathers-authentication
.configure(authentication());

app.use('/users', new service('user', {Model: UserModel}))
.configure(auth({ secret: 'supersecret' }))
.configure(local())
.configure(jwt())
.use('/users', memory())
.use('/', feathers.static(__dirname + '/public'))
.use(errorHandler());

app.service('authentication').hooks({
before: {
create: [
// You can chain multiple strategies
auth.hooks.authenticate(['jwt', 'local']),
customizeJWTPayload()
],
remove: [
auth.hooks.authenticate('jwt')
]
}
});

let userService = app.service('users');
userService.before({
create: [authHooks.hashPassword('password')]
// Add a hook to the user service that automatically replaces
// the password with a hash of the password before saving it.
app.service('users').hooks({
before: {
find: [
auth.hooks.authenticate('jwt')
],
create: [
local.hooks.hashPassword({ passwordField: 'password' })
]
}
});

let server = app.listen(port);
let server = app.listen(3030);
server.on('listening', function() {
console.log(`Feathers application started on localhost:${port}`);
});
Expand All @@ -84,7 +185,7 @@ import feathers from 'feathers/client';
import hooks from 'feathers-hooks';
import socketio from 'feathers-socketio/client';
import localstorage from 'feathers-localstorage';
import authentication from 'feathers-authentication/client';
import authentication from 'feathers-authentication-client';

const socket = io('http://localhost:3030/');
const app = feathers()
Expand All @@ -93,7 +194,7 @@ const app = feathers()
.configure(authentication({ storage: window.localStorage }));

app.authenticate({
type: 'local',
strategy: 'local',
'email': 'admin@feathersjs.com',
'password': 'admin'
}).then(function(result){
Expand Down

0 comments on commit 97f8004

Please sign in to comment.