Social authentication

Adonis Ally is a social authentication provider for AdonisJs. It makes it super easy to authenticate users via 3rd party websites like Facebook, Twitter, Google, so on, with minimum efforts.

Here is the list of supported drivers

  • Facebook

  • Github

  • Google

  • Instagram

  • Linkedin

  • Twitter

  • Foursquare

Setup

Since ally is not installed by default, we need to install it from npm.

adonis install @adonisjs/ally

Next, register the provider inside start/app.js file.

const providers = [
  '@adonisjs/ally/providers/AllyProvider'
]

Config

Installing ally using adonis install command creates the config/services.js file if one does not exists. However, you can always access the latest configuration from github.

The configuration must be stored inside config/services.js file, under an object called ally.

module.exports = {
  ally: {
    facebook: {}
  }
}

Basic Example

Let’s start with a basic example of Login using Facebook.

Route.get('login/facebook', 'LoginController.redirect')
Route.get('facebook/callback', 'LoginController.callback')

We registered a couple of routes, to redirect the user to Facebook and then handle the response when the user is redirected back from Facebook.

Make sure the auth provider and middleware is configured correctly.
adonis make:controller Login
const User = use('App/Models/User')

class LoginController {
  async redirect ({ ally }) {
    await ally.driver('facebook').redirect()
  }

  callback ({ ally, auth }) {
    try {
      const fbUser = ally.driver('facebook').getUser()

      // user details to be saved
      const userDetails = {
        email: fbUser.getEmail(),
        token: fbUser.getAccessToken(),
        login_source: 'facebook'
      }

      // search for existing user
      const whereClause = {
        email: fbUser.getEmail()
      }

      const user = await User.findOrCreate(whereClause, userDetails)
      await auth.login(user)

      return 'Logged in'
    } catch (error) {
      return 'Unable to authenticate. Try again later'
    }
  }
}

We have a fully working login system in a few lines of code. The API is consistent across all the drivers, so it is easier to swap facebook with google or some other one.

Ally API

Below is the list of available functions.

redirect

Redirect user to the 3rd party website

await ally.driver('facebook').redirect()

getRedirectUrl

Get redirect URL back as a string over redirecting the user.

const url = await ally.driver('facebook').getRedirectUrl()

return view.render('login', { url })

scope(scopesArray)

Define runtime scopes before redirecting the user.

You must check the official OAuth documentation of the provider to get a list of available scopes.
await ally
  .driver('facebook')
  .scope(['email', 'birthday'])
  .redirect()

fields(fieldsArray)

Fields to be fetched when getting authenticated user profile.

await ally
  .driver('facebook')
  .fields(['username', 'email', 'profile_pic'])
  .getUser()

getUser

Get user profile of an authenticated user. An instance of AllyUser is returned.

User API

Below is the list of available methods on a user instance.

getName

Returns the user name

const user = await ally
  .driver('facebook')
  .getUser()

user.getName()

getEmail

Returns the user email.

Some 3rd party providers do not share email, in which case this method returns null.
user.getEmail()

getNickname

Returns the nick name/display name of the user.

user.getNickname()

getAvatar

Returns public URL to the profile picture

user.getAvatar()

getAccessToken

Returns the access token which may be used later to update the user profile.

user.getAccessToken()

getRefreshToken

Refresh token to be used when access token expires. Available only when 3rd party provider implements OAuth2.

user.getRefreshToken()

getExpires

Access token expiry data. Available only when 3rd party provider implements OAuth2.

user.getExpires()

getTokenSecret

Returns token secret. Available only when 3rd party provider uses OAuth1.

user.getTokenSecret()

getOriginal

Original payload returned by the 3rd party provider.

user.getOriginal()