Merge pull request #14 from cloudflare/sven/MOW-85-access-config

Configure Access automatically
pull/18/head
Sven Sauleau 2023-01-04 17:10:34 +00:00 zatwierdzone przez GitHub
commit 4480832aee
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
15 zmienionych plików z 140 dodań i 269 usunięć

Wyświetl plik

@ -11,6 +11,10 @@ jobs:
- uses: actions/checkout@v2
- uses: hashicorp/setup-terraform@v2
- name: Install package
run: |
sudo apt-get -y install jq
- name: Setup node.js
uses: actions/setup-node@v3
with:
@ -45,6 +49,12 @@ jobs:
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
- name: retrieve Zero Trust organization
run: |
auth_domain=$(curl https://api.cloudflare.com/client/v4/accounts/${{ secrets.CF_ACCOUNT_ID }}/access/organizations \
-H 'Authorization: Bearer ${{ secrets.CF_API_TOKEN }}' | jq -r '.result.auth_domain')
printf "auth_domain=$auth_domain" >> $GITHUB_ENV
- name: Init
run: terraform init
working-directory: ./tf
@ -59,6 +69,7 @@ jobs:
TF_VAR_cloudflare_zone_name: ${{ secrets.CF_ZONE_NAME }}
TF_VAR_gh_username: ${{ github.actor }}
TF_VAR_d1_id: ${{ env.d1_id }}
TF_VAR_access_auth_domain: ${{ env.auth_domain }}
- name: Publish
uses: cloudflare/wrangler-action@2.0.0

Wyświetl plik

