UNPKG

@rlanz/ally-twitch

Version:

<p align="center"> <img src="https://github.com/RomainLanz/ally-twitch/assets/2793951/d3ccf29b-6169-4563-b932-5b15258a7fa3" alt="@rlanz/ally-twitch"> </p

148 lines (124 loc) 3.69 kB
/** * @rlanz/ally-twitch * * @license MIT * @copyright Romain Lanz <romain.lanz@pm.me> */ import { Oauth2Driver } from '@adonisjs/ally' import type { HttpContext } from '@adonisjs/core/http' import type { ApiRequestContract, RedirectRequestContract } from '@adonisjs/ally/types' import type { TwitchDriverConfig, TwitchScopes, TwitchToken } from './types/main.js' export class TwitchDriver extends Oauth2Driver<TwitchToken, TwitchScopes> { /** * The URL to hit to exchange the authorization code for the access token */ protected accessTokenUrl = 'https://id.twitch.tv/oauth2/token' /** * The URL for the redirect request. The user will be redirected on this page * to authorize the request. */ protected authorizeUrl = 'https://id.twitch.tv/oauth2/authorize' /** * The URL to hit to get the user details */ protected userInfoUrl = 'https://api.twitch.tv/helix/users' /** * The param name for the authorization code */ protected codeParamName = 'code' /** * The param name for the error */ protected errorParamName = 'error' /** * Cookie name for storing the "twitch_oauth_state" */ protected stateCookieName = 'twitch_oauth_state' /** * Parameter name to be used for sending and receiving the state * from Twitch */ protected stateParamName = 'state' /** * Parameter name for defining the scopes */ protected scopeParamName = 'scope' /** * Scopes separator */ protected scopesSeparator = ' ' constructor( ctx: HttpContext, public config: TwitchDriverConfig ) { super(ctx, config) this.loadState() } protected configureRedirectRequest(request: RedirectRequestContract<TwitchScopes>) { request.scopes(this.config.scopes || ['user:read:email']) request.param('response_type', 'code') request.param('grant_type', 'authorization_code') } /** * Returns the HTTP request with the authorization header set */ protected getAuthenticatedRequest(url: string, token: string) { const request = this.httpClient(url) request.header('Authorization', `Bearer ${token} `) request.header('Client-id', this.config.clientId) request.header('Accept', 'application/json') request.parseAs('json') return request } /** * Fetches the user info from the Twitch API */ protected async getUserInfo(token: string, callback?: (request: ApiRequestContract) => void) { const request = this.getAuthenticatedRequest(this.userInfoUrl, token) if (typeof callback === 'function') { callback(request) } const body = await request.get() const user = body.data[0] return { id: user.id, nickName: user.login, name: user.display_name, email: user.email, emailVerificationState: 'unsupported' as const, avatarUrl: user.profile_image_url, original: user, } } /** * Find if the current error code is for access denied */ accessDenied(): boolean { const error = this.getError() if (!error) { return false } return error === 'access_denied' } /** * Returns details for the authorized user */ async user(callback?: (request: ApiRequestContract) => void) { const token = await this.accessToken(callback) const user = await this.getUserInfo(token.token, callback) return { ...user, token, } } /** * Finds the user by the access token */ async userFromToken(token: string, callback?: (request: ApiRequestContract) => void) { const user = await this.getUserInfo(token, callback) return { ...user, token: { token, type: 'bearer' as const }, } } }