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:
import { auth } from '@tensei/auth'
import { tensei } from '@tensei/core'
export default 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 export default 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.
import { auth } from '@tensei/auth'
import { tensei } from '@tensei/core'
export default 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'
})
])