@ -20,18 +20,6 @@ export async function configure(db: D1Database, data: InstanceConfig) {
}
}
export async function configureAccess(db: D1Database, domain: string, aud: string) {
const sql = `
INSERT INTO instance_config
VALUES ('accessAud', ?), ('accessDomain', ?);
`
const { success, error } = await db.prepare(sql).bind(aud, domain).run()
if (!success) {
throw new Error('SQL error: ' + error)
}
}
export async function generateVAPIDKeys(db: D1Database) {
const keyPair = (await crypto.subtle.generateKey({ name: 'ECDSA', namedCurve: 'P-256' }, true, [
'sign',

Wyświetl plik

@ -7,10 +7,7 @@ import { loadLocalMastodonAccount } from 'wildebeest/backend/src/mastodon/accoun
async function loadContextData(db: D1Database, clientId: string, email: string, ctx: any): Promise<boolean> {
const query = `
SELECT
actors.*,
(SELECT value FROM instance_config WHERE key='accessAud') as accessAud,
(SELECT value FROM instance_config WHERE key='accessDomain') as accessDomain
SELECT *
FROM actors
WHERE email=? AND type='Person'
`
@ -30,18 +27,12 @@ async function loadContextData(db: D1Database, clientId: string, email: string,
console.warn('person not found')
return false
}
if (!row.accessDomain || !row.accessAud) {
console.warn('access configuration not found')
return false
}
const person = actors.personFromRow(row)
ctx.data.connectedActor = person
ctx.data.identity = { email }
ctx.data.clientId = clientId
ctx.data.accessDomain = row.accessDomain
ctx.data.accessAud = row.accessAud
return true
}
@ -101,12 +92,12 @@ export async function main(context: EventContext<Env, any, any>) {
const validatate = access.generateValidator({
jwt,
domain: context.data.accessDomain,
aud: context.data.accessAud,
domain: context.env.ACCESS_AUTH_DOMAIN,
aud: context.env.ACCESS_AUD,
})
await validatate(context.request)
const identity = await access.getIdentity({ jwt, domain: context.data.accessDomain })
const identity = await access.getIdentity({ jwt, domain: context.env.ACCESS_AUTH_DOMAIN })
if (!identity) {
return errors.notAuthorized('failed to load identity')
}

Wyświetl plik

@ -9,10 +9,6 @@ export type ContextData = {
// ActivityPub Person object of the logged in user
connectedActor: Person
// Configure for Cloudflare Access
accessDomain: string
accessAud: string
// Object returned by Cloudflare Access' provider
identity: Identity

Wyświetl plik

@ -2,6 +2,12 @@ export interface Env {
DATABASE: D1Database
KV_CACHE: KVNamespace
userKEK: string
CF_ACCOUNT_ID: string
CF_API_TOKEN: string
// Configuration for Cloudflare Access
DOMAIN: string
ACCESS_AUD: string
ACCESS_AUTH_DOMAIN: string
}

Wyświetl plik

@ -13,7 +13,6 @@ import {
} from '../utils'
import { TEST_JWT, ACCESS_CERTS } from '../test-data'
import { strict as assert } from 'node:assert/strict'
import { configureAccess } from 'wildebeest/backend/src/config/index'
const userKEK = 'test_kek3'
const accessDomain = 'access.com'
@ -41,20 +40,18 @@ describe('Mastodon APIs', () => {
test('authorize missing params', async () => {
const db = await makeDB()
await configureAccess(db, accessDomain, accessAud)
let req = new Request('https://example.com/oauth/authorize')
let res = await oauth_authorize.handleRequest(req, db, userKEK)
let res = await oauth_authorize.handleRequest(req, db, userKEK, accessDomain, accessAud)
assert.equal(res.status, 400)
req = new Request('https://example.com/oauth/authorize?scope=foobar')
res = await oauth_authorize.handleRequest(req, db, userKEK)
res = await oauth_authorize.handleRequest(req, db, userKEK, accessDomain, accessAud)
assert.equal(res.status, 400)
})
test('authorize unsupported response_type', async () => {
const db = await makeDB()
await configureAccess(db, accessDomain, accessAud)
const params = new URLSearchParams({
redirect_uri: 'https://example.com',
@ -63,14 +60,13 @@ describe('Mastodon APIs', () => {
})
const req = new Request('https://example.com/oauth/authorize?' + params)
const res = await oauth_authorize.handleRequest(req, db, userKEK)
const res = await oauth_authorize.handleRequest(req, db, userKEK, accessDomain, accessAud)
assert.equal(res.status, 400)
})
test("authorize redirect_uri doesn't match client redirect_uris", async () => {
const db = await makeDB()
const client = await createTestClient(db, 'https://redirect.com')
await configureAccess(db, accessDomain, accessAud)
const params = new URLSearchParams({
redirect_uri: 'https://example.com/a',
@ -83,14 +79,13 @@ describe('Mastodon APIs', () => {
const req = new Request('https://example.com/oauth/authorize?' + params, {
headers,
})
const res = await oauth_authorize.handleRequest(req, db, userKEK)
const res = await oauth_authorize.handleRequest(req, db, userKEK, accessDomain, accessAud)
assert.equal(res.status, 403)
})
test('authorize redirects with code on success and show first login', async () => {
const db = await makeDB()
const client = await createTestClient(db)
await configureAccess(db, accessDomain, accessAud)
const params = new URLSearchParams({
redirect_uri: client.redirect_uris,
@ -103,7 +98,7 @@ describe('Mastodon APIs', () => {
const req = new Request('https://example.com/oauth/authorize?' + params, {
headers,
})
const res = await oauth_authorize.handleRequest(req, db, userKEK)
const res = await oauth_authorize.handleRequest(req, db, userKEK, accessDomain, accessAud)
assert.equal(res.status, 302)
const location = new URL(res.headers.get('location') || '')
@ -212,7 +207,7 @@ describe('Mastodon APIs', () => {
const req = new Request('https://example.com/oauth/authorize', {
method: 'OPTIONS',
})
const res = await oauth_authorize.handleRequest(req, db, userKEK)
const res = await oauth_authorize.handleRequest(req, db, userKEK, accessDomain, accessAud)
assert.equal(res.status, 200)
assertCORS(res)
})

Wyświetl plik

@ -2,7 +2,6 @@ import { isUrlValid, makeDB, assertCORS } from './utils'
import { createPerson } from 'wildebeest/backend/src/activitypub/actors'
import { TEST_JWT, ACCESS_CERTS } from './test-data'
import { strict as assert } from 'node:assert/strict'
import { configureAccess } from 'wildebeest/backend/src/config/index'
import * as middleware_main from 'wildebeest/backend/src/middleware/main'
const userKEK = 'test_kek12'
@ -99,14 +98,13 @@ describe('middleware', () => {
const db = await makeDB()
await createPerson(domain, db, userKEK, 'sven@cloudflare.com')
await configureAccess(db, accessDomain, accessAud)
const headers = { authorization: 'Bearer APPID.' + TEST_JWT }
const request = new Request('https://example.com', { headers })
const ctx: any = {
next: () => new Response(),
data: {},
env: { DATABASE: db },
env: { DATABASE: db, ACCESS_AUD: accessAud, ACCESS_AUTH_DOMAIN: accessDomain },
request,
}
@ -114,7 +112,7 @@ describe('middleware', () => {
assert.equal(res.status, 200)
assert(!ctx.data.connectedUser)
assert(isUrlValid(ctx.data.connectedActor.id))
assert.equal(ctx.data.accessDomain, accessDomain)
assert.equal(ctx.data.accessAud, accessAud)
assert.equal(ctx.env.ACCESS_AUTH_DOMAIN, accessDomain)
assert.equal(ctx.env.ACCESS_AUD, accessAud)
})
})

Wyświetl plik

@ -37,7 +37,7 @@ describe('Wildebeest', () => {
}
const req = new Request('https://example.com', { method: 'POST', body, headers })
const res = await startInstance.handlePostRequest(req, db)
const res = await startInstance.handlePostRequest(req, db, accessDomain, accessAud)
assert.equal(res.status, 201)
const { value } = await db.prepare("SELECT value FROM instance_config WHERE key = 'vapid_jwk'").first()

Wyświetl plik

@ -2,14 +2,12 @@ import { $, component$, useStore, useClientEffect$, useSignal } from '@builder.i
import { MastodonLogo } from '~/components/MastodonLogo'
import { useDomain } from '~/utils/useDomain'
import Step1 from './step-1'
import Step2 from './step-2'
import { type InstanceConfig, testAccess, testInstance } from './utils'
export default component$(() => {
const domain = useDomain()
const loading = useSignal(true)
const accessConfigured = useSignal(false)
const instanceConfigured = useSignal(false)
const instanceConfig = useStore<InstanceConfig>({
@ -21,20 +19,15 @@ export default component$(() => {
})
useClientEffect$(async () => {
if (await testAccess()) {
accessConfigured.value = true
if (await testInstance()) {
instanceConfigured.value = true
}
}
if (await testInstance()) {
instanceConfigured.value = true
}
loading.value = false
})
const getStepToShow = () => {
if (loading.value) return 'loading'
if (!accessConfigured.value) return 'step-1'
if (!instanceConfigured.value) return 'step-2'
if (!instanceConfigured.value) return 'step-1'
return 'all-good'
}
@ -55,9 +48,8 @@ export default component$(() => {
</h1>
{stepToShow.startsWith('step-') && <p>Welcome to Wildebeest... Your instance hasn't been configured yet.</p>}
{stepToShow === 'loading' && <p>Loading...</p>}
{stepToShow === 'step-1' && <Step1 instanceConfig={instanceConfig} setLoading={setLoading} />}
{stepToShow === 'step-2' && (
<Step2 instanceConfig={instanceConfig} setLoading={setLoading} setInstanceConfigured={setInstanceConfigured} />
{stepToShow === 'step-1' && (
<Step1 instanceConfig={instanceConfig} setLoading={setLoading} setInstanceConfigured={setInstanceConfigured} />
)}
{stepToShow === 'all-good' && <p>All good, your instance is ready.</p>}
</div>

Wyświetl plik

@ -1,125 +1,80 @@
import { component$, QRL } from '@builder.io/qwik'
import { generateLoginURL } from 'wildebeest/backend/src/access'
import { configure, type InstanceConfig } from './utils'
import { configure, type InstanceConfig, testInstance } from './utils'
interface Props {
instanceConfig: InstanceConfig
setLoading: QRL<(loading: boolean) => void>
setInstanceConfigured: QRL<(configured: boolean) => void>
}
export default component$<Props>(({ instanceConfig, setLoading }) => {
export default component$<Props>(({ instanceConfig, setLoading, setInstanceConfigured }) => {
return (
<>
<h2>Step 1. Configure Cloudflare Pages for user management</h2>
<p>
Wildebeest uses{' '}
<a href="https://www.cloudflare.com/products/zero-trust/access/" target="_new">
{' '}
Cloudflare Access
</a>{' '}
for user management. You can configure Cloudflare Access to allow users to access Wildebeest.
</p>
<p>
Go to{' '}
<a href="https://one.dash.cloudflare.com/" target="_new">
Cloudflare Zero Trust dashboard
</a>
, select the account and go in Access {'>'} Applications.
</p>
<ViewableImage
src="https://imagedelivery.net/NkfPDviynOyTAOI79ar_GQ/f8ee9ab3-31d5-4204-94bd-25d00a971600/public"
ariaLabel="Cloudflare Zero Trust Dashboard Applications Screenshot"
/>
<p>
An application called <code>wildebeest-username</code> should already be present.
</p>
<p>Click on edit and in Overview copy the field called Application Audience (AUD) Tag.</p>
<ViewableImage
src="https://imagedelivery.net/NkfPDviynOyTAOI79ar_GQ/54b11336-9c64-419b-5a5f-e80d5b833700/public"
ariaLabel="Cloudflare Zero Trust Dashboard Application Overview Screenshot"
/>
<p>Paste it bellow.</p>
<h2>Configure your instance</h2>
<div class="flex flex-column mb-6 w-full max-w-md">
<label class="mb-2 text-semi text-sm" for="start-instance-access-aud">
Access AUD
<label class="mb-2 max-w-max text-semi text-sm" for="start-instance-title">
Title
</label>
<div class="flex justify-center items-center flex-wrap gap-1">
<input
id="start-instance-access-aud"
name="access-aud"
type="access-aud"
id="start-instance-title"
name="title"
class="bg-black text-white p-3 rounded outline-none border border-black hover:border-indigo-400 focus:border-indigo-400 invalid:border-red-400 flex-1 w-full"
value={instanceConfig.accessAud}
onInput$={(ev) => (instanceConfig.accessAud = (ev.target as HTMLInputElement).value)}
value={instanceConfig.title}
onInput$={(ev) => (instanceConfig.title = (ev.target as HTMLInputElement).value)}
/>
</div>
</div>
<p>Then go to Settings {'>'} General.</p>
<ViewableImage
src="https://imagedelivery.net/NkfPDviynOyTAOI79ar_GQ/51988fa3-44cc-4ec2-fb9a-2096d2f1c700/public"
ariaLabel="Cloudflare Zero Trust Dashboard General Settings Screenshot"
/>
<p>Copy the Team domain and paste it bellow.</p>
<div class="flex flex-column w-full max-w-md">
<div class="flex flex-column mb-6">
<label class="mb-2 text-semi text-sm" for="start-instance-access-domain">
Access domain
</label>
<div class="flex justify-center items-center flex-wrap gap-1">
<input
id="start-instance-access-domain"
name="access-domain"
type="access-domain"
class="bg-black text-white p-3 rounded outline-none border border-black hover:border-indigo-400 focus:border-indigo-400 invalid:border-red-400 flex-1 w-full"
value={instanceConfig.accessDomain}
onInput$={(ev) => (instanceConfig.accessDomain = (ev.target as HTMLInputElement).value)}
/>
<span>.cloudflareaccess.com</span>
</div>
<div class="flex flex-column mb-6 w-full max-w-md">
<label class="mb-2 max-w-max text-semi text-sm" for="start-instance-email">
Administrator email
</label>
<div class="flex justify-center items-center flex-wrap gap-1">
<input
id="start-instance-email"
name="email"
type="email"
class="bg-black text-white p-3 rounded outline-none border border-black hover:border-indigo-400 focus:border-indigo-400 invalid:border-red-400 flex-1 w-full"
value={instanceConfig.email}
onInput$={(ev) => (instanceConfig.email = (ev.target as HTMLInputElement).value)}
/>
</div>
<button
class="mb-9 bg-indigo-600 hover:bg-indigo-500 p-3 text-white text-uppercase border-indigo-600 text-lg text-semi outline-none border rounded hover:border-indigo-500 focus:border-indigo-500 max-w-md"
preventdefault:click
onClick$={async () => {
setLoading(true)
await configure({
accessDomain: instanceConfig.accessDomain,
accessAud: instanceConfig.accessAud,
})
setLoading(false)
const url = generateLoginURL({
redirectURL: location.href,
domain: instanceConfig.accessDomain + '.cloudflareaccess.com',
aud: instanceConfig.accessAud,
})
window.location.href = url
}}
>
Configure and test
</button>
</div>
<div class="flex flex-column mb-6 w-full max-w-md">
<label class="mb-2 max-w-max text-semi text-sm" for="start-instance-description">
Description
</label>
<div class="flex justify-center items-center flex-wrap gap-1">
<input
id="start-instance-description"
name="description"
class="bg-black text-white p-3 rounded outline-none border border-black hover:border-indigo-400 focus:border-indigo-400 invalid:border-red-400 flex-1 w-full"
value={instanceConfig.description}
onInput$={(ev) => (instanceConfig.description = (ev.target as HTMLInputElement).value)}
/>
</div>
</div>
<button
type="submit"
class="mb-9 bg-indigo-600 hover:bg-indigo-500 p-3 text-white text-uppercase border-indigo-600 text-lg text-semi outline-none border rounded hover:border-indigo-500 focus:border-indigo-500"
preventdefault:click
onClick$={async () => {
setLoading(true)
await configure(instanceConfig)
if (await testInstance()) {
setInstanceConfigured(true)
}
setLoading(false)
}}
>
Configure and start your instance
</button>
</>
)
})
export const ViewableImage = component$(({ src, ariaLabel }: { src: string; ariaLabel: string }) => {
return (
<a href={src} target="_blank">
<img src={src} class="w-full" aria-label={ariaLabel} />
</a>
)
})

Wyświetl plik

@ -1,80 +0,0 @@
import { component$, QRL } from '@builder.io/qwik'
import { configure, type InstanceConfig, testInstance } from './utils'
interface Props {
instanceConfig: InstanceConfig
setLoading: QRL<(loading: boolean) => void>
setInstanceConfigured: QRL<(configured: boolean) => void>
}
export default component$<Props>(({ instanceConfig, setLoading, setInstanceConfigured }) => {
return (
<>
<h2>Step 2. Configure instance</h2>
<div class="flex flex-column mb-6 w-full max-w-md">
<label class="mb-2 max-w-max text-semi text-sm" for="start-instance-title">
Title
</label>
<div class="flex justify-center items-center flex-wrap gap-1">
<input
id="start-instance-title"
name="title"
class="bg-black text-white p-3 rounded outline-none border border-black hover:border-indigo-400 focus:border-indigo-400 invalid:border-red-400 flex-1 w-full"
value={instanceConfig.title}
onInput$={(ev) => (instanceConfig.title = (ev.target as HTMLInputElement).value)}
/>
</div>
</div>
<div class="flex flex-column mb-6 w-full max-w-md">
<label class="mb-2 max-w-max text-semi text-sm" for="start-instance-email">
Administrator email
</label>
<div class="flex justify-center items-center flex-wrap gap-1">
<input
id="start-instance-email"
name="email"
type="email"
class="bg-black text-white p-3 rounded outline-none border border-black hover:border-indigo-400 focus:border-indigo-400 invalid:border-red-400 flex-1 w-full"
value={instanceConfig.email}
onInput$={(ev) => (instanceConfig.email = (ev.target as HTMLInputElement).value)}
/>
</div>
</div>
<div class="flex flex-column mb-6 w-full max-w-md">
<label class="mb-2 max-w-max text-semi text-sm" for="start-instance-description">
Description
</label>
<div class="flex justify-center items-center flex-wrap gap-1">
<input
id="start-instance-description"
name="description"
class="bg-black text-white p-3 rounded outline-none border border-black hover:border-indigo-400 focus:border-indigo-400 invalid:border-red-400 flex-1 w-full"
value={instanceConfig.description}
onInput$={(ev) => (instanceConfig.description = (ev.target as HTMLInputElement).value)}
/>
</div>
</div>
<button
type="submit"
class="mb-9 bg-indigo-600 hover:bg-indigo-500 p-3 text-white text-uppercase border-indigo-600 text-lg text-semi outline-none border rounded hover:border-indigo-500 focus:border-indigo-500"
preventdefault:click
onClick$={async () => {
setLoading(true)
await configure(instanceConfig)
if (await testInstance()) {
setInstanceConfigured(true)
}
setLoading(false)
}}
>
Configure and start your instance
</button>
</>
)
})

Wyświetl plik

@ -11,10 +11,16 @@ import { getPersonByEmail } from 'wildebeest/backend/src/activitypub/actors'
const extractJWTFromRequest = (request: Request) => request.headers.get('Cf-Access-Jwt-Assertion') || ''
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ data, request, env }) => {
return handleRequest(request, env.DATABASE, env.userKEK)
return handleRequest(request, env.DATABASE, env.userKEK, env.ACCESS_AUTH_DOMAIN, env.ACCESS_AUD)
}
export async function handleRequest(request: Request, db: D1Database, userKEK: string): Promise<Response> {
export async function handleRequest(
request: Request,
db: D1Database,
userKEK: string,
accessDomain: string,
accessAud: string
): Promise<Response> {
if (request.method === 'OPTIONS') {
const headers = {
'Access-Control-Allow-Origin': '*',
@ -54,18 +60,11 @@ export async function handleRequest(request: Request, db: D1Database, userKEK: s
const scope = url.searchParams.get('scope') || ''
const query = `
SELECT
(SELECT value FROM instance_config WHERE key='accessAud') as accessAud,
(SELECT value FROM instance_config WHERE key='accessDomain') as accessDomain
`
const config: any = await db.prepare(query).first()
const jwt = extractJWTFromRequest(request)
const validate = access.generateValidator({ jwt, domain: config.accessDomain, aud: config.accessAud })
const validate = access.generateValidator({ jwt, domain: accessDomain, aud: accessAud })
await validate(request)
const identity = await access.getIdentity({ jwt, domain: config.accessDomain })
const identity = await access.getIdentity({ jwt, domain: accessDomain })
if (!identity) {
return new Response('', { status: 401 })
}

Wyświetl plik

@ -34,9 +34,9 @@ export async function handleGetRequest(db: D1Database, request: Request): Promis
return errors.notAuthorized('missing authorization')
}
const domain = data.accessDomain
const domain = env.ACCESS_AUTH_DOMAIN
const validator = access.generateValidator({ jwt, domain, aud: data.accessAud })
const validator = access.generateValidator({ jwt, domain, aud: env.ACCESS_AUD })
const { payload } = await validator(request)
const identity = await access.getIdentity({ jwt, domain })

Wyświetl plik

@ -7,28 +7,44 @@ import type { ContextData } from 'wildebeest/backend/src/types/context'
import type { InstanceConfig } from 'wildebeest/backend/src/config'
import * as config from 'wildebeest/backend/src/config'
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ request, env, data }) => {
return handlePostRequest(request, env.DATABASE)
export const onRequestPost: PagesFunction<Env, any> = async ({ request, env }) => {
return handlePostRequest(request, env.DATABASE, env.ACCESS_AUTH_DOMAIN, env.ACCESS_AUD)
}
export async function handlePostRequest(request: Request, db: D1Database): Promise<Response> {
const data = await request.json<InstanceConfig>()
if (!data.accessAud || !data.accessDomain) {
return new Response('', { status: 400 })
export const onRequestGet: PagesFunction<Env, any> = async ({ request, env, next }) => {
const cookie = parse(request.headers.get('Cookie') || '')
const jwt = cookie['CF_Authorization']
if (!jwt) {
const { hostname } = new URL(request.url)
const url = access.generateLoginURL({
redirectURL: new URL('/start-instance', 'https://' + env.DOMAIN),
domain: env.ACCESS_AUTH_DOMAIN,
aud: env.ACCESS_AUD,
})
return Response.redirect(url)
}
return next()
}
export async function handlePostRequest(
request: Request,
db: D1Database,
accessDomain: string,
accessAud: string
): Promise<Response> {
const data = await request.json<InstanceConfig>()
const cookie = parse(request.headers.get('Cookie') || '')
const jwt = cookie['CF_Authorization']
if (!jwt) {
// Allow to configure Access without any authentification
await config.configureAccess(db, data.accessDomain + '.cloudflareaccess.com', data.accessAud)
return new Response()
return new Response('', { status: 401 })
}
const validator = access.generateValidator({ jwt, domain: data.accessDomain, aud: data.accessAud })
const validator = access.generateValidator({ jwt, domain: accessDomain, aud: accessAud })
const { payload } = await validator(request)
const identity = await access.getIdentity({ jwt, domain: data.accessDomain })
const identity = await access.getIdentity({ jwt, domain: accessDomain })
if (!identity) {
return errors.notAuthorized('failed to load identity')
}

Wyświetl plik

@ -18,6 +18,10 @@ variable "d1_id" {
type = string
}
variable "access_auth_domain" {
type = string
}
terraform {
required_providers {
cloudflare = {
@ -65,6 +69,10 @@ resource "cloudflare_pages_project" "wildebeest_pages_project" {
CF_API_TOKEN = ""
USER_KEY = random_password.user_key.result
DOMAIN = var.cloudflare_zone_name
ACCESS_AUD = cloudflare_access_application.wildebeest_access.aud
ACCESS_AUTH_DOMAIN = var.access_auth_domain
}
kv_namespaces = {
KV_CACHE = cloudflare_workers_kv_namespace.wildebeest_cache.id
@ -111,7 +119,3 @@ resource "cloudflare_access_policy" "policy" {
email = ["test@example.com"]
}
}
/* output "access_aud" { */
/* value = cloudflare_access_application.wildebeest_access.aud */
/* } */