@@ -16,7 +16,7 @@ import logger from './utils/logger';
1616import { isAccessTokenExpiredOrExpiring } from './utils/token' ;
1717import { PassportError , PassportErrorType , withPassportError } from './errors/passportError' ;
1818import {
19- DirectLoginMethod ,
19+ DirectLoginOptions ,
2020 PassportMetadata ,
2121 User ,
2222 DeviceTokenResponse ,
@@ -177,19 +177,38 @@ export default class AuthManager {
177177 } ) ;
178178 } ;
179179
180- private buildExtraQueryParams ( anonymousId ?: string , directLoginMethod ?: DirectLoginMethod ) : Record < string , string > {
181- return {
180+ private buildExtraQueryParams ( anonymousId ?: string , directLoginOptions ?: DirectLoginOptions ) : Record < string , string > {
181+ const params : Record < string , string > = {
182182 ...( this . userManager . settings ?. extraQueryParams ?? { } ) ,
183183 rid : getDetail ( Detail . RUNTIME_ID ) || '' ,
184184 third_party_a_id : anonymousId || '' ,
185- ...( directLoginMethod && { direct : directLoginMethod } ) ,
186185 } ;
186+
187+ if ( directLoginOptions ) {
188+ // If method is email, only include direct login params if email is valid
189+ if ( directLoginOptions . directLoginMethod === 'email' ) {
190+ const emailValue = directLoginOptions . email ;
191+ if ( emailValue ) {
192+ params . direct = directLoginOptions . directLoginMethod ;
193+ params . email = emailValue ;
194+ }
195+ // If email method but no valid email, disregard both direct and email params
196+ } else {
197+ // For non-email methods (social login), always include direct param
198+ params . direct = directLoginOptions . directLoginMethod ;
199+ }
200+ if ( directLoginOptions . marketingConsentStatus ) {
201+ params . marketingConsent = directLoginOptions . marketingConsentStatus ;
202+ }
203+ }
204+
205+ return params ;
187206 }
188207
189- public async loginWithRedirect ( anonymousId ?: string , directLoginMethod ?: DirectLoginMethod ) : Promise < void > {
208+ public async loginWithRedirect ( anonymousId ?: string , directLoginOptions ?: DirectLoginOptions ) : Promise < void > {
190209 await this . userManager . clearStaleState ( ) ;
191210 return withPassportError < void > ( async ( ) => {
192- const extraQueryParams = this . buildExtraQueryParams ( anonymousId , directLoginMethod ) ;
211+ const extraQueryParams = this . buildExtraQueryParams ( anonymousId , directLoginOptions ) ;
193212
194213 await this . userManager . signinRedirect ( {
195214 extraQueryParams,
@@ -200,12 +219,16 @@ export default class AuthManager {
200219 /**
201220 * login
202221 * @param anonymousId Caller can pass an anonymousId if they want to associate their user's identity with immutable's internal instrumentation.
222+ * @param directLoginOptions If provided, contains login method and marketing consent options
223+ * @param directLoginOptions.directLoginMethod The login method to use (e.g., 'google', 'apple', 'email')
224+ * @param directLoginOptions.marketingConsentStatus Marketing consent status ('opted_in' or 'unsubscribed')
225+ * @param directLoginOptions.email Required when directLoginMethod is 'email'
203226 */
204- public async login ( anonymousId ?: string , directLoginMethod ?: DirectLoginMethod ) : Promise < User > {
227+ public async login ( anonymousId ?: string , directLoginOptions ?: DirectLoginOptions ) : Promise < User > {
205228 return withPassportError < User > ( async ( ) => {
206229 const popupWindowTarget = 'passportLoginPrompt' ;
207230 const signinPopup = async ( ) => {
208- const extraQueryParams = this . buildExtraQueryParams ( anonymousId , directLoginMethod ) ;
231+ const extraQueryParams = this . buildExtraQueryParams ( anonymousId , directLoginOptions ) ;
209232
210233 return this . userManager . signinPopup ( {
211234 extraQueryParams,
@@ -289,7 +312,7 @@ export default class AuthManager {
289312 } , PassportErrorType . AUTHENTICATION_ERROR ) ;
290313 }
291314
292- public async getPKCEAuthorizationUrl ( directLoginMethod ?: DirectLoginMethod ) : Promise < string > {
315+ public async getPKCEAuthorizationUrl ( directLoginOptions ?: DirectLoginOptions ) : Promise < string > {
293316 const verifier = base64URLEncode ( window . crypto . getRandomValues ( new Uint8Array ( 32 ) ) ) ;
294317 const challenge = base64URLEncode ( await sha256 ( verifier ) ) ;
295318
@@ -312,7 +335,23 @@ export default class AuthManager {
312335
313336 if ( scope ) pKCEAuthorizationUrl . searchParams . set ( 'scope' , scope ) ;
314337 if ( audience ) pKCEAuthorizationUrl . searchParams . set ( 'audience' , audience ) ;
315- if ( directLoginMethod ) pKCEAuthorizationUrl . searchParams . set ( 'direct' , directLoginMethod ) ;
338+
339+ if ( directLoginOptions ) {
340+ // If method is email, only include direct login params if email is valid
341+ if ( directLoginOptions . directLoginMethod === 'email' ) {
342+ const emailValue = directLoginOptions . email ;
343+ if ( emailValue ) {
344+ pKCEAuthorizationUrl . searchParams . set ( 'direct' , directLoginOptions . directLoginMethod ) ;
345+ pKCEAuthorizationUrl . searchParams . set ( 'email' , emailValue ) ;
346+ }
347+ } else {
348+ // For non-email methods (social login), always include direct param
349+ pKCEAuthorizationUrl . searchParams . set ( 'direct' , directLoginOptions . directLoginMethod ) ;
350+ }
351+ if ( directLoginOptions . marketingConsentStatus ) {
352+ pKCEAuthorizationUrl . searchParams . set ( 'marketingConsent' , directLoginOptions . marketingConsentStatus ) ;
353+ }
354+ }
316355
317356 return pKCEAuthorizationUrl . toString ( ) ;
318357 }
0 commit comments