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.
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.
Let's create a new Github Oauth application to use for our login example:
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:
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.
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 websiteGET 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.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!
}
oauth_identity
identity type stores a record of all social accounts a user has connected.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.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.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'
})
])