kopia lustrzana https://github.com/cloudflare/wildebeest
Merge pull request #157 from cloudflare/sven/gh-86
gh-86: implement authorization screenpull/158/head
commit
74f0ff9097
|
@ -35,11 +35,11 @@ describe('Mastodon APIs', () => {
|
||||||
const db = await makeDB()
|
const db = await makeDB()
|
||||||
|
|
||||||
let req = new Request('https://example.com/oauth/authorize')
|
let req = new Request('https://example.com/oauth/authorize')
|
||||||
let res = await oauth_authorize.handleRequest(req, db, userKEK, accessDomain, accessAud)
|
let res = await oauth_authorize.handleRequestPost(req, db, userKEK, accessDomain, accessAud)
|
||||||
assert.equal(res.status, 400)
|
assert.equal(res.status, 400)
|
||||||
|
|
||||||
req = new Request('https://example.com/oauth/authorize?scope=foobar')
|
req = new Request('https://example.com/oauth/authorize?scope=foobar')
|
||||||
res = await oauth_authorize.handleRequest(req, db, userKEK, accessDomain, accessAud)
|
res = await oauth_authorize.handleRequestPost(req, db, userKEK, accessDomain, accessAud)
|
||||||
assert.equal(res.status, 400)
|
assert.equal(res.status, 400)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ describe('Mastodon APIs', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const req = new Request('https://example.com/oauth/authorize?' + params)
|
const req = new Request('https://example.com/oauth/authorize?' + params)
|
||||||
const res = await oauth_authorize.handleRequest(req, db, userKEK, accessDomain, accessAud)
|
const res = await oauth_authorize.handleRequestPost(req, db, userKEK, accessDomain, accessAud)
|
||||||
assert.equal(res.status, 400)
|
assert.equal(res.status, 400)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ describe('Mastodon APIs', () => {
|
||||||
const req = new Request('https://example.com/oauth/authorize?' + params, {
|
const req = new Request('https://example.com/oauth/authorize?' + params, {
|
||||||
headers,
|
headers,
|
||||||
})
|
})
|
||||||
const res = await oauth_authorize.handleRequest(req, db, userKEK, accessDomain, accessAud)
|
const res = await oauth_authorize.handleRequestPost(req, db, userKEK, accessDomain, accessAud)
|
||||||
assert.equal(res.status, 403)
|
assert.equal(res.status, 403)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ describe('Mastodon APIs', () => {
|
||||||
const req = new Request('https://example.com/oauth/authorize?' + params, {
|
const req = new Request('https://example.com/oauth/authorize?' + params, {
|
||||||
headers,
|
headers,
|
||||||
})
|
})
|
||||||
const res = await oauth_authorize.handleRequest(req, db, userKEK, accessDomain, accessAud)
|
const res = await oauth_authorize.handleRequestPost(req, db, userKEK, accessDomain, accessAud)
|
||||||
assert.equal(res.status, 302)
|
assert.equal(res.status, 302)
|
||||||
|
|
||||||
const location = new URL(res.headers.get('location') || '')
|
const location = new URL(res.headers.get('location') || '')
|
||||||
|
@ -223,7 +223,7 @@ describe('Mastodon APIs', () => {
|
||||||
const req = new Request('https://example.com/oauth/authorize', {
|
const req = new Request('https://example.com/oauth/authorize', {
|
||||||
method: 'OPTIONS',
|
method: 'OPTIONS',
|
||||||
})
|
})
|
||||||
const res = await oauth_authorize.handleRequest(req, db, userKEK, accessDomain, accessAud)
|
const res = await oauth_authorize.handleRequestPost(req, db, userKEK, accessDomain, accessAud)
|
||||||
assert.equal(res.status, 200)
|
assert.equal(res.status, 200)
|
||||||
assertCORS(res)
|
assertCORS(res)
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { component$ } from '@builder.io/qwik'
|
||||||
|
import * as access from 'wildebeest/backend/src/access'
|
||||||
|
import type { Client } from 'wildebeest/backend/src/mastodon/client'
|
||||||
|
import { getClientById } from 'wildebeest/backend/src/mastodon/client'
|
||||||
|
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
|
||||||
|
import { WildebeestLogo } from '~/components/MastodonLogo'
|
||||||
|
|
||||||
|
export const clientLoader = loader$<{ DATABASE: D1Database }, Promise<Client>>(async ({ platform, query }) => {
|
||||||
|
const client_id = query.get('client_id') || ''
|
||||||
|
const client = await getClientById(platform.DATABASE, client_id)
|
||||||
|
if (client === null) {
|
||||||
|
throw new Error('client not found')
|
||||||
|
}
|
||||||
|
return client
|
||||||
|
})
|
||||||
|
|
||||||
|
export const userLoader = loader$<{ DATABASE: D1Database; domain: string }, Promise<{ email: string }>>(
|
||||||
|
async ({ cookie }) => {
|
||||||
|
const jwt = cookie.get('CF_Authorization')
|
||||||
|
if (jwt === null) {
|
||||||
|
throw new Error('missing authorization')
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// TODO: eventually, verify the JWT with Access, however this
|
||||||
|
// is not critical.
|
||||||
|
const payload = access.getPayload(jwt.value)
|
||||||
|
return { email: payload.email }
|
||||||
|
} catch (err: unknown) {
|
||||||
|
console.warn(err.stack)
|
||||||
|
throw new Error('failed to validate Access JWT')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export default component$(() => {
|
||||||
|
const client = clientLoader.use().value
|
||||||
|
const user = userLoader.use().value
|
||||||
|
return (
|
||||||
|
<div class="flex flex-col p-5 items-center">
|
||||||
|
<h1 class="text-center mt-7 mb-9 flex items-center">
|
||||||
|
<WildebeestLogo size="large" />
|
||||||
|
</h1>
|
||||||
|
<div class="text-left">
|
||||||
|
<p>Signed in as: {user.email}.</p>
|
||||||
|
<p>
|
||||||
|
<a href="/cdn-cgi/access/logout">Click here to change account</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p class="text-left">
|
||||||
|
<b>{client.name}</b> would like permission to access your account. It is a third-party application. If you do
|
||||||
|
not trust it, then you should not authorize it.
|
||||||
|
</p>
|
||||||
|
<form method="post" class="flex flex-col w-full max-w-md">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="mb-9 bg-wildebeest-vibrant-600 hover:bg-wildebeest-vibrant-500 p-3 text-white text-uppercase border-wildebeest-vibrant-600 text-lg text-semi outline-none border rounded hover:border-wildebeest-vibrant-500 focus:border-wildebeest-vibrant-500"
|
||||||
|
>
|
||||||
|
Authorize
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export const head: DocumentHead = () => {
|
||||||
|
return {
|
||||||
|
title: 'Wildebeest Authorization required',
|
||||||
|
meta: [
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
content: 'Wildebeest Authorization required',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,11 +11,11 @@ import { getPersonByEmail } from 'wildebeest/backend/src/activitypub/actors'
|
||||||
// Extract the JWT token sent by Access (running before us).
|
// Extract the JWT token sent by Access (running before us).
|
||||||
const extractJWTFromRequest = (request: Request) => request.headers.get('Cf-Access-Jwt-Assertion') || ''
|
const extractJWTFromRequest = (request: Request) => request.headers.get('Cf-Access-Jwt-Assertion') || ''
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env }) => {
|
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ request, env }) => {
|
||||||
return handleRequest(request, env.DATABASE, env.userKEK, env.ACCESS_AUTH_DOMAIN, env.ACCESS_AUD)
|
return handleRequestPost(request, env.DATABASE, env.userKEK, env.ACCESS_AUTH_DOMAIN, env.ACCESS_AUD)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(
|
export async function handleRequestPost(
|
||||||
request: Request,
|
request: Request,
|
||||||
db: D1Database,
|
db: D1Database,
|
||||||
userKEK: string,
|
userKEK: string,
|
||||||
|
|
Ładowanie…
Reference in New Issue