Skip to content

Commit

Permalink
webAuth: Better compare web auth callback's realm with current realm.
Browse files Browse the repository at this point in the history
Part of #4146.

Rather than doing a straight string comparison, which will unfairly
reject on, e.g., a trailing slash in one URL but not the other,
parse them both with `react-native-url-polyfill`, made available at
the global URL in 413bf95.

Also stop using `url-parse` at all; `authFromCallbackUrl` is the
only place where we use it. We introduced
`react-native-url-polyfill` in c675cdd, for #4081, and we'll keep
using that for #4146. Not only is it specifically intended for RN
projects, but its README and implementation make it very clear that
it's an implementation of a standard; in particular, the WHATWG URL
Standard [1].

[1] https://url.spec.whatwg.org/
  • Loading branch information
chrisbobbe committed Sep 16, 2020
1 parent 20427e7 commit 26272d8
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 41 deletions.
31 changes: 0 additions & 31 deletions flow-typed/npm/url-parse_v1.3.x.js

This file was deleted.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@
"rn-fetch-blob": "^0.11.0",
"string.fromcodepoint": "^0.2.1",
"timezone": "^1.0.13",
"url-parse": "^1.4.0",
"url-regex": "^4.1.1",
"zulip-markdown-parser": "^1.0.6"
},
Expand Down
39 changes: 31 additions & 8 deletions src/start/webAuth.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* @flow strict-local */
import { NativeModules, Platform } from 'react-native';
import SafariView from 'react-native-safari-view';
import parseURL, { type Url } from 'url-parse';

import type { Auth } from '../types';
import openLink from '../utils/openLink';
import { tryParseUrl } from '../utils/url';
import { base64ToHex, hexToAscii, xorHexStrings } from '../utils/encoding';

/*
Expand Down Expand Up @@ -71,19 +71,42 @@ export const authFromCallbackUrl = (
otp: string,
realm: string,
): Auth | null => {
const url: Url = parseURL(callbackUrl, true);
const url = tryParseUrl(callbackUrl);

if (!url) {
return null;
}

const callbackRealmStr = url.searchParams.get('realm');
if (callbackRealmStr === null) {
return null;
}

let callbackRealm: URL;
try {
callbackRealm = new URL(callbackRealmStr);
} catch (e) {
return null;
}

// TODO: Check validity of `realm` much sooner
if (callbackRealm.origin !== new URL(realm).origin) {
return null;
}

const email = url.searchParams.get('email');
const otpEncryptedApiKey = url.searchParams.get('otp_encrypted_api_key');

// callback format expected: zulip://login?realm={}&email={}&otp_encrypted_api_key={}
if (
url.host === 'login'
&& url.query.realm === realm
&& otp
&& url.query.email
&& url.query.otp_encrypted_api_key
&& url.query.otp_encrypted_api_key.length === otp.length
&& email !== null
&& otpEncryptedApiKey !== null
&& otpEncryptedApiKey.length === otp.length
) {
const apiKey = extractApiKey(url.query.otp_encrypted_api_key, otp);
return { realm, email: url.query.email, apiKey };
const apiKey = extractApiKey(otpEncryptedApiKey, otp);
return { realm, email, apiKey };
}

return null;
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10029,7 +10029,7 @@ url-parse-lax@^3.0.0:
dependencies:
prepend-http "^2.0.0"

url-parse@^1.4.0, url-parse@^1.4.4:
url-parse@^1.4.4:
version "1.4.7"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
Expand Down

0 comments on commit 26272d8

Please sign in to comment.