Files
trpc-nuxt/docs/content/1.get-started/3.tips/3.authorization.md
wobsoriano 1d7be4642d update docs
2022-11-24 13:07:13 -08:00

2.7 KiB

title
title
Authorization

Authorization

The createContext function is called for each incoming request so here you can add contextual information about the calling user from the request object.

::alert{type="info"} Before you can access request headers in any context or middleware, you need to set the outgoing request headers. See here. ::

Create context from request headers

import type { H3Event } from 'h3'
import { inferAsyncReturnType } from '@trpc/server'
import { decodeAndVerifyJwtToken } from './somewhere/in/your/app/utils'

export async function createContext(event: H3Event) {
  // Create your context based on the request object
  // Will be available as `ctx` in all your resolvers

  // This is just an example of something you might want to do in your ctx fn
  const authorization = getRequestHeader(event, authorization)
  async function getUserFromHeader() {
    if (authorization) {
      const user = await decodeAndVerifyJwtToken(authorization.split(' ')[1])
      return user
    }
    return null
  }
  const user = await getUserFromHeader()

  return {
    user,
  }
}
type Context = inferAsyncReturnType<typeof createContext>

Option 1: Authorize using resolver

import { TRPCError, initTRPC } from '@trpc/server'
import type { Context } from '../context'

export const t = initTRPC.context<Context>().create()

const appRouter = t.router({
  // open for anyone
  hello: t.procedure
    .input(z.string().nullish())
    .query(({ input, ctx }) => `hello ${input ?? ctx.user?.name ?? 'world'}`),
  // checked in resolver
  secret: t.procedure.query(({ ctx }) => {
    if (!ctx.user) {
      throw new TRPCError({ code: 'UNAUTHORIZED' })
    }
    return {
      secret: 'sauce',
    }
  }),
})

Option 2: Authorize using middleware

import { TRPCError, initTRPC } from '@trpc/server'

export const t = initTRPC.context<Context>().create()

const isAuthed = t.middleware(({ next, ctx }) => {
  if (!ctx.user?.isAdmin) {
    throw new TRPCError({ code: 'UNAUTHORIZED' })
  }
  return next({
    ctx: {
      user: ctx.user,
    },
  })
})

// you can reuse this for any procedure
export const protectedProcedure = t.procedure.use(isAuthed)

t.router({
  // this is accessible for everyone
  hello: t.procedure
    .input(z.string().nullish())
    .query(({ input, ctx }) => `hello ${input ?? ctx.user?.name ?? 'world'}`),
  admin: t.router({
    // this is accessible only to admins
    secret: protectedProcedure.query(({ ctx }) => {
      return {
        secret: 'sauce',
      }
    }),
  }),
})

This page is entirely based on authorization docs of tRPC with a minimal change made to work with Nuxt.