diff --git a/README.md b/README.md index 515af1ed..a272f797 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,7 @@ Supported providers: - GitHub - Spotify - Google +- Twitch You can add your favorite provider by creating a new file in [src/runtime/server/lib/oauth/](./src/runtime/server/lib/oauth/). @@ -158,6 +159,9 @@ Example: `~/server/routes/auth/github.get.ts` ```ts export default oauth.githubEventHandler({ + config: { + emailRequired: true + }, async onSuccess(event, { user, tokens }) { await setUserSession(event, { user: { diff --git a/playground/.env.example b/playground/.env.example index 60e761b7..50a7035b 100644 --- a/playground/.env.example +++ b/playground/.env.example @@ -8,3 +8,6 @@ NUXT_OAUTH_SPOTIFY_CLIENT_SECRET= # Google OAuth NUXT_OAUTH_GOOGLE_CLIENT_ID= NUXT_OAUTH_GOOGLE_CLIENT_SECRET= +# Twitch OAuth +NUXT_OAUTH_TWITCH_CLIENT_ID= +NUXT_OAUTH_TWITCH_CLIENT_SECRET= diff --git a/playground/pages/index.vue b/playground/pages/index.vue index 14a8780a..c448df7f 100644 --- a/playground/pages/index.vue +++ b/playground/pages/index.vue @@ -1,7 +1,9 @@ - diff --git a/playground/server/routes/auth/twitch.get.ts b/playground/server/routes/auth/twitch.get.ts index f4fd88e0..79ce81d0 100644 --- a/playground/server/routes/auth/twitch.get.ts +++ b/playground/server/routes/auth/twitch.get.ts @@ -1,4 +1,7 @@ export default oauth.twitchEventHandler({ + config: { + emailRequired: true, + }, async onSuccess(event, { user }) { await setUserSession(event, { user: { @@ -9,4 +12,4 @@ export default oauth.twitchEventHandler({ return sendRedirect(event, '/') } -}) \ No newline at end of file +}) diff --git a/src/runtime/server/lib/oauth/twitch.ts b/src/runtime/server/lib/oauth/twitch.ts index 42e9d55d..04800c36 100644 --- a/src/runtime/server/lib/oauth/twitch.ts +++ b/src/runtime/server/lib/oauth/twitch.ts @@ -26,6 +26,12 @@ export interface OAuthTwitchConfig { */ scope?: string[] + /** + * Require email from user, adds the ['user:read:email'] scope if not present + * @default false + */ + emailRequired?: boolean + /** * Twitch OAuth Authorization URL * @default 'https://id.twitch.tv/oauth2/authorize' @@ -65,7 +71,10 @@ export function twitchEventHandler({ config, onSuccess, onError }: OAuthConfig) const redirectUrl = getRequestURL(event).href if (!code) { - config.scope = config.scope || ['user:read:email'] + config.scope = config.scope || [] + if (config.emailRequired && !config.scope.includes('user:read:email')) { + config.scope.push('user:read:email') + } // Redirect to Twitch Oauth page return sendRedirect( event, @@ -107,16 +116,28 @@ export function twitchEventHandler({ config, onSuccess, onError }: OAuthConfig) } const accessToken = tokens.access_token - const user: any = await ofetch('https://api.twitch.tv/helix/users', { + const users: any = await ofetch('https://api.twitch.tv/helix/users', { headers: { - "Client-ID": config.clientId, + 'Client-ID': config.clientId, Authorization: `Bearer ${accessToken}` } }) + const user = users.data?.[0] + + if (!user) { + const error = createError({ + statusCode: 500, + message: 'Could not get Twitch user', + data: tokens + }) + if (!onError) throw error + return onError(event, error) + } + return onSuccess(event, { tokens, user }) }) -} \ No newline at end of file +}