import { ServerRequest } from "@sveltejs/kit/types/hooks" ; import type { Auth } from "../auth" ; import { ucFirst } from "../helpers" ; import { OAuth2BaseProvider , OAuth2BaseProviderConfig , OAuth2Tokens } from "./oauth2.base" ; export interface OAuth2ProviderConfig < ProfileType = any , TokensType extends OAuth2Tokens = any > extends OAuth2BaseProviderConfig < ProfileType , TokensType > { accessTokenUrl ? : string ; authorizationUrl ? : string ; profileUrl ? : string ; clientId ? : string ; clientSecret ? : string ; scope ? : string | string [ ] ; headers ? : any ; authorizationParams ? : any ; params ? : any ; grantType ? : string ; responseType ? : string ; contentType ? : "application/json" | "application/x-www-form-urlencoded" ; } const defaultConfig = { responseType : "code" , grantType : "authorization_code" , contentType : "application/json" , } ; export class OAuth2Provider < ProfileType = any , TokensType extends OAuth2Tokens = OAuth2Tokens , ConfigType extends OAuth2ProviderConfig = OAuth2ProviderConfig < ProfileType , TokensType > > extends OAuth2BaseProvider < ProfileType , TokensType , ConfigType > { constructor ( config ) { super ( { ... defaultConfig , ... config , } ) ; } getAuthorizationUrl ( { url } , auth , state , nonce ) { const data = { state , nonce , response_type : this . config . responseType , client_id : this . config . clientId , scope : Array . isArray ( this . config . scope ) ? this . config . scope . join ( " " ) : this . config . scope ! , redirect_uri : this . getCallbackUri ( auth , url . host ) , ... ( this . config . authorizationParams ?? { } ) , } ; const authUrl = `${ this . config . authorizationUrl }?${ new URLSearchParams ( data ) }` ; return authUrl ; } async getTokens ( code , redirectUri ) { const data = { code , grant_type : this . config . grantType , client_id : this . config . clientId , redirect_uri : redirectUri , client_secret : this . config . clientSecret , ... ( this . config . params ?? { } ) , } ; let body ; if ( this . config . contentType === "application/x-www-form-urlencoded" ) { body = Object . entries ( data ) . map ( ( [ key , value ] ) => `${ encodeURIComponent ( key ) }=${ encodeURIComponent ( value ) }` ) . join ( "&" ) ; } else { body = JSON . stringify ( data ) ; } const res = await fetch ( this . config . accessTokenUrl ! , { body , method : "POST" , headers : { "Content-Type" : this . config . contentType , ... ( this . config . headers ?? { } ) , } , } ) ; return await res . json ( ) ; } async getUserProfile ( tokens ) { const res = await fetch ( this . config . profileUrl ! , { headers : { Authorization : `${ ucFirst ( tokens . token_type ) } ${ tokens . access_token }` } , } ) ; return await res . json ( ) ; } }