tutorial

49 Autentikasi Resolver Berdasarkan Context


title: 49 Autentikasi Resolver Berdasarkan Context: Pendekatan Efektif untuk Authorization di GraphQL date: 2024-06-15 author: Senior Engineer - Medium Publication tags:

  • GraphQL
  • Authorization
  • Security
  • Backend
  • NodeJS

Ketika kita berbicara tentang autentikasi di API GraphQL, ada begitu banyak metode yang bisa digunakan. Namun, sering kali developer pemula terjebak dalam satu paradigma: semua otorisasi diselesaikan pada level middleware. Padahal, dalam pengembangan sistem modern, especially di microservices dan skala besar, melakukan autentikasi resolver berdasarkan context adalah salah satu teknik yang sangat powerful, maintainable, dan scalable.

Dengan semakin populernya GraphQL di kalangan engineers backend, kebutuhan untuk membuat mekanisme authorization yang granular serta universal menjadi semakin krusial. Pada artikel kali ini, saya akan membahas pendekatan “49 Autentikasi Resolver Berdasarkan Context” — angka 49 di sini hanya penanda teknik sehingga mudah dikenali di internal company saya dulu dan kini saya share logic-nya secara umum.

Kita akan membedah konsep, contoh kode, diagram alur, serta best practice via contoh nyata yang sederhana namun aplikatif. Yuk, langsung cek!


Apa itu Resolver Context di GraphQL?

Sebelum masuk ke kode, mari pahami dulu konsep context di GraphQL. Dalam ekosistem seperti Apollo Server, context adalah objek yang disediakan pada setiap request dan diteruskan ke setiap resolver. Objek ini biasanya menyimpan data user hasil autentikasi, koneksi database, dan hal-hal yang bersifat global selama satu siklus request.

// server.js
const { ApolloServer } = require('apollo-server');

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: ({ req }) => {
    // Simulasi autentikasi via bearer token
    const token = req.headers.authorization || "";
    const user = authenticateToken(token); // your custom logic
    return { user };
  }
});

Dengan begitu, setiap resolver bisa mengakses context tersebut tanpa harus memanggil logic authentication berulang-ulang.


Resolver, Context, dan Authorization

Sebuah resolver di GraphQL bertugas untuk “menjawab” query client dengan menjalankan fungsi tertentu. Misal, kita punya resolver sederhana:

const resolvers = {
  Query: {
    profile: (_, __, context) => {
      // context.user akan selalu tersedia jika token valid
      return context.user;
    }
  }
};

Nah, teknik “49 Autentikasi Resolver Berdasarkan Context” akan memastikan setiap resolver menghormati konteks user dan hanya menjalankan logic jika pengguna memang memiliki hak akses.


Studi Kasus: Role-based Resolver Guard

Mari bicara kasus nyata: Anda punya tiga role: ADMIN, USER, GUEST. Namun, hanya ADMIN yang boleh menjalankan query tertentu.

Skema User

type User {
  id: ID!
  name: String!
  role: String!
}

type Query {
  getAllUsers: [User!]!
  profile: User!
}

Implementasi Middleware Resolver

Salah satu pola populer di ecosystem adalah decorator resolver menggunakan higher-order functions. Ini memastikan guard tetap re-usable dan clean.

function withRole(requiredRole, resolverFn) {
  return (parent, args, context, info) => {
    if (!context.user || context.user.role !== requiredRole) {
      throw new Error('Unauthorized! Forbidden access.');
    }
    return resolverFn(parent, args, context, info);
  };
}

// Example resolver
const resolvers = {
  Query: {
    getAllUsers: withRole('ADMIN', (_, __, context) => {
      return fetchAllUsersFromDB();
    }),
    profile: (_, __, context) => {
      if (!context.user)
        throw new Error("Not authenticated!");
      return context.user;
    }
  }
};

Dengan pattern ini, kita bisa easily insert authentication & authorization logic per resolver based on context. Setiap withRole bisa di-compose dengan skenario berbeda.


Simulasi: Kode Query dan Response

Mari simulasikan dua request ke endpoint GraphQL:

  1. Sebagai ADMIN:

    query {
      getAllUsers { id name role }
    }
    

    Dengan token ADMIN, berhasil dapat hasil list user.

  2. Sebagai USER:

    query {
      getAllUsers { id name role }
    }
    

    Hasil response:

    {
      "errors": [
        {
          "message": "Unauthorized! Forbidden access."
        }
      ],
      "data": {
        "getAllUsers": null
      }
    }
    

Sederhana, readable, sangat mudah di-maintain.


Tabel: Mapping Role dan Akses Resolver

Mari kita buat tabel akses role pada masing-masing resolvers—

ResolverADMINUSERGUEST
getAllUsers
profile

Penjelasan: Arsitektur Flow Autentikasi

Agar mudah dipahami, berikut flow diagram dalam format Mermaid.

flowchart TD
  A[Client Request]
  B{Apakah Token Valid?}
  C{Role Sesuai?}
  D[Return Data]
  E[Return Error]

  A --> B
  B -- Tidak --> E
  B -- Ya --> C
  C -- Tidak --> E
  C -- Ya --> D

Dari flow di atas, tampak proses validasi context berjalan dari hulu ke hilir, memastikan integritas autentikasi di semua lapisan resolver.


Tips & Best Practice

  1. Gunakan Higher-Order Resolver Functions
    Pola seperti withRole atau withAuth membuat logic reusable. Hindari penulisan logic autentikasi inline dalam resolver.

  2. Jangan Taruh Logic di Middleware Saja
    Middleware memang powerful, tapi granular authorization semestinya tetap di-resolver untuk menjaga maintainability.

  3. Simulasikan Context Beragam
    Buat suite test untuk user dengan role berbeda; pastikan semua logic berjalan sesuai aturan bisnis.

  4. Debug dan Logging Context
    Log objek context saat development untuk observability dalam tahap debugging.


Penutup

Membangun sistem autentikasi resolver berbasis context adalah teknik esensial bagi backend engineer yang ingin menjaga sistem tetap aman, scalable, dan readable. Metode “49 Autentikasi Resolver Berdasarkan Context” membawa praktik best-in-class yang mudah diadopsi untuk GraphQL API.

Dengan memanfaatkan context di setiap resolver serta pendekatan higher-order function untuk guard authorization, codebase akan tetap clean tanpa kehilangan power untuk ekspansi logic access control di masa depan.

Jika artikelnya bermanfaat, jangan lupa share dan kasih masukan di kolom komentar. Sampai jumpa di artikel engineering selanjutnya!


Referensi:

comments powered by Disqus