mirror of
				https://github.com/Dan6erbond/sk-auth.git
				synced 2025-10-26 10:22:56 +01:00 
			
		
		
		
	added twitch provider (#22)
This commit is contained in:
		
							parent
							
								
									ae203f06db
								
							
						
					
					
						commit
						615ff5fee3
					
				
							
								
								
									
										2
									
								
								app/src/global.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								app/src/global.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -3,6 +3,8 @@ | ||||
| interface ImportMetaEnv { | ||||
|   VITE_GOOGLE_OAUTH_CLIENT_ID: string; | ||||
|   VITE_GOOGLE_OAUTH_CLIENT_SECRET: string; | ||||
|   VITE_TWITCH_OAUTH_CLIENT_ID: string; | ||||
|   VITE_TWITCH_OAUTH_CLIENT_SECRET: string; | ||||
|   VITE_FACEBOOK_OAUTH_CLIENT_ID: string; | ||||
|   VITE_FACEBOOK_OAUTH_CLIENT_SECRET: string; | ||||
|   VITE_TWITTER_API_KEY: string; | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| import { SvelteKitAuth } from "sk-auth"; | ||||
| import { | ||||
|   TwitchOAuth2Provider, | ||||
|   FacebookOAuth2Provider, | ||||
|   GoogleOAuth2Provider, | ||||
|   RedditOAuth2Provider, | ||||
| @ -15,6 +16,13 @@ export const appAuth = new SvelteKitAuth({ | ||||
|         return { ...profile, provider: "google" }; | ||||
|       }, | ||||
|     }), | ||||
|     new TwitchOAuth2Provider({ | ||||
|       clientId: import.meta.env.VITE_TWITCH_OAUTH_CLIENT_ID, | ||||
|       clientSecret: import.meta.env.VITE_TWITCH_OAUTH_CLIENT_SECRET, | ||||
|       profile(profile) { | ||||
|         return { ...profile, provider: "twitch" }; | ||||
|       }, | ||||
|     }), | ||||
|     new FacebookOAuth2Provider({ | ||||
|       clientId: import.meta.env.VITE_FACEBOOK_OAUTH_CLIENT_ID, | ||||
|       clientSecret: import.meta.env.VITE_FACEBOOK_OAUTH_CLIENT_SECRET, | ||||
|  | ||||
| @ -36,6 +36,38 @@ | ||||
|   <br /> | ||||
| 
 | ||||
|   <div class={clsx("flex", "flex-col", "justify-items-stretch", "space-y-4")}> | ||||
|     <a | ||||
|       href="/api/auth/signin/twitch" | ||||
|       class={clsx( | ||||
|         "text-sm", | ||||
|         "md:text-base", | ||||
|         "inline-flex", | ||||
|         "space-x-4", | ||||
|         "py-2", | ||||
|         "px-4", | ||||
|         "border-gray-400", | ||||
|         "rounded", | ||||
|         "hover:no-underline", | ||||
|         "border", | ||||
|         "hover:bg-gray-100", | ||||
|         "transition-colors", | ||||
|         "items-center", | ||||
|       )} | ||||
|     > | ||||
|       <svg viewBox="0 0 300 300" class={clsx("h-4", "w-4", "md:h-6", "md:w-6")}> | ||||
|         <path | ||||
|           fill-rule="evenodd" | ||||
|           clip-rule="evenodd" | ||||
|           fill="#65459B" | ||||
|           d="M215.2 260.8h-58.7L117.4 300H78.3v-39.2H6.6V52.2L26.1 0h267.3v182.6l-78.2 78.2zm52.2-91.2V26.1H52.2v189.1h58.7v39.1l39.1-39.1h71.7l45.7-45.6z" | ||||
|         /><path | ||||
|           fill="#65459B" | ||||
|           d="M195.6 78.3v78.3h26.1V78.3h-26.1zm-71.7 78.2H150V78.3h-26.1v78.2z" | ||||
|         /> | ||||
|       </svg> | ||||
|       <span>Sign in with Twitch</span> | ||||
|     </a> | ||||
| 
 | ||||
|     <a | ||||
|       href="/api/auth/signin/google" | ||||
|       class={clsx( | ||||
|  | ||||
| @ -1,4 +1,6 @@ | ||||
| export { Provider } from "./base"; | ||||
| export { TwitchOAuth2Provider } from "./twitch"; | ||||
| export type { TwitchProfile, TwitchTokens } from "./twitch"; | ||||
| export { GoogleOAuth2Provider } from "./google"; | ||||
| export type { GoogleProfile, GoogleTokens } from "./google"; | ||||
| export { TwitterAuthProvider } from "./twitter"; | ||||
|  | ||||
							
								
								
									
										57
									
								
								src/providers/twitch.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/providers/twitch.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| import { OAuth2Provider, OAuth2ProviderConfig } from "./oauth2"; | ||||
| import { ucFirst } from "../helpers"; | ||||
| 
 | ||||
| export interface TwitchProfile { | ||||
| 	id: string; | ||||
| 	login: string; | ||||
| 	display_name: string; | ||||
| 	type?: string; | ||||
| 	broadcaster_type?: string; | ||||
| 	description: boolean; | ||||
| 	profile_image_url: string; | ||||
| 	offline_image_url: string; | ||||
| 	view_count: number; | ||||
| 	email: string; | ||||
| 	created_at: string; | ||||
| } | ||||
| 
 | ||||
| export interface TwitchTokens { | ||||
| 	access_token: string; | ||||
| 	expires_in: number; | ||||
| 	scope: string; | ||||
| 	token_type: string; | ||||
| 	refresh_token: string; | ||||
| } | ||||
| 
 | ||||
| type TwitchOAuth2ProviderConfig = OAuth2ProviderConfig<TwitchProfile, TwitchTokens>; | ||||
| 
 | ||||
| const defaultConfig: Partial<TwitchOAuth2ProviderConfig> = { | ||||
| 	id: "twitch", | ||||
| 	scope: "user:read:email", | ||||
| 	accessTokenUrl: "https://id.twitch.tv/oauth2/token", | ||||
| 	authorizationUrl: "https://id.twitch.tv/oauth2/authorize", | ||||
| 	profileUrl: "https://api.twitch.tv/helix/users", | ||||
| }; | ||||
| 
 | ||||
| export class TwitchOAuth2Provider extends OAuth2Provider< | ||||
| 	TwitchProfile, | ||||
| 	TwitchTokens, | ||||
| 	TwitchOAuth2ProviderConfig | ||||
| > { | ||||
| 	constructor(config: TwitchOAuth2ProviderConfig) { | ||||
| 		super({ | ||||
| 			...defaultConfig, | ||||
| 			...config, | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	async getUserProfile(tokens: TwitchTokens): Promise<TwitchProfile> { | ||||
| 		const headers = { | ||||
| 			'Client-ID': this.config.clientId + '', | ||||
| 			'Accept': 'application/vnd.twitchtv.v5+json', | ||||
| 			'Authorization': `Bearer ${tokens.access_token}` | ||||
| 		}; | ||||
| 		const { data: [profile] } = await fetch(this.config.profileUrl!, { headers: headers }).then(res => res.json()) | ||||
| 		return profile | ||||
| 	} | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user