use TwitchAuth
This commit is contained in:
+28
-116
@@ -1,150 +1,62 @@
|
|||||||
/** @param {Response} response */
|
import * as TwitchAuth from './TwitchAuth.mjs'
|
||||||
async function validateResponse(response){
|
/** @type {import('./TwitchAuth.mjs').TwitchToken} */
|
||||||
if(!response.ok){
|
let token=null;
|
||||||
throw new Error(response.status+' '+response.url+' '+await response.text())
|
|
||||||
}
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
export function request_auth(client_id,scope,redirect_uri=location.origin+location.pathname){
|
export function request_auth(client_id,scope,redirect_uri=location.origin+location.pathname){
|
||||||
const url=new URL('https://id.twitch.tv/oauth2/authorize')
|
return TwitchAuth.requestAuthCode(client_id,scope.split(' '))
|
||||||
url.search=new URLSearchParams({
|
|
||||||
client_id:client_id,
|
|
||||||
response_type:'code',
|
|
||||||
scope:scope
|
|
||||||
})
|
|
||||||
const dialog=document.createElement('dialog')
|
|
||||||
dialog.innerHTML='Redirecting you to Twitch for authorization<br>'
|
|
||||||
dialog.innerHTML+='If you see this multiple times, please report it as a bug<br>'
|
|
||||||
const okButton=document.createElement('button')
|
|
||||||
okButton.innerHTML='OK'
|
|
||||||
okButton.onclick=()=>location.assign(url.href+'&redirect_uri='+redirect_uri)
|
|
||||||
dialog.appendChild(okButton)
|
|
||||||
const cancelButton=document.createElement('button')
|
|
||||||
cancelButton.innerHTML='Cancel'
|
|
||||||
cancelButton.onclick=()=>dialog.close()
|
|
||||||
dialog.appendChild(cancelButton)
|
|
||||||
document.body.appendChild(dialog)
|
|
||||||
dialog.showModal()
|
|
||||||
//if(window.confirm((document.title||location.origin+location.pathname)+' redirecting you to twitch for authorization')){
|
|
||||||
// location.assign(url.href+'&redirect_uri='+redirect_uri)
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_url_params(){
|
export function get_url_params(){
|
||||||
return Object.fromEntries(new URLSearchParams(location.search))
|
return Object.fromEntries(new URLSearchParams(location.search))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetch_tokens(client_id,code,redirect_uri=location.origin+location.path){
|
export async function fetch_tokens(client_id,code,redirect_uri=location.origin+location.path){
|
||||||
const url=new URL('/oauth2/token',import.meta.url)
|
client_id=client_id
|
||||||
const body=new URLSearchParams({
|
token=await TwitchAuth.exchangeCode(client_id,code)
|
||||||
client_id:client_id,
|
token.client_id=client_id
|
||||||
code:code,
|
return token
|
||||||
grant_type:'authorization_code',
|
|
||||||
redirect_uri:redirect_uri
|
|
||||||
}).toString()
|
|
||||||
return fetch(url.href,{
|
|
||||||
method:'POST',
|
|
||||||
headers:{'Content-Type':'application/x-www-form-urlencoded'},
|
|
||||||
body:body
|
|
||||||
})
|
|
||||||
.then(validateResponse)
|
|
||||||
.then(response=>response.json())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_headers(tokens){
|
export function get_headers(tokens){
|
||||||
return {
|
return {
|
||||||
'Authorization':'Bearer '+tokens.access_token,
|
'Authorization':'Bearer '+token.access_token,
|
||||||
'Client-ID':tokens.client_id
|
'Client-ID':token.client_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validate_tokens(tokens){
|
export async function validate_tokens(tokens){
|
||||||
const url=new URL('https://id.twitch.tv/oauth2/validate')//,import.meta.url)
|
const validation=await TwitchAuth.validateToken(tokens.auth_token)
|
||||||
return fetch(url,{headers:{
|
Object.assign(tokens,validation)
|
||||||
'Authorization':'OAuth '+tokens.access_token
|
tokens.scopes=validation.scope
|
||||||
}}).then(validateResponse)
|
token=tokens
|
||||||
.then(response=>response.json())
|
return token
|
||||||
.then(validation=>{
|
|
||||||
if('message' in validation){
|
|
||||||
throw new Error(validation.message)
|
|
||||||
}
|
|
||||||
Object.assign(tokens,validation)
|
|
||||||
delete tokens.scope
|
|
||||||
return tokens
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function set_local_tokens(client_id,tokens){
|
export function set_local_tokens(client_id,tokens){
|
||||||
localStorage.setItem(client_id,JSON.stringify(tokens))
|
token=tokens
|
||||||
return tokens
|
return token
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_local_tokens(client_id){
|
export function get_local_tokens(client_id){
|
||||||
return JSON.parse(localStorage.getItem(client_id))
|
return token
|
||||||
}
|
}
|
||||||
|
|
||||||
export function refresh_tokens(client_id,refresh_token){
|
export async function refresh_tokens(client_id,refresh_token){
|
||||||
const url=new URL('/oauth2/token',import.meta.url)
|
token=await TwitchAuth.refreshToken(client_id,refresh_token)
|
||||||
const body=new URLSearchParams({
|
return token
|
||||||
client_id:client_id,
|
|
||||||
grant_type:'refresh_token',
|
|
||||||
refresh_token:refresh_token
|
|
||||||
}).toString()
|
|
||||||
return fetch(url.href,{
|
|
||||||
method:'POST',
|
|
||||||
headers:{'Content-Type':'application/x-www-form-urlencoded'},
|
|
||||||
body:body
|
|
||||||
})
|
|
||||||
.then(validateResponse)
|
|
||||||
.then(response=>response.json())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function set_refresh_timeout(client_id,tokens){
|
export function set_refresh_timeout(client_id,tokens){
|
||||||
return setTimeout(()=>{
|
return setTimeout(()=>{
|
||||||
get_tokens(client_id)
|
TwitchAuth.refreshToken(client_id,tokens.refresh_token)
|
||||||
.then(new_tokens=>Object.assign(tokens,new_tokens))
|
.then(new_tokens=>Object.assign(tokens,new_tokens))
|
||||||
},tokens.expires_in*1000)
|
},tokens.expires_in*999)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get_tokens(client_id,scope=null,redirect_uri=location.origin+location.pathname,auth_return=false){
|
export async function get_tokens(client_id,scope=null,redirect_uri=location.origin+location.pathname,auth_return=false){
|
||||||
let tokens=get_local_tokens(client_id)||get_url_params()
|
token=await TwitchAuth.getUserToken(client_id,scope.split(' ')).then(validate_tokens)
|
||||||
if('code' in tokens){
|
set_refresh_timeout(client_id,token)
|
||||||
tokens=await fetch_tokens(client_id,tokens.code,redirect_uri)
|
return token
|
||||||
.catch((error)=>console.warn(error))
|
|
||||||
}
|
|
||||||
if(!tokens){
|
|
||||||
tokens={refresh_token:undefined}
|
|
||||||
}
|
|
||||||
return refresh_tokens(client_id,tokens.refresh_token)
|
|
||||||
.then(validate_tokens)
|
|
||||||
.then(tokens=>{
|
|
||||||
tokens.auth_headers=get_headers(tokens)
|
|
||||||
set_refresh_timeout(client_id,tokens)
|
|
||||||
return set_local_tokens(client_id,tokens)
|
|
||||||
})
|
|
||||||
.catch(async (error)=>{
|
|
||||||
if(error.message==="Failed to fetch"){
|
|
||||||
await new Promise(function(resolve,reject){
|
|
||||||
setTimeout(resolve,1000)
|
|
||||||
})
|
|
||||||
return get_tokens(client_id,scope,redirect_uri,auth_return)
|
|
||||||
}
|
|
||||||
if(scope){
|
|
||||||
request_auth(client_id,scope,redirect_uri)
|
|
||||||
}else{
|
|
||||||
const dialog=document.createElement('dialog')
|
|
||||||
dialog.innerHTML=(document.title||location.origin+location.pathname)+' has been logged out of your twitch account<br>'
|
|
||||||
const okButton=document.createElement('button')
|
|
||||||
okButton.innerHTML='OK'
|
|
||||||
okButton.onclick=()=>dialog.close()
|
|
||||||
dialog.appendChild(okButton)
|
|
||||||
document.body.appendChild(dialog)
|
|
||||||
dialog.showModal()
|
|
||||||
localStorage.clear(client_id)
|
|
||||||
}
|
|
||||||
throw error
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default get_tokens
|
export default get_tokens
|
||||||
Reference in New Issue
Block a user