feat: Make OAuth optional and define it at runtime of the app
Description
This issue aims to simplify self-hosting further by enabling OAuth with minimal configuration. For instance, to activate GitHub OAuth, one need only provide the following environment variables:
- NUXT_OAUTH_GITHUB_CLIENT_ID
- NUXT_OAUTH_GITHUB_CLIENT_SECRET
To facilitate this, Shelve will now support a default authentication system utilizing a one-time password (OTP) mechanism. This update will decrease the number of required environment variables and shorten the setup time.
This issue is stale because it has been open for 30 days with no activity.
What if rework https://github.com/atinux/nuxt-auth-utils/issues/277#issuecomment-2468559614 into api route which returns available oauth methods based on provided envs?
Kinda like that:
// server/routes/auth/providers.get.ts
const providers = ['github', 'google', 'gitlab']
export default defineEventHandler((event) => {
const configured = []
const oauthProviders = useRuntimeConfig(event).oauth
for (const provider of providers) {
const providerConfig = oauthProviders[provider as keyof typeof oauthProviders]
if (providerConfig.clientId && providerConfig.clientSecret) {
configured.push(provider)
}
}
return configured
})
Or, as we know that nuxt-auth-utils propagate variables in runtimeConfig:
export default defineEventHandler((event) => {
const configured = []
const oauthProviders = useRuntimeConfig(event).oauth
for (const provider in oauthProviders) {
const providerConfig = oauthProviders[provider as keyof typeof oauthProviders]
if (providerConfig.clientId && providerConfig.clientSecret) {
configured.push(provider)
}
}
return configured
})
The only reason not to do that it is we also need to define a loader for each oauth provider existing or find a way to locally extract it, like:
// warning! uses internals
import { handlersMeta } from '#nitro-internal-virtual/server-handlers-meta'
const currentRoute = 'providers'
const authPrefix = '/auth/'
const definedProviders = handlersMeta.reduce((acc, { route }) => {
if (route && route.startsWith(authPrefix) && route !== authPrefix + currentRoute) {
acc.push(route.replace(authPrefix, ''))
}
return acc
}, [] as string[])
export default defineEventHandler((event) => {
const nitroApp = useNitroApp()
console.log(nitroApp.router.get)
const configured = []
const oauthProviders = useRuntimeConfig(event).oauth
for (const provider of definedProviders) {
const providerConfig = oauthProviders[provider as keyof typeof oauthProviders]
if (providerConfig?.clientId && providerConfig?.clientSecret) {
configured.push(provider)
}
}
return configured
})
and also this example doesn't count bluesky, which doesn't follow oauth by default: https://github.com/atinux/nuxt-auth-utils?tab=readme-ov-file#at-protocol
@AndreyYolkin I think I'll refactor this as a route api (something like your first example) as Atinux suggested and I'll standardize this endpoint to more simply define a provider 🤔
@AndreyYolkin And nothing to see but I pushed in prod most of what you suggested if you want to give me feedback on it or what to see if it's what you're thinking of!
@AndreyYolkin And nothing to see but I pushed in prod most of what you suggested if you want to give me feedback on it or what to see if it's what you're thinking of!
I've already tried the changes you applied, thanks! I'll left some comments on dedicated issues, but generally speaking that's a great work
This issue is stale because it has been open for 30 days with no activity.