Is this related to a new or existing framework?
React Native
Is this related to a new or existing API?
Authentication
Is this related to another service?
- Amazon Cognito (Hosted UI / OAuth 2.0 flows) - CloudFront (HTTPS endpoint for App Link verification) - S3 (hosting
.well-known/assetlinks.json and apple-app-site-association)
Describe the feature you'd like to request
On Android, using custom URL schemes (e.g., myapp://auth/callback) as OAuth redirect URIs is vulnerable to authorization code interception by malicious apps that register the same scheme. Android shows a disambiguation dialog ("Open with...") allowing any app claiming the scheme to steal the auth code.
The industry-standard mitigation (per RFC 8252 §8.2) is to use HTTPS App Links (Android) / Universal Links (iOS) as the redirect URI. These are verified against a .well-known/assetlinks.json file on the domain, ensuring only the legitimate app (matching package name + SHA-256 signing certificate) can handle the redirect.
Amplify v6 has the preferredRedirectUrl option in signInWithRedirect() and getRedirectUrl.native.js has logic to handle it — but the parameter is never passed through the internal call chain, making HTTPS redirects impossible without patching.
Request: Wire preferredRedirectUrl through signInWithRedirect() → oauthSignIn() → getRedirectUrl() so that HTTPS App Links work as OAuth redirect URIs on React Native.
Describe the solution you'd like
A one-line fix in signInWithRedirect.js to pass preferredRedirectUrl through:
Current code (@aws-amplify/auth/dist/cjs/providers/cognito/apis/signInWithRedirect.js):
return oauthSignIn({
oauthConfig: authConfig.loginWith.oauth,
clientId: authConfig.userPoolClientId,
provider,
idpIdentifier,
customState: input?.customState,
preferPrivateSession: input?.options?.preferPrivateSession,
options: {
loginHint: input?.options?.loginHint,
lang: input?.options?.lang,
nonce: input?.options?.nonce,
prompt: input?.options?.prompt,
},
authSessionOpener: input?.options?.authSessionOpener,
// ❌ preferredRedirectUrl is NOT passed here
});
Proposed fix:
return oauthSignIn({
oauthConfig: authConfig.loginWith.oauth,
clientId: authConfig.userPoolClientId,
provider,
idpIdentifier,
customState: input?.customState,
preferPrivateSession: input?.options?.preferPrivateSession,
options: {
loginHint: input?.options?.loginHint,
lang: input?.options?.lang,
nonce: input?.options?.nonce,
prompt: input?.options?.prompt,
},
authSessionOpener: input?.options?.authSessionOpener,
preferredRedirectUrl: input?.options?.preferredRedirectUrl, // ✅ ADD THIS
});
And in oauthSignIn function signature, add preferredRedirectUrl to the destructured params:
const oauthSignIn = async ({ oauthConfig, provider, idpIdentifier, clientId, customState, preferPrivateSession, options, authSessionOpener, preferredRedirectUrl, }) => {
And pass it to getRedirectUrl:
const redirectUri = (0, oauth_1.getRedirectUrl)(oauthConfig.redirectSignIn, preferredRedirectUrl);
The getRedirectUrl.native.js already has the logic to handle preferredRedirectUrl — it just never receives it.
Describe alternatives you've considered
Alternative 1: Patch via postinstall script (current workaround)
We currently patch getRedirectUrl.native.js via a postinstall.sh script to prefer HTTPS URLs when available:
// Patched: prefer HTTPS over custom scheme
const httpsRedirectUrl = redirects?.find(redirect => redirect.startsWith('https://'));
if (httpsRedirectUrl) {
return httpsRedirectUrl;
}
return appSchemeRedirectUrl;
Downsides: Fragile, breaks on Amplify updates, requires custom build scripts.
Alternative 2: Change default behavior on React Native
Instead of always defaulting to the custom scheme, getRedirectUrl.native.js could prefer HTTPS when available (since HTTPS is strictly more secure than custom schemes on mobile).
Alternative 3: Remove custom scheme requirement
Currently, getRedirectUrl.native.js throws invalidAppSchemeException if no custom scheme URL exists in the config. For apps that ONLY want HTTPS redirects, this validation should be optional.
Additional context
Security Impact
This is a security vulnerability in the current implementation. On Android:
- Any malicious app can register
myapp://auth/callback
- When Cognito redirects with the auth code, Android shows "Open with" dialog
- Malicious app can intercept the authorization code
- Auth code can be exchanged for access/refresh tokens (PKCE mitigates but doesn't eliminate risk on Android < 12)
Working Implementation
We built a complete working implementation with:
- CloudFront + S3 hosting
.well-known/assetlinks.json for App Link verification
- Custom
authSessionOpener using Linking.openURL (Chrome dispatches App Links correctly)
- Patched
getRedirectUrl.native.js to prefer HTTPS
- Custom sign-out flow (Amplify's
signOut() also needs the redirect URL fix)
- Tested with a malicious app installed — no interception possible with HTTPS App Links
Affected Files (3 total for the fix)
packages/auth/src/providers/cognito/apis/signInWithRedirect.ts — pass preferredRedirectUrl through
packages/auth/src/providers/cognito/utils/oauth/getRedirectUrl.native.ts — already has the logic (no change needed)
packages/auth/src/providers/cognito/utils/oauth/handleOAuthSignOut.native.ts — same fix needed for sign-out redirect
References
Enterprise Use Case
For regulated environments (finance, healthcare, government), custom URL schemes are not acceptable because:
- They cannot be verified/owned (any app can claim them)
- They don't meet security audit requirements for OAuth flows
- Industry standards (RFC 8252, FAPI) recommend HTTPS-based redirects
Is this something that you'd be interested in working on?
👋 I may be able to implement this feature request
The fix is minimal (3 lines across 1-2 files). Happy to submit a PR if the approach is approved
Reproduction Steps (for maintainers)
- Create a React Native app with
aws-amplify v6.18+
- Configure
signInWithRedirect with both HTTPS and custom scheme in redirectSignIn
- Pass
preferredRedirectUrl: 'https://...' in options
- Observe that the authorize URL still contains
redirect_uri=myapp://... (custom scheme)
- Check
getRedirectUrl.native.js — preferredRedirectUrl parameter is always undefined
Breaking Change Assessment
This fix is non-breaking and safe for a patch release (e.g., 6.20.1):
-
preferredRedirectUrl is already a documented API parameter — it's accepted by signInWithRedirect() today, just never wired through internally. No API signature changes required.
-
getRedirectUrl() already accepts the optional second parameter — the receiving function has the logic implemented; it simply never receives the value from the call site.
-
Backward-compatible behavior:
- If
preferredRedirectUrl is not passed: behavior is identical to today (picks first URL, or on native, prefers custom scheme). Zero impact on existing apps.
- If
preferredRedirectUrl is passed: the parameter now works as documented. This is a bug fix, not a behavior change.
-
Only theoretical "break": An app that passes preferredRedirectUrl but unknowingly depends on it being ignored (relying on the default URL selection). This would be an app depending on buggy behavior — not a valid backward-compatibility concern.
Conclusion: This qualifies as a bug fix, not a feature or breaking change. No major version bump needed.
Is this something that you'd be interested in working on?
- [✔️ ] 👋 I may be able to implement this feature request
- [ ❌ ] ⚠️ This feature might incur a breaking change
Is this related to a new or existing framework?
React Native
Is this related to a new or existing API?
Authentication
Is this related to another service?
.well-known/assetlinks.jsonandapple-app-site-association)Describe the feature you'd like to request
On Android, using custom URL schemes (e.g.,
myapp://auth/callback) as OAuth redirect URIs is vulnerable to authorization code interception by malicious apps that register the same scheme. Android shows a disambiguation dialog ("Open with...") allowing any app claiming the scheme to steal the auth code.The industry-standard mitigation (per RFC 8252 §8.2) is to use HTTPS App Links (Android) / Universal Links (iOS) as the redirect URI. These are verified against a
.well-known/assetlinks.jsonfile on the domain, ensuring only the legitimate app (matching package name + SHA-256 signing certificate) can handle the redirect.Amplify v6 has the
preferredRedirectUrloption insignInWithRedirect()andgetRedirectUrl.native.jshas logic to handle it — but the parameter is never passed through the internal call chain, making HTTPS redirects impossible without patching.Request: Wire
preferredRedirectUrlthroughsignInWithRedirect()→oauthSignIn()→getRedirectUrl()so that HTTPS App Links work as OAuth redirect URIs on React Native.Describe the solution you'd like
A one-line fix in
signInWithRedirect.jsto passpreferredRedirectUrlthrough:Current code (
@aws-amplify/auth/dist/cjs/providers/cognito/apis/signInWithRedirect.js):Proposed fix:
And in
oauthSignInfunction signature, addpreferredRedirectUrlto the destructured params:And pass it to
getRedirectUrl:The
getRedirectUrl.native.jsalready has the logic to handlepreferredRedirectUrl— it just never receives it.Describe alternatives you've considered
Alternative 1: Patch via postinstall script (current workaround)
We currently patch
getRedirectUrl.native.jsvia apostinstall.shscript to prefer HTTPS URLs when available:Downsides: Fragile, breaks on Amplify updates, requires custom build scripts.
Alternative 2: Change default behavior on React Native
Instead of always defaulting to the custom scheme,
getRedirectUrl.native.jscould prefer HTTPS when available (since HTTPS is strictly more secure than custom schemes on mobile).Alternative 3: Remove custom scheme requirement
Currently,
getRedirectUrl.native.jsthrowsinvalidAppSchemeExceptionif no custom scheme URL exists in the config. For apps that ONLY want HTTPS redirects, this validation should be optional.Additional context
Security Impact
This is a security vulnerability in the current implementation. On Android:
myapp://auth/callbackWorking Implementation
We built a complete working implementation with:
.well-known/assetlinks.jsonfor App Link verificationauthSessionOpenerusingLinking.openURL(Chrome dispatches App Links correctly)getRedirectUrl.native.jsto prefer HTTPSsignOut()also needs the redirect URL fix)Affected Files (3 total for the fix)
packages/auth/src/providers/cognito/apis/signInWithRedirect.ts— passpreferredRedirectUrlthroughpackages/auth/src/providers/cognito/utils/oauth/getRedirectUrl.native.ts— already has the logic (no change needed)packages/auth/src/providers/cognito/utils/oauth/handleOAuthSignOut.native.ts— same fix needed for sign-out redirectReferences
Enterprise Use Case
For regulated environments (finance, healthcare, government), custom URL schemes are not acceptable because:
Is this something that you'd be interested in working on?
👋 I may be able to implement this feature request
The fix is minimal (3 lines across 1-2 files). Happy to submit a PR if the approach is approved
Reproduction Steps (for maintainers)
aws-amplifyv6.18+signInWithRedirectwith both HTTPS and custom scheme inredirectSignInpreferredRedirectUrl: 'https://...'in optionsredirect_uri=myapp://...(custom scheme)getRedirectUrl.native.js—preferredRedirectUrlparameter is alwaysundefinedBreaking Change Assessment
This fix is non-breaking and safe for a patch release (e.g.,
6.20.1):preferredRedirectUrlis already a documented API parameter — it's accepted bysignInWithRedirect()today, just never wired through internally. No API signature changes required.getRedirectUrl()already accepts the optional second parameter — the receiving function has the logic implemented; it simply never receives the value from the call site.Backward-compatible behavior:
preferredRedirectUrlis not passed: behavior is identical to today (picks first URL, or on native, prefers custom scheme). Zero impact on existing apps.preferredRedirectUrlis passed: the parameter now works as documented. This is a bug fix, not a behavior change.Only theoretical "break": An app that passes
preferredRedirectUrlbut unknowingly depends on it being ignored (relying on the default URL selection). This would be an app depending on buggy behavior — not a valid backward-compatibility concern.Conclusion: This qualifies as a bug fix, not a feature or breaking change. No major version bump needed.
Is this something that you'd be interested in working on?