Skip to content

Commit

Permalink
Merge branch 'release-2.0.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Aug 16, 2017
2 parents a85ed87 + 47fcfe5 commit 90d39dd
Show file tree
Hide file tree
Showing 12 changed files with 702 additions and 4 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,14 @@
<a name="2.0.3"></a>
## [2.0.3](https://github.com/adonisjs/adonis-auth/compare/v2.0.2...v2.0.3) (2017-08-16)


### Features

* **middleware:** add auth middleware ([50e7346](https://github.com/adonisjs/adonis-auth/commit/50e7346))
* **schemes:** add api tokens scheme ([b4c98d7](https://github.com/adonisjs/adonis-auth/commit/b4c98d7))



<a name="2.0.2"></a>
## [2.0.2](https://github.com/adonisjs/adonis-auth/compare/v2.0.1...v2.0.2) (2017-08-08)

Expand Down
3 changes: 3 additions & 0 deletions instructions.md
Expand Up @@ -14,8 +14,11 @@ Next you need to do is register couple of middleware to ensure everything works

Middleware are defined inside `start/kernel.js` file. Make sure to define the middleware after `Adonis/Middleware/Session`, since authentication relies on sessions unless you are using JWT etc.

Note: Make sure you have setup sessions middleware ( if using session scheme )

```js
const globalMiddleware = [
'Adonis/Middleware/Session', // after this
'Adonis/Middleware/AuthInit'
]
```
Expand Down
4 changes: 2 additions & 2 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "@adonisjs/auth",
"version": "2.0.2",
"version": "2.0.3",
"description": "Offical authentication provider for Adonis framework",
"main": "index.js",
"directories": {
Expand Down Expand Up @@ -52,7 +52,7 @@
"test/**/*.spec.js"
],
"exclude": [
"src/ExceptionHandler/index.js"
"src/ExceptionHandler/*"
]
},
"standard": {
Expand Down
17 changes: 17 additions & 0 deletions providers/AuthProvider.js
Expand Up @@ -53,6 +53,22 @@ class AuthProvider extends ServiceProvider {
})
}

/**
* Register auth middleware under `Adonis/Middleware/Auth` namespace.
*
* @method _registerAuthMiddleware
*
* @return {void}
*
* @private
*/
_registerAuthMiddleware () {
this.app.bind('Adonis/Middleware/Auth', (app) => {
const Auth = require('../src/Middleware/Auth')
return new Auth(app.use('Adonis/Src/Config'))
})
}

/**
* Register namespaces to the IoC container
*
Expand All @@ -64,6 +80,7 @@ class AuthProvider extends ServiceProvider {
this._registerAuth()
this._registerAuthManager()
this._registerAuthInitMiddleware()
this._registerAuthMiddleware()
}

/**
Expand Down
9 changes: 8 additions & 1 deletion src/Exceptions/index.js
Expand Up @@ -102,11 +102,18 @@ class ExpiredJwtToken extends InvalidLoginException {
}
}

class InvalidApiToken extends InvalidLoginException {
static invoke () {
return new this('The api is invalid or missing', 401, 'E_INVALID_API_TOKEN')
}
}

module.exports = {
UserNotFoundException,
PasswordMisMatchException,
InvalidJwtToken,
InvalidRefreshToken,
ExpiredJwtToken,
InvalidLoginException
InvalidLoginException,
InvalidApiToken
}
83 changes: 83 additions & 0 deletions src/Middleware/Auth.js
@@ -0,0 +1,83 @@
'use strict'

/*
* adonis-auth
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

const debug = require('debug')('adonis:auth')

class Auth {
constructor (Config) {
const authenticator = Config.get('auth.authenticator')
this.scheme = Config.get(`auth.${authenticator}.scheme`, null)
}

/**
* Authenticate the user using one of the defined
* schemes or the default scheme
*
* @method handle
*
* @param {Object} options.auth
* @param {Function} next
*
* @return {void}
*/
async handle ({ auth }, next, schemes) {
let lastError = null
let authenticatedScheme = null

schemes = schemes instanceof Array === true ? schemes : [this.scheme]
debug('attempting to authenticate via %j scheme(s)', schemes)

/**
* Loop over all the defined schemes and wait until use is logged
* via anyone
*/
for (const scheme of schemes) {
try {
await auth.authenticator(scheme).check()
debug('authenticated using %s scheme', scheme)
authenticatedScheme = scheme
lastError = null
break
} catch (error) {
debug('authentication failed using %s scheme', scheme)
lastError = error
}
}

/**
* If there is an error from all the schemes
* then throw it back
*/
if (lastError) {
throw lastError
}

/**
* If user got logged then set the `current` property
* on auth, which is reference to the scheme via
* which user got authenticated.
*/
if (authenticatedScheme) {
/**
* If logged in scheme is same as the default scheme, the reference
* the actual authenticator instance, otherwise create a new
* one for the scheme via which user got authenticated
*/
auth.current = authenticatedScheme === this.scheme
? auth.authenticatorInstance
: auth.authenticator(authenticatedScheme)
}

await next()
}
}

module.exports = Auth
131 changes: 131 additions & 0 deletions src/Schemes/Api.js
@@ -0,0 +1,131 @@
'use strict'

/*
* adonis-auth
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

const uuid = require('uuid')
const BaseScheme = require('./Base')
const GE = require('@adonisjs/generic-exceptions')
const CE = require('../Exceptions')

class ApiScheme extends BaseScheme {
/**
* Validate user credentials
*
* @method validate
*
* @param {String} uid
* @param {String} password
* @param {Boolean} returnUser
*
* @return {Object}
*
* @throws {UserNotFoundException} If unable to find user with uid
* @throws {PasswordMisMatchException} If password mismatches
*/
async validate (uid, password, returnUser) {
const user = await this._serializerInstance.findByUid(uid)
if (!user) {
throw CE.UserNotFoundException.invoke(`Cannot find user with ${this._config.uid} as ${uid}`)
}

const validated = await this._serializerInstance.validateCredentails(user, password)
if (!validated) {
throw CE.PasswordMisMatchException.invoke('Cannot verify user password')
}

return returnUser ? user : !!user
}

/**
* Attempt to valid the user credentials and then
* generates a new token for it.
*
* @method attempt
*
* @param {String} uid
* @param {String} password
*
* @return {String}
*/
async attempt (uid, password) {
const user = await this.validate(uid, password, true)
return this.generate(user)
}

/**
* Generates a personal API token for a user
*
* @method generate
* @async
*
* @param {Object} user
*
* @return {Object}
*/
async generate (user) {
/**
* Throw exception when user is not persisted to
* database
*/
const userId = user[this.primaryKey]
if (!userId) {
throw GE.RuntimeException.invoke('Primary key value is missing for user')
}

const token = uuid.v4().replace(/-/g, '')
await this._serializerInstance.saveToken(user, token, 'api_token')
return { type: 'bearer', token }
}

/**
* Check whether the api token has been passed
* in the request header and is it valid or
* not.
*
* @method check
*
* @return {Boolean}
*/
async check () {
if (this.user) {
return true
}

const token = this.getAuthHeader()
if (!token) {
throw CE.InvalidApiToken.invoke()
}

this.user = await this._serializerInstance.findByToken(token, 'api_token')

/**
* Throw exception when user is not found
*/
if (!this.user) {
throw CE.InvalidApiToken.invoke()
}
return true
}

/**
* Makes sure user is loggedin and then
* returns the user back
*
* @method getUser
*
* @return {Object}
*/
async getUser () {
await this.check()
return this.user
}
}

module.exports = ApiScheme
3 changes: 2 additions & 1 deletion src/Schemes/index.js
Expand Up @@ -12,5 +12,6 @@
module.exports = {
session: require('./Session'),
basic: require('./BasicAuth'),
jwt: require('./Jwt')
jwt: require('./Jwt'),
api: require('./Api')
}

0 comments on commit 90d39dd

Please sign in to comment.