Using GraphQL API for Password Authentication and Lighthouse Laravel

Sarah Stephens
Feb 7, 2020 · 7 min read

What is GraphQL?

GraphQL is a simple query language for APIs, which provides all the relevant information about the data, present in that particular API. Avoiding text string while query writing makes GraphQL extremely easy and user-friendly while retrieving data.

GraphQL enables us to evolve APIs over the passage of time and use powerful developer tools. In addition to that, GraphQL gets you the exact data, with only one single request. With its modern compatibility, GraphQl allows to connect with back-end applications, to fulfill requirements of many clients at the same time, without dedicating separate API for each client.

In this project, I am going to use GraphQL API for Password Authentication and Lighthouse Laravel.

In order to checkout my code. Please follow the link below.

let’s start!

Step 1:

composer create-project — prefer-dist laravel/laravel gqlapp

Step 2:

composer require nuwave/lighthouse laravel/passport joselfonseca/lighthouse-graphql-passport-auth

Now I am going to configure “Laravel Passport” with our application, run php artisan migrate command to migrate all the tables.

Step 3:

Step 4:

Step 5:

Step 6:

Step 7:

Step 8:

php artisan vendor:publish — provider=”Nuwave\Lighthouse\LighthouseServiceProvider” — tag=schema

Step 9:

php artisan vendor:publish — provider=”Joselfonseca\LighthouseGraphQLPassport\Providers\LighthouseGraphQLPassportServiceProvider”

Step 10:

input LoginInput {
username: String!
password: String!
}
input RefreshTokenInput {
refresh_token: String
}
type AuthPayload {
access_token: String!
refresh_token: String!
expires_in: Int!
token_type: String!
user: User!
}
type LogoutResponse {
status: String!
message: String
}
type Tokens {
token_type: String!
expires_in: Int!
access_token: String!
refresh_token: String!
user: User!
}
type TokenResponse {
status: String!
tokens: Tokens
}
type RegisterResponse {
user: User!
}
type ForgotPasswordResponse {
status: String!
message: String
}
input RegisterInput {
name: String! @rules(apply: ["required", "string"])
email: String! @rules(apply: ["required", "email"])
password: String! @rules(apply: ["required", "confirmed", "min:8"])
password_confirmation: String!
}
input ForgotPasswordInput {
email: String!
}
input NewPasswordWithCodeInput {
email: String!
token: String!
password: String!
password_confirmation: String!
}

And Schema GraphQL like this

"A datetime string with format `Y-m-d H:i:s`, e.g. `2018-01-01 13:00:00`."
scalar DateTime @scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\DateTime")
"A date string with format `Y-m-d`, e.g. `2011-05-23`."
scalar Date @scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\Date")
type Query {
users: [User!]! @middleware(checks: ["auth:api"]) @paginate(type: "paginator" model: "App\\User")
# users: [User!]! @paginate(type: "paginator" model: "App\\User")
user(id: ID @eq): User @find(model: "App\\User")
}
type Mutation {
login (input: LoginInput @spread): AuthPayload! @field(resolver: "Joselfonseca\\LighthouseGraphQLPassport\\GraphQL\\Mutations\\Login@resolve")
refreshToken(input: RefreshTokenInput @spread): AuthPayload! @field(resolver: "Joselfonseca\\LighthouseGraphQLPassport\\GraphQL\\Mutations\\RefreshToken@resolve")
logout: LogoutResponse! @field(resolver: "Joselfonseca\\LighthouseGraphQLPassport\\GraphQL\\Mutations\\Logout@resolve")
forgotPassword(input: ForgotPasswordInput! @spread): ForgotPasswordResponse! @field(resolver: "Joselfonseca\\LighthouseGraphQLPassport\\GraphQL\\Mutations\\ForgotPassword@resolve")
updateForgottenPassword(input: NewPasswordWithCodeInput! @spread): ForgotPasswordResponse! @field(resolver: "Joselfonseca\\LighthouseGraphQLPassport\\GraphQL\\Mutations\\ResetPassword@resolve")
register(input: RegisterInput @spread): TokenResponse! @field(resolver: "Joselfonseca\\LighthouseGraphQLPassport\\GraphQL\\Mutations\\Register@resolve")
}
type User {
id: ID!
name: String!
email: String!
created_at: DateTime!
updated_at: DateTime!
}

