@@ -72,132 +72,132 @@ public static RpcHttpEndpoints.AuthenticateDelegate Compose(
7272 var providerSlots = new SemaphoreSlim ( maxProviderConcurrency , maxProviderConcurrency ) ;
7373 return async context =>
7474 {
75- AuthFailure ? missing = null ;
76- if ( applicationAuthenticate is not null )
77- {
78- try
75+ AuthFailure ? missing = null ;
76+ if ( applicationAuthenticate is not null )
7977 {
80- await applicationAuthenticate ( context ) . ConfigureAwait ( false ) ;
78+ try
79+ {
80+ await applicationAuthenticate ( context ) . ConfigureAwait ( false ) ;
81+ }
82+ catch ( AuthFailure failure ) when ( failure . Reason == AuthReason . MissingCredential )
83+ {
84+ missing = failure ;
85+ }
8186 }
82- catch ( AuthFailure failure ) when ( failure . Reason == AuthReason . MissingCredential )
83- {
84- missing = failure ;
85- }
86- }
8787
88- var identity = AuthIdentity . GetFrom ( context ) ;
89- var existing = identity is null
90- ? AuthContext . Anonymous
91- : new AuthContext ( identity . Domain , identity . Authenticated , identity . Principal ) ;
92- using var deadline = CancellationTokenSource . CreateLinkedTokenSource ( context . RequestAborted ) ;
93- deadline . CancelAfter ( providerTimeout ) ;
94- var headers = context . Request . Headers . ToDictionary (
95- pair => pair . Key ,
96- pair => ( IReadOnlyList < string > ) Array . AsReadOnly ( pair . Value . Select ( value => value ?? "" ) . ToArray ( ) ) ,
97- StringComparer . OrdinalIgnoreCase ) ;
98- var physical = context . Items [ PhysicalPeerItem ] as PhysicalConnection ;
99- var resolution = physical is null ? null : new PeerResolutionContext (
100- "http" ,
101- physical . RemoteAddress ,
102- destinationAddress : FormatAddress ( physical . LocalAddress , physical . LocalPort ) ,
103- authority : context . Request . Host . Value ,
104- serviceName : serviceName ,
105- headers : headers ,
106- metadata : new Dictionary < string , object ? > { [ "request_path" ] = context . Request . Path . Value ?? "" } ,
107- deadline : DateTimeOffset . UtcNow + providerTimeout ,
108- sourceEndpoint : FormatAddress ( physical . RemoteAddress , physical . RemotePort ) ) ;
109- var results = resolution is null
110- ? providers . Select ( provider =>
111- new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Unavailable ) ) . ToArray ( )
112- : await Task . WhenAll ( providers . Select ( async provider =>
113- {
114- if ( ! await providerSlots . WaitAsync ( 0 , context . RequestAborted ) . ConfigureAwait ( false ) )
115- return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Unavailable ) ;
116- Task < PeerIdentityResult > providerTask ;
117- try
118- {
119- providerTask = provider . ResolveAsync ( resolution , deadline . Token ) . AsTask ( ) ;
120- }
121- catch ( PeerIdentityRejectedException )
88+ var identity = AuthIdentity . GetFrom ( context ) ;
89+ var existing = identity is null
90+ ? AuthContext . Anonymous
91+ : new AuthContext ( identity . Domain , identity . Authenticated , identity . Principal ) ;
92+ using var deadline = CancellationTokenSource . CreateLinkedTokenSource ( context . RequestAborted ) ;
93+ deadline . CancelAfter ( providerTimeout ) ;
94+ var headers = context . Request . Headers . ToDictionary (
95+ pair => pair . Key ,
96+ pair => ( IReadOnlyList < string > ) Array . AsReadOnly ( pair . Value . Select ( value => value ?? "" ) . ToArray ( ) ) ,
97+ StringComparer . OrdinalIgnoreCase ) ;
98+ var physical = context . Items [ PhysicalPeerItem ] as PhysicalConnection ;
99+ var resolution = physical is null ? null : new PeerResolutionContext (
100+ "http" ,
101+ physical . RemoteAddress ,
102+ destinationAddress : FormatAddress ( physical . LocalAddress , physical . LocalPort ) ,
103+ authority : context . Request . Host . Value ,
104+ serviceName : serviceName ,
105+ headers : headers ,
106+ metadata : new Dictionary < string , object ? > { [ "request_path" ] = context . Request . Path . Value ?? "" } ,
107+ deadline : DateTimeOffset . UtcNow + providerTimeout ,
108+ sourceEndpoint : FormatAddress ( physical . RemoteAddress , physical . RemotePort ) ) ;
109+ var results = resolution is null
110+ ? providers . Select ( provider =>
111+ new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Unavailable ) ) . ToArray ( )
112+ : await Task . WhenAll ( providers . Select ( async provider =>
122113 {
123- providerSlots . Release ( ) ;
124- return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Invalid ) ;
125- }
126- catch ( PeerIdentityUnavailableException )
127- {
128- providerSlots . Release ( ) ;
129- return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Unavailable ) ;
130- }
131- catch
132- {
133- providerSlots . Release ( ) ;
134- throw new InvalidOperationException ( "peer identity provider failed" ) ;
135- }
114+ if ( ! await providerSlots . WaitAsync ( 0 , context . RequestAborted ) . ConfigureAwait ( false ) )
115+ return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Unavailable ) ;
116+ Task < PeerIdentityResult > providerTask ;
117+ try
118+ {
119+ providerTask = provider . ResolveAsync ( resolution , deadline . Token ) . AsTask ( ) ;
120+ }
121+ catch ( PeerIdentityRejectedException )
122+ {
123+ providerSlots . Release ( ) ;
124+ return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Invalid ) ;
125+ }
126+ catch ( PeerIdentityUnavailableException )
127+ {
128+ providerSlots . Release ( ) ;
129+ return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Unavailable ) ;
130+ }
131+ catch
132+ {
133+ providerSlots . Release ( ) ;
134+ throw new InvalidOperationException ( "peer identity provider failed" ) ;
135+ }
136+ try
137+ {
138+ var result = await providerTask . WaitAsync ( providerTimeout , context . RequestAborted ) . ConfigureAwait ( false ) ;
139+ if ( result is null || ! StringComparer . Ordinal . Equals ( provider . Provider , result . Provider ) )
140+ throw new InvalidOperationException ( "peer identity provider result mismatch" ) ;
141+ providerSlots . Release ( ) ;
142+ return result ;
143+ }
144+ catch ( TimeoutException )
145+ {
146+ ReleaseProviderSlotWhenComplete ( providerTask , providerSlots ) ;
147+ return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Unavailable ) ;
148+ }
149+ catch ( OperationCanceledException ) when ( ! context . RequestAborted . IsCancellationRequested )
150+ {
151+ if ( providerTask . IsCompleted ) providerSlots . Release ( ) ;
152+ else ReleaseProviderSlotWhenComplete ( providerTask , providerSlots ) ;
153+ return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Unavailable ) ;
154+ }
155+ catch ( OperationCanceledException )
156+ {
157+ if ( providerTask . IsCompleted ) providerSlots . Release ( ) ;
158+ else ReleaseProviderSlotWhenComplete ( providerTask , providerSlots ) ;
159+ throw ;
160+ }
161+ catch ( PeerIdentityRejectedException )
162+ {
163+ providerSlots . Release ( ) ;
164+ return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Invalid ) ;
165+ }
166+ catch ( PeerIdentityUnavailableException )
167+ {
168+ providerSlots . Release ( ) ;
169+ return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Unavailable ) ;
170+ }
171+ catch
172+ {
173+ providerSlots . Release ( ) ;
174+ throw new InvalidOperationException ( "peer identity provider failed" ) ;
175+ }
176+ } ) ) . ConfigureAwait ( false ) ;
177+
178+ var evidence = new PeerEvidenceSet ( results ) ;
179+ AuthContext auth ;
136180 try
137181 {
138- var result = await providerTask . WaitAsync ( providerTimeout , context . RequestAborted ) . ConfigureAwait ( false ) ;
139- if ( result is null || ! StringComparer . Ordinal . Equals ( provider . Provider , result . Provider ) )
140- throw new InvalidOperationException ( "peer identity provider result mismatch" ) ;
141- providerSlots . Release ( ) ;
142- return result ;
143- }
144- catch ( TimeoutException )
145- {
146- ReleaseProviderSlotWhenComplete ( providerTask , providerSlots ) ;
147- return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Unavailable ) ;
148- }
149- catch ( OperationCanceledException ) when ( ! context . RequestAborted . IsCancellationRequested )
150- {
151- if ( providerTask . IsCompleted ) providerSlots . Release ( ) ;
152- else ReleaseProviderSlotWhenComplete ( providerTask , providerSlots ) ;
153- return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Unavailable ) ;
154- }
155- catch ( OperationCanceledException )
156- {
157- if ( providerTask . IsCompleted ) providerSlots . Release ( ) ;
158- else ReleaseProviderSlotWhenComplete ( providerTask , providerSlots ) ;
159- throw ;
182+ auth = await policy ( evidence , existing ) . ConfigureAwait ( false ) ;
160183 }
161184 catch ( PeerIdentityRejectedException )
162185 {
163- providerSlots . Release ( ) ;
164- return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Invalid ) ;
186+ throw new AuthFailure ( AuthReason . InvalidCredential , "peer identity rejected" ) ;
165187 }
166- catch ( PeerIdentityUnavailableException )
188+ catch ( PeerIdentityUnavailableException unavailable )
167189 {
168- providerSlots . Release ( ) ;
169- return new PeerIdentityResult ( provider . Provider , PeerIdentityStatus . Unavailable ) ;
190+ throw new PeerIdentityUnavailableException (
191+ "peer identity unavailable" , unavailable . RetryAfterSeconds ) ;
170192 }
171- catch
193+ if ( missing is not null && ! auth . Authenticated ) throw missing ;
194+ context . Items [ AuthItem ] = auth ;
195+ context . Items [ EvidenceItem ] = evidence ;
196+ var binding = EvidenceBinding ( auth ) ;
197+ if ( auth . Authenticated || binding is not null )
172198 {
173- providerSlots . Release ( ) ;
174- throw new InvalidOperationException ( "peer identity provider failed" ) ;
199+ AuthIdentity . SetOn ( context , auth . Domain , auth . Principal ?? "" , binding , auth . Authenticated ) ;
175200 }
176- } ) ) . ConfigureAwait ( false ) ;
177-
178- var evidence = new PeerEvidenceSet ( results ) ;
179- AuthContext auth ;
180- try
181- {
182- auth = await policy ( evidence , existing ) . ConfigureAwait ( false ) ;
183- }
184- catch ( PeerIdentityRejectedException )
185- {
186- throw new AuthFailure ( AuthReason . InvalidCredential , "peer identity rejected" ) ;
187- }
188- catch ( PeerIdentityUnavailableException unavailable )
189- {
190- throw new PeerIdentityUnavailableException (
191- "peer identity unavailable" , unavailable . RetryAfterSeconds ) ;
192- }
193- if ( missing is not null && ! auth . Authenticated ) throw missing ;
194- context . Items [ AuthItem ] = auth ;
195- context . Items [ EvidenceItem ] = evidence ;
196- var binding = EvidenceBinding ( auth ) ;
197- if ( auth . Authenticated || binding is not null )
198- {
199- AuthIdentity . SetOn ( context , auth . Domain , auth . Principal ?? "" , binding , auth . Authenticated ) ;
200- }
201201 } ;
202202 }
203203
0 commit comments