Skip to content

Commit

Permalink
Remove ua-parser-js. Change isMobileSafari18 to isSafari18 (#1562)
Browse files Browse the repository at this point in the history
OKTA-851978 fix: remove ua-parser-js dep
  • Loading branch information
denysoblohin-okta authored Jan 14, 2025
1 parent 2d4639f commit 45e1ed3
Show file tree
Hide file tree
Showing 17 changed files with 62 additions and 60 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

# 7.10.1

### Other

- [#1562](https://github.com/okta/okta-auth-js/pull/1562) chore: Remove `ua-parser-js`. Change `isMobileSafari18` to `isSafari18`

# 7.10.0

### Bug Fix
Expand Down
6 changes: 3 additions & 3 deletions lib/authn/util/poll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import AuthSdkError from '../../errors/AuthSdkError';
import AuthPollStopError from '../../errors/AuthPollStopError';
import { AuthnTransactionState } from '../types';
import { getStateToken } from './stateToken';
import { isMobileSafari18 } from '../../features';
import { isSafari18 } from '../../features';

interface PollOptions {
delay?: number;
Expand Down Expand Up @@ -86,7 +86,7 @@ export function getPollFn(sdk, res: AuthnTransactionState, ref) {

const delayNextPoll = (ms) => {
// no need for extra logic in non-iOS environments, just continue polling
if (!isMobileSafari18()) {
if (!isSafari18()) {
return delayFn(ms);
}

Expand Down Expand Up @@ -136,7 +136,7 @@ export function getPollFn(sdk, res: AuthnTransactionState, ref) {
}

// don't trigger polling request if page is hidden wait until window is visible again
if (isMobileSafari18() && document.hidden) {
if (isSafari18() && document.hidden) {
let handler;
return new Promise<void>((resolve) => {
handler = () => {
Expand Down
2 changes: 1 addition & 1 deletion lib/base/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export interface FeaturesAPI {
isIE11OrLess(): boolean;
isDPoPSupported(): boolean;
isIOS(): boolean;
isMobileSafari18(): boolean;
isSafari18(): boolean;
}


Expand Down
19 changes: 13 additions & 6 deletions lib/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
/* eslint-disable node/no-unsupported-features/node-builtins */
/* global document, window, TextEncoder, navigator */

import { UAParser } from 'ua-parser-js';
import { webcrypto } from './crypto';

const isWindowsPhone = /windows phone|iemobile|wpdesktop/i;
Expand Down Expand Up @@ -97,11 +96,19 @@ export function isIOS () {
(/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream);
}

export function isMobileSafari18 () {
if (isBrowser()) {
const { browser, os } = new UAParser().getResult();
return os.name?.toLowerCase() === 'ios' && !!browser.name?.toLowerCase()?.includes('safari')
&& browser.major === '18';
const isIOSRegex = /iPad|iPhone|iPod/;
const v18Regex = /Version\/18(\.| |$)/;
const notSafariRegex = /EdgiOS|CriOS|Chrome/;

/* eslint complexity:[0,8] */
export function isSafari18 () {
if (isBrowser() && typeof navigator !== 'undefined' && typeof navigator.userAgent !== 'undefined') {
const isIOS = isIOSRegex.test(navigator.userAgent);
// Mobile Safari in desktop mode emulates Macintosh in user agent
const isDesktop = navigator.userAgent.includes('Macintosh');
const isSafari18 = navigator.userAgent.includes('Safari/') && v18Regex.test(navigator.userAgent);
const isOtherBrowser = notSafariRegex.test(navigator.userAgent);
return isSafari18 && !isOtherBrowser && (isIOS || isDesktop);
}
return false;
}
6 changes: 3 additions & 3 deletions lib/http/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ import {
HttpResponse
} from './types';
import { AuthApiError, OAuthError, APIError, WWWAuthError } from '../errors';
import { isMobileSafari18 } from '../features';
import { isSafari18 } from '../features';


// For iOS track last date when document became visible
let dateDocumentBecameVisible = 0;
let trackDateDocumentBecameVisible: () => void;
if (isMobileSafari18()) {
if (isSafari18()) {
dateDocumentBecameVisible = Date.now();
trackDateDocumentBecameVisible = () => {
if (!document.hidden) {
Expand Down Expand Up @@ -165,7 +165,7 @@ export function httpRequest(sdk: OktaAuthHttpInterface, options: RequestOptions)

var err, res, promise;

if (pollingIntent && isMobileSafari18()) {
if (pollingIntent && isSafari18()) {
let waitForVisibleAndAwakenDocument: () => Promise<void>;
let waitForAwakenDocument: () => Promise<void>;
let recursiveFetch: () => Promise<HttpResponse>;
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"private": true,
"name": "@okta/okta-auth-js",
"description": "The Okta Auth SDK",
"version": "7.10.0",
"version": "7.10.1",
"homepage": "https://github.com/okta/okta-auth-js",
"license": "Apache-2.0",
"main": "build/cjs/exports/default.js",
Expand Down Expand Up @@ -162,7 +162,6 @@
"node-cache": "^5.1.2",
"p-cancelable": "^2.0.0",
"tiny-emitter": "1.1.0",
"ua-parser-js": "^2.0.0",
"webcrypto-shim": "^0.1.5",
"xhr2": "0.1.3"
},
Expand Down
2 changes: 1 addition & 1 deletion test/spec/TokenManager/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const mocked = {
isIE11OrLess: () => false,
isLocalhost: () => false,
isTokenVerifySupported: () => true,
isMobileSafari18: () => false
isSafari18: () => false
}
};
jest.mock('../../../lib/features', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/spec/TokenManager/expireEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ jest.mock('../../../lib/features', () => {
return {
isLocalhost: () => true, // to allow configuring expireEarlySeconds
isIE11OrLess: () => false,
isMobileSafari18: () => false
isSafari18: () => false
};
});

Expand Down
4 changes: 2 additions & 2 deletions test/spec/authn/mfa-challenge.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jest.mock('lib/features', () => {
const actual = jest.requireActual('../../../lib/features');
return {
...actual,
isMobileSafari18: () => false
isSafari18: () => false
};
});
import OktaAuth from '@okta/okta-auth-js';
Expand Down Expand Up @@ -1581,7 +1581,7 @@ describe('MFA_CHALLENGE', function () {
});

// mocks iOS environment
jest.spyOn(mocked.features, 'isMobileSafari18').mockReturnValue(true);
jest.spyOn(mocked.features, 'isSafari18').mockReturnValue(true);

const { response: mfaPush } = await util.generateXHRPair({
uri: 'https://auth-js-test.okta.com'
Expand Down
32 changes: 23 additions & 9 deletions test/spec/features/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe('features (browser)', function() {
});
});

describe('isIOS, isMobileSafari18', () => {
describe('isIOS, isSafari18', () => {
const iOSAgents = [
'Mozilla/5.0 (iPhone; CPU iPhone OS 14_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/92.0.4515.90 Mobile/15E148 Safari/604.1',
'Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.1 Mobile/15E148 Safari/604.1',
Expand All @@ -79,33 +79,47 @@ describe('features (browser)', function() {
'Mozilla/5.0 (iPhone; CPU iPhone OS 18_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1',
'Mozilla/5.0 (iPad; CPU OS 18_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1',
];
const desktopSafari18Agents = [
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15',
];
const notSafariAgents = [
'Mozilla/5.0 (Linux; Android 15) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.260 Mobile Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
'Mozilla/5.0 (iPhone; CPU iPhone OS 14_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/92.0.4515.90 Mobile/15E148 Safari/604.1',
'Mozilla/5.0 (iPhone; CPU iPhone OS 18_2_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) EdgiOS/132.0.2957.32 Version/18.0 Mobile/15E148 Safari/604.1',
];

for (let userAgent of iOSAgents) {
it('can succeed for ' + userAgent, () => {
it('isIOS() should be true for ' + userAgent, () => {
jest.spyOn(global.navigator, 'userAgent', 'get').mockReturnValue(userAgent);
expect(OktaAuth.features.isIOS()).toBe(true);
expect(OktaAuth.features.isMobileSafari18()).toBe(false);
});
}
for (let userAgent of mobileSafari18Agents) {
for (let userAgent of [...mobileSafari18Agents, ...desktopSafari18Agents]) {
// eslint-disable-next-line jasmine/no-spec-dupes
it('can succeed for ' + userAgent, () => {
it('isSafari18() should be true for ' + userAgent, () => {
jest.spyOn(global.navigator, 'userAgent', 'get').mockReturnValue(userAgent);
expect(OktaAuth.features.isIOS()).toBe(true);
expect(OktaAuth.features.isMobileSafari18()).toBe(true);
expect(OktaAuth.features.isSafari18()).toBe(true);
});
}
for (let userAgent of notSafariAgents) {
// eslint-disable-next-line jasmine/no-spec-dupes
it('isSafari18() should be false for ' + userAgent, () => {
jest.spyOn(global.navigator, 'userAgent', 'get').mockReturnValue(userAgent);
expect(OktaAuth.features.isSafari18()).toBe(false);
});
}

it('returns false if navigator is unavailable', () => {
jest.spyOn(global, 'navigator', 'get').mockReturnValue(undefined as never);
expect(OktaAuth.features.isIOS()).toBe(false);
expect(OktaAuth.features.isMobileSafari18()).toBe(false);
expect(OktaAuth.features.isSafari18()).toBe(false);
});

it('returns false if userAgent is unavailable', () => {
jest.spyOn(global.navigator, 'userAgent', 'get').mockReturnValue(undefined as never);
expect(OktaAuth.features.isIOS()).toBe(false);
expect(OktaAuth.features.isMobileSafari18()).toBe(false);
expect(OktaAuth.features.isSafari18()).toBe(false);
});
});
});
6 changes: 3 additions & 3 deletions test/spec/http/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jest.mock('../../../lib/features', () => {
isIE11OrLess: () => false,
isLocalhost: () => false,
isHTTPS: () => false,
isMobileSafari18: () => false
isSafari18: () => false
};
});

Expand Down Expand Up @@ -376,7 +376,7 @@ describe('HTTP Requestor', () => {
jest.mock('../../../lib/features', () => {
return {
...mocked.features,
isMobileSafari18: () => true
isSafari18: () => true
};
});
const { httpRequest: reloadedHttpRequest } = jest.requireActual('../../../lib/http');
Expand All @@ -390,7 +390,7 @@ describe('HTTP Requestor', () => {
jest.mock('../../../lib/features', () => {
return {
...mocked.features,
isMobileSafari18: () => false
isSafari18: () => false
};
});
});
Expand Down
2 changes: 1 addition & 1 deletion test/spec/idx/IdxStorageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jest.mock('../../../lib/util', () => {
jest.mock('../../../lib/features', () => {
return {
isBrowser: () => {},
isMobileSafari18: () => false
isSafari18: () => false
};
});

Expand Down
2 changes: 1 addition & 1 deletion test/spec/oidc/OAuthStorageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jest.mock('../../../lib/util', () => {
jest.mock('../../../lib/features', () => {
return {
isBrowser: () => {},
isMobileSafari18: () => false
isSafari18: () => false
};
});

Expand Down
2 changes: 1 addition & 1 deletion test/spec/oidc/endpoints/well-known.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const mocked = {
isBrowser: () => typeof window !== 'undefined',
isIE11OrLess: () => false,
isLocalhost: () => false,
isMobileSafari18: () => false
isSafari18: () => false
}
};
jest.mock('../../../../lib/features', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/spec/oidc/util/prepareEnrollAuthenticatorParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const mocked = {
isLocalhost: () => true,
isHTTPS: () => false,
isPKCESupported: () => true,
isMobileSafari18: () => false,
isSafari18: () => false,
},
};
jest.mock('../../../../lib/features', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/spec/oidc/util/prepareTokenParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const mocked = {
isPKCESupported: () => true,
hasTextEncoder: () => true,
isDPoPSupported: () => true,
isMobileSafari18: () => false,
isSafari18: () => false,
},
wellKnown: {
getWellKnown: (): Promise<unknown> => Promise.resolve()
Expand Down
24 changes: 0 additions & 24 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4882,11 +4882,6 @@ [email protected]:
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==

detect-europe-js@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/detect-europe-js/-/detect-europe-js-0.1.2.tgz#aa76642e05dae786efc2e01a23d4792cd24c7b88"
integrity sha512-lgdERlL3u0aUdHocoouzT10d9I89VVhk0qNRmll7mXdGfJT1/wqZ2ZLA4oJAjeACPY5fT1wsbq2AT+GkuInsow==

detect-file@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
Expand Down Expand Up @@ -7770,11 +7765,6 @@ is-shared-array-buffer@^1.0.2:
dependencies:
call-bind "^1.0.2"

is-standalone-pwa@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/is-standalone-pwa/-/is-standalone-pwa-0.1.1.tgz#7a1b0459471a95378aa0764d5dc0a9cec95f2871"
integrity sha512-9Cbovsa52vNQCjdXOzeQq5CnCbAcRk05aU62K20WO372NrTv0NxibLFCK6lQ4/iZEFdEA3p3t2VNOn8AJ53F5g==

is-stream@^2.0.0, is-stream@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
Expand Down Expand Up @@ -12808,20 +12798,6 @@ [email protected]:
resolved "https://registry.yarnpkg.com/u2f-api-polyfill/-/u2f-api-polyfill-0.4.3.tgz#b7ad165a6f962558517a867c5c4bf9399fcf7e98"
integrity sha512-0DVykdzG3tKft2GciQCGzgO8BinDEfIhTBo7FKbLBmA+sVTPYmNOFbsZuduYQmnc3+ykUadTHNqXVqnvBfLCvg==

ua-is-frozen@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ua-is-frozen/-/ua-is-frozen-0.1.2.tgz#bfbc5f06336e379590e36beca444188c7dc3a7f3"
integrity sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw==

ua-parser-js@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-2.0.0.tgz#fae88e352510198bd29a6dd41624c7cd0d2c7ade"
integrity sha512-SASgD4RlB7+SCMmlVNqrhPw0f/2pGawWBzJ2+LwGTD0GgNnrKGzPJDiraGHJDwW9Zm5DH2lTmUpqDpbZjJY4+Q==
dependencies:
detect-europe-js "^0.1.2"
is-standalone-pwa "^0.1.1"
ua-is-frozen "^0.1.2"

uglify-js@^3.1.4:
version "3.17.3"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.3.tgz#f0feedf019c4510f164099e8d7e72ff2d7304377"
Expand Down

0 comments on commit 45e1ed3

Please sign in to comment.