@@ -57,9 +57,7 @@ public static class Authentication
5757 */
5858 ExtractGetOrPostHttpListenerRequest < ExtractRedirectionRequestContext > . Descriptor ,
5959 ExtractProtocolActivationParameters < ExtractRedirectionRequestContext > . Descriptor ,
60- ExtractASWebAuthenticationCallbackUrlData < ExtractRedirectionRequestContext > . Descriptor ,
61- ExtractCustomTabsIntentData < ExtractRedirectionRequestContext > . Descriptor ,
62- ExtractWebAuthenticationResultData < ExtractRedirectionRequestContext > . Descriptor ,
60+ ExtractPlatformCallbackParameters < ExtractRedirectionRequestContext > . Descriptor ,
6361
6462 /*
6563 * Redirection response handling:
@@ -68,9 +66,7 @@ public static class Authentication
6866 AttachCacheControlHeader < ApplyRedirectionResponseContext > . Descriptor ,
6967 ProcessEmptyHttpResponse . Descriptor ,
7068 ProcessProtocolActivationResponse < ApplyRedirectionResponseContext > . Descriptor ,
71- ProcessASWebAuthenticationSessionResponse < ApplyRedirectionResponseContext > . Descriptor ,
72- ProcessCustomTabsIntentResponse < ApplyRedirectionResponseContext > . Descriptor ,
73- ProcessWebAuthenticationResultResponse < ApplyRedirectionResponseContext > . Descriptor
69+ ProcessPlatformCallbackResponse < ApplyRedirectionResponseContext > . Descriptor
7470 ] ) ;
7571
7672 /// <summary>
@@ -123,7 +119,8 @@ public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
123119 throw new PlatformNotSupportedException ( SR . GetResourceString ( SR . ID0446 ) ) ;
124120 }
125121
126- var source = new TaskCompletionSource < NSUrl > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
122+ var source = new TaskCompletionSource < OpenIddictClientSystemIntegrationPlatformCallback > (
123+ TaskCreationOptions . RunContinuationsAsynchronously ) ;
127124
128125 // OpenIddict represents the complete interactive authentication dance as a two-phase process:
129126 // - The challenge, during which the user is redirected to the authorization server, either
@@ -161,11 +158,11 @@ public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
161158 throw new InvalidOperationException ( SR . GetResourceString ( SR . ID0448 ) ) ;
162159 }
163160
164- NSUrl url ;
161+ OpenIddictClientSystemIntegrationPlatformCallback callback ;
165162
166163 try
167164 {
168- url = await source . Task . WaitAsync ( context . CancellationToken ) ;
165+ callback = await source . Task . WaitAsync ( context . CancellationToken ) ;
169166 }
170167
171168 // Since the result of this operation is known by the time the task signaled by ASWebAuthenticationSession
@@ -195,7 +192,7 @@ public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
195192 return ;
196193 }
197194
198- await _service . HandleASWebAuthenticationCallbackUrlAsync ( url , context . CancellationToken ) ;
195+ await _service . HandlePlatformCallbackAsync ( callback , context . CancellationToken ) ;
199196 context . HandleRequest ( ) ;
200197 return ;
201198
@@ -250,7 +247,43 @@ void HandleCallback(NSUrl? url, NSError? error)
250247 {
251248 if ( url is not null )
252249 {
253- source . SetResult ( url ) ;
250+ var parameters = new Dictionary < string , OpenIddictParameter > ( StringComparer . Ordinal ) ;
251+
252+ if ( ! string . IsNullOrEmpty ( url . Query ) )
253+ {
254+ foreach ( var parameter in OpenIddictHelpers . ParseQuery ( url . Query ) )
255+ {
256+ parameters [ parameter . Key ] = parameter . Value . Count switch
257+ {
258+ 0 => default ,
259+ 1 => parameter . Value [ 0 ] ,
260+ _ => parameter . Value . ToArray ( )
261+ } ;
262+ }
263+ }
264+
265+ // Note: the fragment is always processed after the query string to ensure that
266+ // parameters extracted from the fragment are preferred to parameters extracted
267+ // from the query string when they are present in both parts.
268+
269+ if ( ! string . IsNullOrEmpty ( url . Fragment ) )
270+ {
271+ foreach ( var parameter in OpenIddictHelpers . ParseFragment ( url . Fragment ) )
272+ {
273+ parameters [ parameter . Key ] = parameter . Value . Count switch
274+ {
275+ 0 => default ,
276+ 1 => parameter . Value [ 0 ] ,
277+ _ => parameter . Value . ToArray ( )
278+ } ;
279+ }
280+ }
281+
282+ source . SetResult ( new OpenIddictClientSystemIntegrationPlatformCallback ( url ! , parameters )
283+ {
284+ // Attach the raw URL to the callback properties.
285+ Properties = { [ typeof ( NSUrl ) . FullName ! ] = url }
286+ } ) ;
254287 }
255288
256289 else if ( error is not null )
@@ -426,8 +459,47 @@ public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
426459 parameter => new StringValues ( ( string ? [ ] ? ) parameter . Value ) ) ) ,
427460 callbackUri : new Uri ( context . RedirectUri , UriKind . Absolute ) ) )
428461 {
429- case { ResponseStatus : WebAuthenticationStatus . Success } result :
430- await _service . HandleWebAuthenticationResultAsync ( result , context . CancellationToken ) ;
462+ case { ResponseStatus : WebAuthenticationStatus . Success } result
463+ when Uri . TryCreate ( result . ResponseData , UriKind . Absolute , out Uri ? uri ) :
464+ var parameters = new Dictionary < string , OpenIddictParameter > ( StringComparer . Ordinal ) ;
465+
466+ if ( ! string . IsNullOrEmpty ( uri . Query ) )
467+ {
468+ foreach ( var parameter in OpenIddictHelpers . ParseQuery ( uri . Query ) )
469+ {
470+ parameters [ parameter . Key ] = parameter . Value . Count switch
471+ {
472+ 0 => default ,
473+ 1 => parameter . Value [ 0 ] ,
474+ _ => parameter . Value . ToArray ( )
475+ } ;
476+ }
477+ }
478+
479+ // Note: the fragment is always processed after the query string to ensure that
480+ // parameters extracted from the fragment are preferred to parameters extracted
481+ // from the query string when they are present in both parts.
482+
483+ if ( ! string . IsNullOrEmpty ( uri . Fragment ) )
484+ {
485+ foreach ( var parameter in OpenIddictHelpers . ParseFragment ( uri . Fragment ) )
486+ {
487+ parameters [ parameter . Key ] = parameter . Value . Count switch
488+ {
489+ 0 => default ,
490+ 1 => parameter . Value [ 0 ] ,
491+ _ => parameter . Value . ToArray ( )
492+ } ;
493+ }
494+ }
495+
496+ var callback = new OpenIddictClientSystemIntegrationPlatformCallback ( uri , parameters )
497+ {
498+ // Attach the authentication result to the properties.
499+ Properties = { [ typeof ( WebAuthenticationResult ) . FullName ! ] = result }
500+ } ;
501+
502+ await _service . HandlePlatformCallbackAsync ( callback , context . CancellationToken ) ;
431503 context . HandleRequest ( ) ;
432504 return ;
433505
0 commit comments