nuxt-auth-utils icon indicating copy to clipboard operation
nuxt-auth-utils copied to clipboard

Question: Dynamic OAuth providers activation post-build for self-hosting scenarios

Open HugoRCD opened this issue 1 year ago • 2 comments

Context

When self-hosting a Nuxt application with Docker, it would be valuable to enable/disable OAuth providers without rebuilding the image, simply by providing/removing environment variables in docker-compose.yml.

Feature Request

Would it be possible to make OAuth providers configuration truly dynamic?

The goal would be to:

  • Enable/disable OAuth providers by simply adding/removing environment variables in .env or docker-compose.yml
  • No need to rebuild the Docker image when changing OAuth configuration
  • OAuth buttons and routes would appear/disappear based on the presence of required environment variables

This would greatly improve flexibility for self-hosted deployments, allowing users to configure their authentication methods through environment variables alone.

Example use case:

# Enable only GitHub OAuth
services:
  app:
    environment:
      - NUXT_OAUTH_GITHUB_CLIENT_ID=xxx
      - NUXT_OAUTH_GITHUB_CLIENT_SECRET=xxx

# Later, enable Google OAuth by just adding variables
services:
  app:
    environment:
      - NUXT_OAUTH_GITHUB_CLIENT_ID=xxx
      - NUXT_OAUTH_GITHUB_CLIENT_SECRET=xxx
      - NUXT_OAUTH_GOOGLE_CLIENT_ID=xxx
      - NUXT_OAUTH_GOOGLE_CLIENT_SECRET=xxx

HugoRCD avatar Nov 11 '24 13:11 HugoRCD

Hi @HugoRCD

As the server helpers are tree-shakable for maximum performance and minimum server bundle size, you will have to import then and create your own dynamic provider server endpoint.

Please see an example on how to achieve this by creating a /auth/:provider endpoint:

// server/routes/auth/[provider].get.ts
import { z } from 'zod'
import { defineOAuthGitHubEventHandler, defineOAuthGoogleEventHandler } from '#imports'

const oAuthEventHandlers = {
  github: defineOAuthGitHubEventHandler,
  google: defineOAuthGoogleEventHandler
}

export default defineEventHandler(async (event) => {
  // Validate the provider
  const { provider } = await getValidatedRouterParams(event, z.object({
    provider: z.enum(['github', 'google'])
  }).parse)

  // Make sure the provider client id and secret are set
  const providerConfig = useRuntimeConfig(event).oauth[provider]
  if (!providerConfig.clientId || !providerConfig.clientSecret) {
    throw createError({
      statusCode: 400,
      statusMessage: `OAuth ${provider} is not configured`
    })
  }

  return oAuthEventHandlers[provider]({
    config: {
      // extra config for the provider
    },
    onSuccess(event, { user, tokens }) {
      // You code to handle for providers
    },
    onError(event, error) {
      // You code to handle for providers
    }
  })(event)
})

atinux avatar Nov 11 '24 16:11 atinux

Ok thanks, I'll try that then!

HugoRCD avatar Nov 11 '24 16:11 HugoRCD