@@ -27,22 +27,22 @@ public AuthService(IHttpClientFactory httpClientFactory, ILogger<AuthService> lo
2727 Encoding . UTF8 ,
2828 "application/json" ) ;
2929
30- _logger . LogInformation ( "Generating token for user {UserName}, request body: {RequestBody}" ,
30+ _logger . LogInformation ( "Generating token for user {UserName}, request body: {RequestBody}" ,
3131 userName , JsonSerializer . Serialize ( request ) ) ;
32-
32+
3333 var response = await _httpClient . PostAsync ( "/modulith/admin/generateToken" , content ) ;
34-
34+
3535 // Read the raw response for debugging
3636 var tokenString = await response . Content . ReadAsStringAsync ( ) ;
37- _logger . LogInformation ( "Response status: {Status}, Content: {Content}" ,
37+ _logger . LogInformation ( "Response status: {Status}, Content: {Content}" ,
3838 response . StatusCode , tokenString ) ;
39-
39+
4040 if ( ! response . IsSuccessStatusCode )
4141 {
4242 _logger . LogError ( "Token generation failed with status code {StatusCode}" , response . StatusCode ) ;
4343 return null ;
4444 }
45-
45+
4646 // The response is plain text containing the token, not JSON
4747 return ! string . IsNullOrWhiteSpace ( tokenString ) ? tokenString . Trim ( ) : null ;
4848 }
@@ -53,6 +53,86 @@ public AuthService(IHttpClientFactory httpClientFactory, ILogger<AuthService> lo
5353 }
5454 }
5555
56+ public async Task < string ? > RefreshTokenAsync ( string token )
57+ {
58+ try
59+ {
60+ _logger . LogDebug ( "Attempting to refresh token" ) ;
61+
62+ var request = new HttpRequestMessage ( HttpMethod . Post , "/modulith/admin/refreshToken" ) ;
63+ request . Headers . Add ( "Authorization" , $ "Bearer { token } ") ;
64+
65+ var response = await _httpClient . SendAsync ( request ) ;
66+
67+ if ( ! response . IsSuccessStatusCode )
68+ {
69+ _logger . LogWarning ( "Token refresh failed with status code {StatusCode}" , response . StatusCode ) ;
70+ return null ;
71+ }
72+
73+ var newToken = await response . Content . ReadAsStringAsync ( ) ;
74+ _logger . LogInformation ( "Token refreshed successfully" ) ;
75+ return ! string . IsNullOrWhiteSpace ( newToken ) ? newToken . Trim ( ) : null ;
76+ }
77+ catch ( Exception ex )
78+ {
79+ _logger . LogError ( ex , "Error refreshing token" ) ;
80+ return null ;
81+ }
82+ }
83+
84+ // Helper method to execute authenticated requests with automatic refresh
85+ public async Task < ( bool Success , HttpResponseMessage ? Response ) > ExecuteWithTokenRefreshAsync (
86+ Func < string , Task < HttpResponseMessage > > apiCall ,
87+ string token ,
88+ string username ,
89+ HttpContext httpContext )
90+ {
91+ try
92+ {
93+ // First attempt with current token
94+ var response = await apiCall ( token ) ;
95+
96+ // If successful, return the response
97+ if ( response . IsSuccessStatusCode )
98+ {
99+ return ( true , response ) ;
100+ }
101+
102+ // If we get a 401 Unauthorized, try refreshing the token
103+ if ( response . StatusCode == System . Net . HttpStatusCode . Unauthorized )
104+ {
105+ _logger . LogInformation ( "Received 401 Unauthorized, attempting to refresh token" ) ;
106+
107+ // Try to refresh the token
108+ var newToken = await RefreshTokenAsync ( token ) ;
109+
110+ if ( ! string . IsNullOrEmpty ( newToken ) )
111+ {
112+ // Update token in session
113+ httpContext . Session . SetString ( "AuthToken" , newToken ) ;
114+
115+ // Retry the API call with the new token
116+ var retryResponse = await apiCall ( newToken ) ;
117+ return ( retryResponse . IsSuccessStatusCode , retryResponse ) ;
118+ }
119+
120+ // If refresh fails, clear the token and return false
121+ _logger . LogWarning ( "Token refresh failed, user needs to re-authenticate" ) ;
122+ httpContext . Session . Remove ( "AuthToken" ) ;
123+ return ( false , null ) ;
124+ }
125+
126+ // For other error responses, just return as is
127+ return ( false , response ) ;
128+ }
129+ catch ( Exception ex )
130+ {
131+ _logger . LogError ( ex , "Error executing authenticated request" ) ;
132+ return ( false , null ) ;
133+ }
134+ }
135+
56136 public class TokenRequest
57137 {
58138 public string UserName { get ; set ; } = string . Empty ;
0 commit comments