refactor: better auth code
This commit is contained in:
parent
76a058a312
commit
ff7cf961f2
@ -12,39 +12,109 @@ interface TokenResponse {
|
||||
scope: string,
|
||||
}
|
||||
|
||||
export const discord = {
|
||||
name: 'discord',
|
||||
getAuthUrl: (state: string, scopes: string[] = []) => {
|
||||
const client_id = env.DISCORD_CLIENT_ID
|
||||
const redir_uri = encodeURIComponent(callbackUrl)
|
||||
const scope = scopes.join("+")
|
||||
return `https://discord.com/oauth2/authorize?client_id=${client_id}&response_type=code&redirect_uri=${redir_uri}&scope=${scope}&state=${state}`
|
||||
},
|
||||
getToken: async (code: string): Promise<TokenResponse> => {
|
||||
const api = `https://discord.com/api/oauth2/token`
|
||||
const body = new URLSearchParams({
|
||||
client_id: env.DISCORD_CLIENT_ID,
|
||||
client_secret: env.DISCORD_CLIENT_SECRET,
|
||||
grant_type: 'authorization_code',
|
||||
redirect_uri: callbackUrl,
|
||||
code,
|
||||
})
|
||||
const resp = await fetch(api, { method: 'POST', body })
|
||||
if (resp.status !== 200) {
|
||||
throw new Error("woopsies, couldnt get oauth token")
|
||||
}
|
||||
const tokenResp: any = await resp.json()
|
||||
class OauthConfig {
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
|
||||
authUrl: URL;
|
||||
tokenUrl: URL;
|
||||
|
||||
joinScopes: (scopes: string[]) => string = (scopes) => scopes.join("+");
|
||||
getAuthParams: (params: Record<string, string>, config: OauthConfig) => Record<string, string> = (params) => { return params };
|
||||
getTokenParams: (params: Record<string, string>, config: OauthConfig) => Record<string, string> = (params) => { return params };
|
||||
extractTokenResponse: (tokenResp: any) => TokenResponse = (tokenResp) => {
|
||||
return {
|
||||
accessToken: tokenResp.access_token,
|
||||
tokenType: tokenResp.token_type,
|
||||
scope: tokenResp.scope,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
tokenReqHeaders: Record<string, string> = {};
|
||||
|
||||
constructor(clientId: string, clientSecret: string, authUrl: URL | string, tokenUrl: URL | string) {
|
||||
this.clientId = clientId;
|
||||
this.clientSecret = clientSecret;
|
||||
this.authUrl = typeof authUrl === 'string' ? new URL(authUrl) : authUrl
|
||||
this.tokenUrl = typeof tokenUrl === 'string' ? new URL(tokenUrl) : tokenUrl
|
||||
}
|
||||
|
||||
withJoinScopes(f: typeof this.joinScopes) {
|
||||
this.joinScopes = f
|
||||
return this
|
||||
}
|
||||
withGetAuthParams(f: typeof this.getAuthParams) {
|
||||
this.getAuthParams = f
|
||||
return this
|
||||
}
|
||||
withGetTokenParams(f: typeof this.getTokenParams) {
|
||||
this.getTokenParams = f
|
||||
return this
|
||||
}
|
||||
withExtractTokenResponse(f: typeof this.extractTokenResponse) {
|
||||
this.extractTokenResponse = f
|
||||
return this
|
||||
}
|
||||
withTokenRequestHeaders(f: typeof this.tokenReqHeaders) {
|
||||
this.tokenReqHeaders = f
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
const genericOauthClient = (oauthConfig: OauthConfig) => {
|
||||
return {
|
||||
getAuthUrl: (state: string, scopes: string[] = []) => {
|
||||
const redirect_uri = callbackUrl
|
||||
const scope = oauthConfig.joinScopes(scopes)
|
||||
const baseParams = {
|
||||
client_id: oauthConfig.clientId,
|
||||
redirect_uri,
|
||||
scope,
|
||||
state,
|
||||
}
|
||||
const params = oauthConfig.getAuthParams(baseParams, oauthConfig)
|
||||
const urlParams = new URLSearchParams(params)
|
||||
const urlRaw = `${oauthConfig.authUrl}?${urlParams.toString()}`
|
||||
return new URL(urlRaw)
|
||||
},
|
||||
getToken: async (code: string): Promise<TokenResponse> => {
|
||||
const api = oauthConfig.tokenUrl
|
||||
const baseParams = {
|
||||
client_id: oauthConfig.clientId,
|
||||
client_secret: oauthConfig.clientSecret,
|
||||
redirect_uri: callbackUrl,
|
||||
code,
|
||||
}
|
||||
const body = new URLSearchParams(oauthConfig.getTokenParams(baseParams, oauthConfig))
|
||||
const resp = await fetch(api, { method: 'POST', body, headers: oauthConfig.tokenReqHeaders })
|
||||
if (resp.status !== 200) {
|
||||
throw new Error("woopsies, couldnt get oauth token")
|
||||
}
|
||||
const tokenResp: any = await resp.json()
|
||||
return oauthConfig.extractTokenResponse(tokenResp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const discord = {
|
||||
name: 'discord',
|
||||
...genericOauthClient(
|
||||
new OauthConfig(
|
||||
env.DISCORD_CLIENT_ID,
|
||||
env.DISCORD_CLIENT_SECRET,
|
||||
'https://discord.com/oauth2/authorize',
|
||||
'https://discord.com/api/oauth2/token',
|
||||
)
|
||||
.withGetAuthParams((params) => { return { ...params, response_type: 'code', prompt: 'none' } })
|
||||
.withGetTokenParams((params) => { return { ...params, grant_type: 'authorization_code' } })
|
||||
),
|
||||
identifyToken: async (tokenResp: TokenResponse): Promise<string> => {
|
||||
const api = `https://discord.com/api/users/@me`
|
||||
const resp = await fetch(api, {headers: {
|
||||
'Authorization': `${tokenResp.tokenType} ${tokenResp.accessToken}`
|
||||
}})
|
||||
const resp = await fetch(api, {
|
||||
headers: {
|
||||
'Authorization': `${tokenResp.tokenType} ${tokenResp.accessToken}`
|
||||
}
|
||||
})
|
||||
if (resp.status !== 200) {
|
||||
throw new Error("woopsies, couldnt validate access token")
|
||||
}
|
||||
@ -52,38 +122,26 @@ export const discord = {
|
||||
return body.username
|
||||
}
|
||||
}
|
||||
|
||||
export const github = {
|
||||
name: 'github',
|
||||
getAuthUrl: (state: string, scopes: string[] = []) => {
|
||||
const client_id = env.GITHUB_CLIENT_ID
|
||||
const redir_uri = encodeURIComponent(callbackUrl)
|
||||
const scope = encodeURIComponent(scopes.join(" "))
|
||||
return `https://github.com/login/oauth/authorize?client_id=${client_id}&redirect_uri=${redir_uri}&scope=${scope}&state=${state}`
|
||||
},
|
||||
getToken: async (code: string): Promise<TokenResponse> => {
|
||||
const api = `https://github.com/login/oauth/access_token`
|
||||
const body = new URLSearchParams({
|
||||
client_id: env.GITHUB_CLIENT_ID,
|
||||
client_secret: env.GITHUB_CLIENT_SECRET,
|
||||
redirect_uri: callbackUrl,
|
||||
code,
|
||||
})
|
||||
const resp = await fetch(api, { method: 'POST', body, headers: { 'Accept': 'application/json' } })
|
||||
if (resp.status !== 200) {
|
||||
throw new Error("woopsies, couldnt get oauth token")
|
||||
}
|
||||
const tokenResp: any = await resp.json()
|
||||
return {
|
||||
accessToken: tokenResp.access_token,
|
||||
tokenType: tokenResp.token_type,
|
||||
scope: tokenResp.scope,
|
||||
}
|
||||
},
|
||||
...genericOauthClient(
|
||||
new OauthConfig(
|
||||
env.GITHUB_CLIENT_ID,
|
||||
env.GITHUB_CLIENT_SECRET,
|
||||
'https://github.com/login/oauth/authorize',
|
||||
'https://github.com/login/oauth/access_token',
|
||||
)
|
||||
.withJoinScopes((s) => { return s.join(" ") })
|
||||
.withTokenRequestHeaders({ 'Accept': 'application/json' })
|
||||
),
|
||||
identifyToken: async (tokenResp: TokenResponse): Promise<string> => {
|
||||
const api = `https://api.github.com/user`
|
||||
const resp = await fetch(api, {headers: {
|
||||
'Authorization': `${tokenResp.tokenType} ${tokenResp.accessToken}`
|
||||
}})
|
||||
const resp = await fetch(api, {
|
||||
headers: {
|
||||
'Authorization': `${tokenResp.tokenType} ${tokenResp.accessToken}`
|
||||
}
|
||||
})
|
||||
if (resp.status !== 200) {
|
||||
throw new Error("woopsies, couldnt validate access token")
|
||||
}
|
||||
@ -130,10 +188,10 @@ export const getAuthClient = (name: string) => {
|
||||
switch (name) {
|
||||
case "discord":
|
||||
return discord
|
||||
|
||||
|
||||
case "github":
|
||||
return github
|
||||
|
||||
|
||||
default:
|
||||
return null
|
||||
}
|
||||
|
@ -40,6 +40,14 @@
|
||||
}
|
||||
|
||||
const title = getTitle(data.route);
|
||||
|
||||
const svgSquiggles = [
|
||||
[2],
|
||||
[3],
|
||||
[2],
|
||||
[3],
|
||||
[1],
|
||||
]
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@ -65,26 +73,12 @@
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="absolute -z-50">
|
||||
<defs>
|
||||
<filter id="squiggly-0">
|
||||
<feTurbulence id="turbulence" baseFrequency="0.02" numOctaves="3" result="noise" seed="0" />
|
||||
<feDisplacementMap id="displacement" in="SourceGraphic" in2="noise" scale="2" />
|
||||
</filter>
|
||||
<filter id="squiggly-1">
|
||||
<feTurbulence id="turbulence" baseFrequency="0.02" numOctaves="3" result="noise" seed="1" />
|
||||
<feDisplacementMap in="SourceGraphic" in2="noise" scale="3" />
|
||||
</filter>
|
||||
<filter id="squiggly-2">
|
||||
<feTurbulence id="turbulence" baseFrequency="0.02" numOctaves="3" result="noise" seed="2" />
|
||||
<feDisplacementMap in="SourceGraphic" in2="noise" scale="2" />
|
||||
</filter>
|
||||
<filter id="squiggly-3">
|
||||
<feTurbulence id="turbulence" baseFrequency="0.02" numOctaves="3" result="noise" seed="3" />
|
||||
<feDisplacementMap in="SourceGraphic" in2="noise" scale="3" />
|
||||
</filter>
|
||||
<filter id="squiggly-4">
|
||||
<feTurbulence id="turbulence" baseFrequency="0.02" numOctaves="3" result="noise" seed="4" />
|
||||
<feDisplacementMap in="SourceGraphic" in2="noise" scale="1" />
|
||||
{#each svgSquiggles as [scale], index}
|
||||
<filter id="squiggly-{index}">
|
||||
<feTurbulence id="turbulence" baseFrequency="0.02" numOctaves="3" result="noise" seed={index} />
|
||||
<feDisplacementMap in="SourceGraphic" in2="noise" {scale} />
|
||||
</filter>
|
||||
{/each}
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
@ -92,7 +86,7 @@
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<nav class="w-full max-h-[6vh] fixed bottom-0 z-10 bg-ralsei-black">
|
||||
<nav class="w-full min-h-[5vh] max-h-[6vh] fixed bottom-0 z-10 bg-ralsei-black">
|
||||
<div
|
||||
class="
|
||||
max-w-full max-h-fit p-1 overflow-auto
|
||||
|
Loading…
Reference in New Issue
Block a user