Step 11:

Or I can install GraphQL playground by installing below command

composer require mll-lab/laravel-graphql-playground.

Step 12:

Mutations:

mutation {
login(input: {
username: "myemail@email.com",
password: "123456789qq"
}) {
access_token
expires_in
token_type
user {
id
email
name
created_at
updated_at
}}}
mutation {
register (input:{
name: "Sarah",
email: " sarahstephens727@gmail.com",
password: "asdf1234",
password_confirmation: "asdf1234"
})
{
status
tokens{
token_type
access_token
user{
name
}}}}
mutation {
logout{
status
message
}}
mutation {
forgotPassword(input:{
email: " sarahstephens727@gmail.com"
}){
status
message
}}

Now, I will get other tables data with ‘auth :api’ middleware and authorization

  1. I will add below line to my queries
users: [User!]! @middleware(checks: ["auth:api"]) @paginate(type: "paginator" model: "App\\User")

2. I will fetch data , if it gives unauthenticated error that means it is working perfectly.

3. I will add Authorization variable in header of my GraphQL query.

4. Now I will fetch data.

Creating Post tables for blog with Images:

php artisan make:migration posts

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class Posts extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->string('title');
$table->string('content');
$table->string('image');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('posts');
}}

2. I will run migration.

3. I will update my schema.graphql like this:

type User {
id: ID!
name: String!
email: String!
created_at: DateTime!
updated_at: DateTime!
posts: [Post] @hasMany
}
type Post {
id: ID!
title: String!
content: String!
user: User! @belongsTo
}

In the above code I have specified relation between users and their created posts

4. Now I will make Post Model and add below code

namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = ['user_id', 'title', 'content','image'];
public function user()
{
return $this->belongsTo(User::class);
}}

5. I will define post type

type Post {
id: ID!
user_id: Int!
title: String!
content: String!
image: Upload!
}

6. In order to accept file uploads, I must add the Upload scalar to your schema.

scalar Upload @scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\Upload")

7. Once the scalar is added, I can add it to a mutation

type Mutation {
createPost(
user_id: Int! ,
title: String! @rules(apply: ["required", "min:6"]),
content: String! @rules(apply: ["required"]),
image: Upload!
): String!
}

8. Create CreatePost.php into GraphQL > Mutations and add code below for creating a post.

namespace App\GraphQL\Mutations;
use App\Post;
class CreatePost
{
public function resolve($root, array $args): ?string
{
if($args['image']){
$file = $args['image'];
$file->storePublicly('uploads');
}
$post = new Post;
$post->user_id = $args['user_id'];
$post->title= $args['title'];
$post->content= $args['content'];
$post->image= $file->getClientOriginalName();
$post->save();
return "Post created successfully";
}}

9. Now I will test the mutation in my playground

mutation ($image:Upload!){
createPost(
user_id:1,
title:"Title 1",
content: "some text",
image: $image
)}

10 . I have created post with image upload.

Defining Relations

type User {
id: ID!
name: String!
email: String!
created_at: DateTime!
updated_at: DateTime!
posts: [Post] @hasMany
}
type Post {
id: ID!
user_id: Int!
title: String!
content: String!
image: Upload!
user: User! @belongsTo
}

2. Now I will test query posts with their author.

Uploading Multiple Files

  1. Mutation for multiple uploads like this:
type Mutation {
multiUploads(files: [Upload!]!): String
}

3. Now, I will create a class for multiUploads in the Mutation folder.

<?php
namespace App\GraphQL\Mutations;
class MultiUploads
{
/**
* Upload a file, store it on the server and return the path.
*
* @param mixed $root
* @param mixed[] $args
* @return string|null
*/
public function resolve($root, array $args): ?string
{
$files = $args['files'];
foreach($files as $file)
{
$file->storePublicly('uploads');
}
return "uploaded successfully";
}}

4. Now, I will test my mutations and see results.

I hope this will help lot of young developers, who are using Laravel and GraphQL, Cheers.

Blitz Mobile Apps

A bunch of 100+ skilled and talented developer, designers…