Compare commits
10 Commits
0715bf11a3
...
939fb83119
| Author | SHA1 | Date |
|---|---|---|
|
|
939fb83119 | 3 years ago |
|
|
2ebe7a3c0d | 3 years ago |
|
|
49a43f0698 | 3 years ago |
|
|
fd5cbe0114 | 3 years ago |
|
|
3027d04584 | 3 years ago |
|
|
c207fcc949 | 3 years ago |
|
|
9b770cf95c | 3 years ago |
|
|
e6e73d7d84 | 3 years ago |
|
|
499fff799f | 3 years ago |
|
|
0ba083fc9e | 3 years ago |
2 changed files with 190 additions and 8 deletions
@ -1,7 +1,173 @@ |
|||
import * as cookie from 'https://deno.land/std@0.188.0/http/cookie.ts' |
|||
|
|||
export class Auth { |
|||
constructor({ |
|||
baseUrl, |
|||
remoteBaseUrl, |
|||
giteaAppBaseUrl, |
|||
giteaApiBaseUrl, |
|||
giteaWebBaseUrl, |
|||
giteaClientId, |
|||
giteaClientSecret |
|||
}) { |
|||
this.baseUrl = baseUrl |
|||
this.remoteBaseUrl = remoteBaseUrl |
|||
this.giteaAppBaseUrl = giteaAppBaseUrl |
|||
this.giteaApiBaseUrl = giteaApiBaseUrl |
|||
this.giteaWebBaseUrl = giteaWebBaseUrl |
|||
this.giteaClientId = giteaClientId |
|||
this.giteaClientSecret = giteaClientSecret |
|||
} |
|||
|
|||
redirectUrl(state) { |
|||
const url = new URL( |
|||
this.giteaWebBaseUrl + '/login/oauth/authorize' |
|||
) |
|||
const search = new URLSearchParams() |
|||
search.set('response_type', 'code') |
|||
search.set('client_id', this.giteaClientId) |
|||
search.set('redirect_uri', this.callbackUrl) |
|||
search.set('state', state) |
|||
url.search = search.toString() |
|||
return url.toString() |
|||
} |
|||
|
|||
buildState() { |
|||
const timestamp = new Date().valueOf() |
|||
const randomInt = Math.floor(Math.random() * 10000) |
|||
// TODO: sign
|
|||
return `${randomInt}-${timestamp}` |
|||
} |
|||
|
|||
get callbackUrl() { |
|||
return this.remoteBaseUrl + '/api/auth/callback' |
|||
} |
|||
|
|||
async redirect(event) { |
|||
const state = this.buildState() |
|||
const url = this.redirectUrl(state) |
|||
const headers = new Headers({ |
|||
Location: url |
|||
}) |
|||
cookie.setCookie(headers, { |
|||
name: 'oauth.gitea.state', |
|||
value: state, |
|||
}) |
|||
event.respondWith(new Response('', { |
|||
headers, |
|||
status: 302, |
|||
})) |
|||
} |
|||
|
|||
get tokenEndpoint() { |
|||
return ( |
|||
this.giteaAppBaseUrl + |
|||
'/login/oauth/access_token' |
|||
) |
|||
} |
|||
|
|||
async getToken(code) { |
|||
const resp = await fetch(this.tokenEndpoint, { |
|||
method: 'POST', |
|||
headers: { |
|||
Accept: 'application/json', |
|||
'Content-Type': 'application/json', |
|||
}, |
|||
body: JSON.stringify({ |
|||
grant_type: 'authorization_code', |
|||
code, |
|||
client_id: this.giteaClientId, |
|||
client_secret: this.giteaClientSecret, |
|||
redirect_uri: this.callbackUrl, |
|||
}), |
|||
}) |
|||
return await resp.json() |
|||
} |
|||
|
|||
saveTokens(headers, data) { |
|||
cookie.setCookie(headers, { |
|||
name: 'oauth.gitea.accessToken', |
|||
value: data.access_token, |
|||
}) |
|||
cookie.setCookie(headers, { |
|||
name: 'oauth.gitea.refreshToken', |
|||
value: data.refresh_token, |
|||
}) |
|||
cookie.setCookie(headers, { |
|||
name: 'oauth.gitea.expires', |
|||
value: String( |
|||
Math.floor(new Date().valueOf() / 1000) + |
|||
data.expires_in |
|||
), |
|||
}) |
|||
} |
|||
|
|||
async callback(event) { |
|||
const url = new URL(event.request.url) |
|||
const { state, code } = Object.fromEntries( |
|||
url.searchParams.entries() |
|||
) |
|||
const cookies = cookie.getCookies( |
|||
event.request.headers |
|||
) |
|||
const headers = new Headers({ |
|||
Location: '/#/' |
|||
}) |
|||
if (cookies['oauth.gitea.state'] !== state) { |
|||
event.respondWith(new Response('invalid state', { |
|||
status: 401, |
|||
})) |
|||
return |
|||
} |
|||
const data = await this.getToken(code) |
|||
cookie.deleteCookie(headers, 'oauth.gitea.state') |
|||
this.saveTokens(headers, data) |
|||
event.respondWith(new Response('', { |
|||
headers, |
|||
status: 302, |
|||
})) |
|||
} |
|||
|
|||
async refreshToken(refresh_token) { |
|||
const resp = await fetch(this.tokenEndpoint, { |
|||
method: 'POST', |
|||
headers: { |
|||
Accept: 'application/json', |
|||
'Content-Type': 'application/json', |
|||
}, |
|||
body: JSON.stringify({ |
|||
refresh_token, |
|||
grant_type: 'refresh_token', |
|||
}) |
|||
}) |
|||
return await resp.json() |
|||
} |
|||
|
|||
async refresh(event) { |
|||
const headers = new Headers() |
|||
const cookies = cookie.getCookies( |
|||
event.request.headers |
|||
) |
|||
const data = await this.refreshToken(body) |
|||
this.saveTokens(headers, data) |
|||
event.respondWith( |
|||
new Response(JSON.stringify({}), {headers}) |
|||
) |
|||
} |
|||
|
|||
async serve(event) { |
|||
const {pathname} = new URL(event.request.url) |
|||
const u = this.baseUrl |
|||
if (pathname === `${u}/api/auth`) { |
|||
await this.redirect(event) |
|||
} else if (pathname === `${u}/api/auth/callback`) { |
|||
await this.callback(event) |
|||
} else if (pathname === `${u}/api/auth/refresh`) { |
|||
await this.refresh(event) |
|||
} else { |
|||
event.respondWith(new Response( |
|||
'extract query and redirect', {status: 200} |
|||
'Not Found', {status: 404} |
|||
)) |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue