@@ -2,13 +2,18 @@ namespace KK.AspNetCore.EasyAuthAuthentication
22{
33 using System ;
44 using System . Collections . Generic ;
5+ using System . IdentityModel . Tokens . Jwt ;
6+ using System . Linq ; // required by Children<JObject>.FirstOrDefault requires using System.Linq;
57 using System . Net ;
68 using System . Net . Http ;
79 using System . Security . Claims ;
810 using System . Security . Principal ;
11+ using System . Text ;
912 using System . Text . Encodings . Web ;
1013 using System . Threading . Tasks ;
14+ using KK . AspNetCore . EasyAuthAuthentication . Services ;
1115 using Microsoft . AspNetCore . Authentication ;
16+ using Microsoft . AspNetCore . Http ;
1217 using Microsoft . Extensions . Logging ;
1318 using Microsoft . Extensions . Options ;
1419 using Newtonsoft . Json ;
@@ -34,142 +39,44 @@ public EasyAuthAuthenticationHandler(
3439 {
3540 }
3641
42+ private static Func < ClaimsPrincipal , bool > isContextUserNotAuthenticated =
43+ user => ( user == null || user . Identity == null || user . Identity . IsAuthenticated == false ) ;
44+ private static Func < IHeaderDictionary , string , bool > isHeaderSet =
45+ ( headers , headerName ) => ! string . IsNullOrEmpty ( headers [ headerName ] . ToString ( ) ) ;
46+ private Func < IHeaderDictionary , ClaimsPrincipal , bool > canUseHeaderAuth =
47+ ( headers , user ) => isContextUserNotAuthenticated ( user ) &&
48+ isHeaderSet ( headers , AuthTokenHeaderNames . AADIdToken ) ;
49+ private static Func < IHeaderDictionary , ClaimsPrincipal , HttpRequest , string , bool > canUseEasyAuthJson =
50+ ( headers , user , request , authEndpoint ) =>
51+ isContextUserNotAuthenticated ( user )
52+ && ! isHeaderSet ( headers , AuthTokenHeaderNames . AADIdToken )
53+ && request . Path != "/" + $ "{ authEndpoint } ";
54+
3755 /// <inheritdoc/>
3856 protected override async Task < AuthenticateResult > HandleAuthenticateAsync ( )
3957 {
4058 this . Logger . LogInformation ( "starting authentication handler for app service authentication" ) ;
4159
42- if (
43- ( this . Context . User == null ||
44- this . Context . User . Identity == null ||
45- this . Context . User . Identity . IsAuthenticated == false )
46- && this . Context . Request . Path != "/" + $ "{ this . Options . AuthEndpoint } ")
60+ if ( canUseHeaderAuth ( this . Context . Request . Headers , this . Context . User ) )
4761 {
48- var cookieContainer = new CookieContainer ( ) ;
49- var handler = this . CreateHandler ( ref cookieContainer ) ;
50- var httpRequest = this . CreateAuthRequest ( ref cookieContainer ) ;
51-
52- JArray payload = null ;
53- try
54- {
55- payload = await this . GetAuthMe ( handler , httpRequest ) ;
56- }
57- catch ( Exception ex )
58- {
59- return AuthenticateResult . Fail ( ex . Message ) ;
60- }
61-
62- // build up identity from json...
63- var ticket = this . BuildIdentityFromJsonPayload ( ( JObject ) payload [ 0 ] ) ;
64-
65- this . Logger . LogInformation ( "Set identity to user context object." ) ;
66- this . Context . User = ticket . Principal ;
67-
68- this . Logger . LogInformation ( "identity build was a success, returning ticket" ) ;
69- return AuthenticateResult . Success ( ticket ) ;
62+ return EasyAuthWithHeaderService . AuthUser ( this . Logger , this . Context ) ;
7063 }
71- else
64+ else if ( canUseEasyAuthJson ( this . Context . Request . Headers , this . Context . User , this . Context . Request , this . Options . AuthEndpoint ) )
7265 {
73- this . Logger . LogInformation ( "identity already set, skipping middleware" ) ;
74- return AuthenticateResult . NoResult ( ) ;
66+ return await EasyAuthWithAuthMeService . AuthUser ( this . Logger , this . Context , this . Options . AuthEndpoint ) ;
7567 }
76- }
77-
78- private AuthenticationTicket BuildIdentityFromJsonPayload ( JObject payload )
79- {
80- var id = payload [ "user_id" ] . Value < string > ( ) ;
81- var idToken = payload [ "id_token" ] . Value < string > ( ) ;
82- var providerName = payload [ "provider_name" ] . Value < string > ( ) ;
83-
84- this . Logger . LogDebug ( "payload was fetched from endpoint. id: {0}" , id ) ;
85-
86- var identity = new GenericIdentity ( id ) ;
87-
88- this . Logger . LogInformation ( "building claims from payload..." ) ;
89-
90- var claims = new List < Claim > ( ) ;
91- foreach ( var claim in payload [ "user_claims" ] )
92- {
93- claims . Add ( new Claim ( claim [ "typ" ] . ToString ( ) , claim [ "val" ] . ToString ( ) ) ) ;
94- }
95-
96- this . Logger . LogInformation ( "Add claims to new identity" ) ;
97-
98- identity . AddClaims ( claims ) ;
99- identity . AddClaim ( new Claim ( "id_token" , idToken ) ) ;
100- identity . AddClaim ( new Claim ( "provider_name" , providerName ) ) ;
101- var p = new GenericPrincipal ( identity , null ) ;
102- return new AuthenticationTicket (
103- p ,
104- EasyAuthAuthenticationDefaults . AuthenticationScheme ) ;
105- }
106-
107- private HttpRequestMessage CreateAuthRequest ( ref CookieContainer cookieContainer )
108- {
109- this . Logger . LogInformation ( $ "identity not found, attempting to fetch from auth endpoint '/{ this . Options . AuthEndpoint } '") ;
110-
111- var uriString = $ "{ this . Context . Request . Scheme } ://{ this . Context . Request . Host } ";
112-
113- this . Logger . LogDebug ( "host uri: {0}" , uriString ) ;
114-
115- foreach ( var c in this . Context . Request . Cookies )
116- {
117- cookieContainer . Add ( new Uri ( uriString ) , new Cookie ( c . Key , c . Value ) ) ;
118- }
119-
120- this . Logger . LogDebug ( "found {0} cookies in request" , cookieContainer . Count ) ;
121-
122- foreach ( var cookie in this . Context . Request . Cookies )
123- {
124- this . Logger . LogDebug ( cookie . Key ) ;
125- }
126-
127- // fetch value from endpoint
128- var request = new HttpRequestMessage ( HttpMethod . Get , $ "{ uriString } /{ this . Options . AuthEndpoint } ") ;
129- foreach ( var header in this . Context . Request . Headers )
130- {
131- if ( header . Key . StartsWith ( "X-ZUMO-" ) )
132- {
133- request . Headers . Add ( header . Key , header . Value [ 0 ] ) ;
134- }
135- }
136-
137- return request ;
138- }
139-
140- private HttpClientHandler CreateHandler ( ref CookieContainer container )
141- {
142- var handler = new HttpClientHandler ( )
143- {
144- CookieContainer = container
145- } ;
146- return handler ;
147- }
148-
149- private async Task < JArray > GetAuthMe ( HttpClientHandler handler , HttpRequestMessage httpRequest )
150- {
151- JArray payload = null ;
152- using ( var client = new HttpClient ( handler ) )
68+ else
15369 {
154- var response = await client . SendAsync ( httpRequest ) ;
155- if ( ! response . IsSuccessStatusCode )
156- {
157- this . Logger . LogDebug ( "auth endpoint was not sucessful. Status code: {0}, reason {1}" , response . StatusCode , response . ReasonPhrase ) ;
158- throw new WebException ( "Unable to fetch user information from auth endpoint." ) ;
159- }
160-
161- var content = await response . Content . ReadAsStringAsync ( ) ;
162- try
70+ if ( isContextUserNotAuthenticated ( this . Context . User ) )
16371 {
164- payload = JArray . Parse ( content ) ;
72+ this . Logger . LogInformation ( "The identity isn't set by easy auth." ) ;
16573 }
166- catch ( Exception )
74+ else
16775 {
168- throw new JsonSerializationException ( "Could not retreive json from /me endpoint. ") ;
76+ this . Logger . LogInformation ( "identity already set, skipping middleware ") ;
16977 }
78+ return AuthenticateResult . NoResult ( ) ;
17079 }
171-
172- return payload ;
17380 }
17481 }
175- }
82+ }
0 commit comments