Social auth

How to easily integrate social authentication with Tensei

You might need users to login using external providers such as Github, Facebook, or LinkedIn. Thanks to the grant, Tensei auth supports a wide range of providers.

Enable social authentication

This feature is disabled by default. To enable it, first you need to install the @tensei/social-auth package.

yarn add @tensei/social-auth

# Or with npm
npm install --save @tensei/social-auth

Finally, you need to configure at least one social provider. Let's configure Github login in this example:

const { auth } = require('@tensei/auth')
const { tensei } = require('@tensei/core')

tensei()
    .plugins([
        auth()
            .social('github', {
                key: process.env.GITHUB_KEY,
                secret: process.env.GITHUB_SECRET,
                scope: ['user', 'user:email'],
                clientCallback: 'https://dashboard.awesome-app.com'
            })
    ])

To enable a provider, call the .social() method, pass the provider name, and pass a second argument with the provider options such as client key, client secret and request scopes.

Social auth flow

Let's create a new Github Oauth application to use for our login example:

new github oauth application

  • Make sure the Homepage URL is the URL to your client-side application

  • Make sure the Authorization callback URL points to your backend API, specific to the connect/<provider>/callback path.

  • Copy the client id and secret from your newly created oauth application and provide them in your Tensei configuration:

new github oauth application details

  • The Login or Register button on your client-side application should point to <backend-url>/connect/<provider> path. For example, in this case, these buttons should point to http://localhost:8810/connect/github.

  • The backend API will redirect the user to Github, and once authorized, the backend API will redirect the user to your client-side application with an access_token in the query string, or an error if something went wrong. This access token is NOT the access token from the oauth provider, but a unique random token generated by Tensei behind the scenes to ensure security.

  • Your client-side application then needs to grab this access token, and call the backend-api to either register or login the user.

Rest API

The following endpoints will be created on your server application:

  • GET connect/:provider. Redirect your users to this endpoint so they can be sent to provider website
  • GET connect/:provider/callback. The Oauth provider will redirect users back to this backend endpoint. This should be the Authorization callback URL added to your auth provider.
  • POST auth/social/login. Your client-side application calls this endpoint with the access_token to login a user.
  • POST auth/social/register. Your client-side application calls this endpoint with the access_token to register a user.

GraphQL API

The following types, queries and mutations will be added to the GraphQL API:

type oauth_identity {
  id: ID!
  user: user
  provider: String
  created_at: Date
  updated_at: Date
}

type user {
  id: ID!
  email: String
  created_at: Date
  updated_at: Date
  oauth_identities__count(where: oauth_identity_where_query): Int
  oauth_identities(offset: Int, limit: Int, where: oauth_identity_where_query, order_by: oauth_identity_query_order): [oauth_identity]
}

type login_user_response {
    user: user!
}

type register_user_response {
    user: user!
}

input user_social_auth_login_input {
    access_token: String!
}

input user_social_auth_register_input {
    access_token: String!
}

extend type Mutation {
    user_social_auth_login(object: user_social_auth_login_input!): login_user_response!
    user_social_auth_register(object: user_social_auth_register_input!): register_user_response!
}
  • The new oauth_identity identity type stores a record of all social accounts a user has connected.
  • The user_social_auth_login mutation may be used to login a user. You need to call this mutation with the access_token sent to the client-side of your application.
  • The user_social_auth_register mutation may be used to register a new user. You need to call this mutation with the access_token sent to the client-side of your application.

Client callback

If you configure the client-side url of your app using the tensei().clientUrl() method, the user is redirected back to this url. You may customize the route where the user is redirected to by adding a clientCallback option to the provider options.

const { auth } = require('@tensei/auth')
const { tensei } = require('@tensei/core')

tensei()
    .plugins([
        auth()
            .social('github', {
                key: process.env.GITHUB_KEY,
                secret: process.env.GITHUB_SECRET,
                scope: ['user', 'user:email'],
                clientCallback: 'https://app.tenseijs.com/users/auth'
            })
    ])