diff --git a/packages/toolkit/core-kit/src/regex.ts b/packages/toolkit/core-kit/src/regex.ts index 37450ad2e..a9eb5a18f 100644 --- a/packages/toolkit/core-kit/src/regex.ts +++ b/packages/toolkit/core-kit/src/regex.ts @@ -3,7 +3,15 @@ export const phoneRegEx = /^\d+$/; export const phoneInputRegEx = /^\+?[\d-( )]+$/; export const usernameRegEx = /^[A-Z_a-z]\w*$/; export const webRedirectUriProtocolRegEx = /^https?:$/; +/** + * Strict custom URI scheme check that matches the OIDC recommended pattern: a reversed domain name followed by a colon. + * E.g. `com.myapp://callback` is a valid redirect URI, but `myapp://callback` is not. + */ export const mobileUriSchemeProtocolRegEx = /^[a-z][\d+_a-z-]*(\.[\d+_a-z-]+)+:$/; +/** + * Loose custom URI scheme check that matches any non-whitespace character followed by a colon, for better compatibility. + * Community reports that some windows native apps use this scheme pattern. E.g. `myapp://callback` + */ export const looseNativeUriSchemeProtocolRegEx = /^\S*:$/; export const hexColorRegEx = /^#[\da-f]{3}([\da-f]{3})?$/i; export const dateRegex = /^\d{4}(-\d{2}){2}/; diff --git a/packages/toolkit/core-kit/src/utils/url.test.ts b/packages/toolkit/core-kit/src/utils/url.test.ts index 51f5525f2..eb384e210 100644 --- a/packages/toolkit/core-kit/src/utils/url.test.ts +++ b/packages/toolkit/core-kit/src/utils/url.test.ts @@ -17,11 +17,10 @@ describe('url utilities', () => { it('should detect invalid redirect URIs', () => { expect(validateRedirectUrl('io.logto://my-app/callback', 'web')).toBeFalsy(); - expect(validateRedirectUrl('ws://com.company://demo:1234', 'web')).toBeFalsy(); expect(validateRedirectUrl('abc.com', 'web')).toBeFalsy(); - expect(validateRedirectUrl('abc.com', 'native')).toBeFalsy(); - expect(validateRedirectUrl('http://localhost:3001', 'native')).toBeFalsy(); - expect(validateRedirectUrl('https://logto.dev/callback', 'native')).toBeFalsy(); + // Does not have colon. expect(validateRedirectUrl('demoApp/callback', 'native')).toBeFalsy(); + // Does not have non-whitespace characters before colon. + expect(validateRedirectUrl('://callback', 'native')).toBeFalsy(); }); });