Skip to main content

User Authentication

Authentication Flow Through GraphQL API

This document describes the steps needed to use the Propeller GraphQL API’s authentication features.

Important field are

  • accessToken: This is the token that can be sent over to any other request using the authorization/Bearer token. This can be stored in a session/cookie with a ttl of the expirationTime
  • refreshToken: This token can be used to fetch a new accessToken in the case the old activeToken times out. The refreshToken can be stored for a longer time.
  • expirationTime: The lifespan of the accessToken. After you created the session we can now send the accessToken to each next request, please do so also for anonymous users.
curl https://api.helice.cloud/graphql
-X POST
-H "Accept: application/json"
-H "Authorization: Bearer {accessToken}"
-d "{{graphql_query}}"

Register a new User

When you have an anonymous session you can now upgrade the session to a registered user account.

We do this using the userRegister() mutation:

mutation UserRegister{
userRegister(
input: {
firstName: "John"
middleName: ""
lastName: "Doe"
email: "sander123@propel.us"
phone: "020-6717171"
gender: M
company: "Propeller"
password: "secret_password"
parentId: 109
}
) {
user {
id
userId
}
session {
accessToken
refreshToken
expirationTime
}
}
}

The userRegister() mutation generally does two things:

  1. It creates the user in the Propeller Backend
  2. It creates an authentication user in Google Identity Platform (GCIP)/Firebase for the given email and password. When the email address already exists in GCIP the api will throw an error.

The userRegister() mutation returns a RegisterUserResponse object with 2 fields.

  • User: holds the full user data, as you would also get with the user and viewer queries.
  • Session: A new session object with new accessToken, refreshToken and expirationTime. These tokens should replace the tokens stored earlier.

Login

To login an existing user we use the login() mutation where we provide the email address.

mutation Login{
login(
input: {
email: "sander@propel.us",
password: "secret_password"
}
) {
session {
isAnonymous
email
accessToken
refreshToken
expirationTime
}
}
}

The returned session will provide you with new tokens that you can use to replace your anonymous tokens with. You can validate a successful login through the isAnonymous field in the session.

Logout

For now there is no specific Logout functionality, but the logout effect can be achieved by removing the stored tokens, and, if needed, start a new anonymous session.

Password recovery email sending

First we need to check if we can create a password recovery link:

mutation PasswordResetLink{
passwordResetLink(input: {
email: "s.vleugelhof@propel.us"
redirectUrl: "https://helice.cloud/login"
language: "nl"
})
}

The redirectUrl is the page the user should be redirected to after the password is reset, most likely the login page on the front-end. Domain used need to be registered in firebase as “Authorized domain”

This will either generate a successful response:

{
"data": {
"passwordResetLink": "https://helice.cloud/__/auth/action?mode=resetPassword&oobCode=-W-kU7cRA5LD2M8g6_MgMQJtTa_qo3jUHPkhwoSdE8AAAAGCGpsZEw&apiKey=AIzaSyCW5zkUks1iQIqxMy5twA_4ZmgzBCEmV6Q&continueUrl=https%3A%2F%2Fhelice.cloud&lang=en&tenantId=example-tenant-id"
}
}

Or generate an error:

{
"errors": [
{
"message": "There is no user record corresponding to the provided email.",
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"serviceName": "Auth",
"exception": {
"errorInfo": {
"code": "auth/email-not-found",
"message": "There is no user record corresponding to the provided email."
},
"codePrefix": "auth",
"message": "There is no user record corresponding to the provided email.",
"locations": [
{
"line": 1,
"column": 10
}
],
"path": [
"passwordResetLink"
]
}
}
}
],
"data": null
}

On a successful response we can start generating the email to send to the client.

For proper personalization you could fetch the user’s data from the users api:

query User{
user(login: "s.vleugelhof@propel.us") {
firstName
lastName
middleName
gender
email
}
}
warning

The current functionality for sending an email uses templates from within the Propeller repository. This situation will be changed in the near future as this repository will be depreciated. It's recommended that you use externally sourced email templates for all production implementations. Additionally this mutation is only accessible by system keys - you may require an additional API key to deliver messages.

To send an email transactional email in the right template, use the publishEmailEvent mutation in our API, make sure the type is set to transactional:

mutation PublishEmailEvent{
publishEmailEvent(
input: {
type: transactional
to: { email: "s.vleugelhof@propel.us" }
subject: "Uw wachtwoord resetten?"
content: "Dear {{var:user.firstName}}, <br>
We received a request to reset your {{var:site.name}} password.<br>
Please use the following link to reset your password <a href=\"{{var:resetLink}}\">{{var:resetLink}}</a><br><br>
If you haven't request a new password from us, no action is needed."
variables: {
user: { firstName: "John", lastName: "Doe" }
site: { name: "Example Site" }
resetLink: "https://helice.cloud/login"
}
}
) {
messageId
}
}

siteId is needed to determine the template that will be used, and could be changed to channel at some point.

If the messageId is returned, it means that the message is successfully sent, other than that, you cannot really do anything with that id.

Note: the use of {{var:user.firstName}} is based on Mailjet’s template parser.