Callback-URL aus APP_URL ableiten
Auth.js baut die redirect_uri nicht aus dem Host-Header, sondern aus AUTH_URL. Ohne die Variable bleibt sie fest auf http://localhost:3000 — hinter dem Cloudflare Tunnel wäre die Anmeldung damit kaputt gewesen, und zwar mit einer Fehlermeldung von Discord, die nicht auf die Ursache zeigt. APP_URL ist ohnehin die kanonische öffentliche Adresse und wird jetzt durchgereicht. Nachweis mit dem gebauten Standalone-Server: mit gesetztem APP_URL kommt https://afis.example.de/api/auth/callback/discord heraus, ohne fällt sie auf localhost zurück. Ein E2E-Test hält Scope identify, state, PKCE mit S256 und den Pfad der Callback-URL fest. Nebenbefund, eigenständig behoben: loadEnvFromRepoRoot hat gesetzte Umgebungsvariablen mit den Werten der Entwicklungs-.env überschrieben. process.loadEnvFile tut das von sich aus. Eine .env ist ein Rückfall für die lokale Entwicklung, kein Vorrang vor dem, was der Aufrufer ausdrücklich mitgibt — sonst überschreibt sie etwa die APP_URL eines Testlaufs und die Fehlersuche führt weit weg von der Ursache.
This commit is contained in:
@@ -46,3 +46,34 @@ test('Fehlerseite benennt den Grund der Ablehnung', async ({ page }) => {
|
||||
'Du bist nicht auf dem AfiS-Discord',
|
||||
)
|
||||
})
|
||||
|
||||
test('OAuth-Start nutzt Scope identify, state und PKCE', async ({ request, baseURL }) => {
|
||||
// Sichert die Anforderungen aus docs/03-auth-und-rechte.md ab.
|
||||
//
|
||||
// Der Pfad der redirect_uri wird hier festgehalten, nicht ihr Ursprung: den
|
||||
// baut Auth.js aus AUTH_URL, das in web/auth.ts aus APP_URL abgeleitet wird.
|
||||
// Welchen Ursprung der Testserver dabei sieht, haengt daran, wie Playwright
|
||||
// die Umgebung durchreicht, und sagt ueber die Anwendung nichts aus. Wichtig
|
||||
// ist: die URI muss zeichengenau im Discord Developer Portal hinterlegt sein,
|
||||
// sonst lehnt Discord den Start ab.
|
||||
const csrfResponse = await request.get('/api/auth/csrf')
|
||||
const { csrfToken } = await csrfResponse.json()
|
||||
|
||||
const response = await request.post('/api/auth/signin/discord', {
|
||||
form: { csrfToken, callbackUrl: `${baseURL}/uebersicht` },
|
||||
maxRedirects: 0,
|
||||
})
|
||||
|
||||
const location = response.headers()['location'] ?? ''
|
||||
expect(location).toContain('discord.com')
|
||||
|
||||
const params = new URL(location).searchParams
|
||||
expect(params.get('scope')).toBe('identify')
|
||||
expect(params.get('state')).toBeTruthy()
|
||||
expect(params.get('code_challenge')).toBeTruthy()
|
||||
expect(params.get('code_challenge_method')).toBe('S256')
|
||||
|
||||
const redirectUri = new URL(params.get('redirect_uri') ?? '')
|
||||
expect(redirectUri.pathname).toBe('/api/auth/callback/discord')
|
||||
expect(redirectUri.protocol).toMatch(/^https?:$/)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user