mirror of
https://github.com/bulwarkmail/native.git
synced 2026-10-31 08:06:36 +00:00
fix: keep a sign-in code from following a redirect to another host
This commit is contained in:
@@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|||||||
import * as WebBrowser from 'expo-web-browser';
|
import * as WebBrowser from 'expo-web-browser';
|
||||||
|
|
||||||
import { setManualFetchForTests } from '../client-cert';
|
import { setManualFetchForTests } from '../client-cert';
|
||||||
import { HandoffError, TransientRefreshError, refreshOAuthAccessToken, resetRefreshRotations } from '../oauth';
|
import { HandoffError, PairingError, TransientRefreshError, redeemPairingCode, refreshOAuthAccessToken, resetRefreshRotations } from '../oauth';
|
||||||
import { discoverOAuthMetadata, loginWithPkce, revokeRefreshToken, type OAuthMetadata } from '../oauth-native';
|
import { discoverOAuthMetadata, loginWithPkce, revokeRefreshToken, type OAuthMetadata } from '../oauth-native';
|
||||||
|
|
||||||
// The refresh token, the code + verifier and the metadata that decides where
|
// The refresh token, the code + verifier and the metadata that decides where
|
||||||
@@ -149,3 +149,13 @@ describe('metadata discovery', () => {
|
|||||||
expect((await discoverOAuthMetadata(SERVER))?.token_endpoint).toBe(`${IDP}/token`);
|
expect((await discoverOAuthMetadata(SERVER))?.token_endpoint).toBe(`${IDP}/token`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('pairing', () => {
|
||||||
|
it('does not take a sign-in code along a redirect to another host', async () => {
|
||||||
|
routes[`${SERVER}/api/auth/pair/redeem`] = () => redirect(`${EVIL}/api/auth/pair/redeem`);
|
||||||
|
|
||||||
|
await expect(redeemPairingCode(SERVER, 'ABCD-EFGH')).rejects.toBeInstanceOf(PairingError);
|
||||||
|
|
||||||
|
expect(evilHits()).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
+3
-1
@@ -459,7 +459,9 @@ export async function redeemPairingCode(webmailUrl: string, code: string): Promi
|
|||||||
const exchange = (async () => {
|
const exchange = (async () => {
|
||||||
let response: Response;
|
let response: Response;
|
||||||
try {
|
try {
|
||||||
response = await secureFetch(`${base}/api/auth/pair/redeem`, {
|
// The code is a one-time credential: never let a redirect carry it
|
||||||
|
// to another host.
|
||||||
|
response = await fetchWithoutForeignRedirect(`${base}/api/auth/pair/redeem`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
||||||
body: JSON.stringify({ pairing_code: code }),
|
body: JSON.stringify({ pairing_code: code }),
|
||||||
|
|||||||
Reference in New Issue
Block a user