@@ -15,16 +15,19 @@ namespace PushSharp.Windows
1515{
1616 public class WnsServiceConnectionFactory : IServiceConnectionFactory < WnsNotification >
1717 {
18+ WnsAccessTokenManager wnsAccessTokenManager ;
19+
1820 public WnsServiceConnectionFactory ( WnsConfiguration configuration )
1921 {
22+ wnsAccessTokenManager = new WnsAccessTokenManager ( configuration ) ;
2023 Configuration = configuration ;
2124 }
2225
2326 public WnsConfiguration Configuration { get ; private set ; }
2427
2528 public IServiceConnection < WnsNotification > Create ( )
2629 {
27- return new WnsServiceConnection ( Configuration ) ;
30+ return new WnsServiceConnection ( Configuration , wnsAccessTokenManager ) ;
2831 }
2932 }
3033
@@ -39,32 +42,30 @@ public class WnsServiceConnection : IServiceConnection<WnsNotification>
3942 {
4043 HttpClient http ;
4144
42- public WnsServiceConnection ( WnsConfiguration configuration )
45+ public WnsServiceConnection ( WnsConfiguration configuration , WnsAccessTokenManager accessTokenManager )
4346 {
47+ AccessTokenManager = accessTokenManager ;
4448 Configuration = configuration ;
4549
4650 //TODO: Microsoft recommends we disable expect-100 to improve latency
4751 // Not sure how to do this in httpclient
4852 http = new HttpClient ( ) ;
4953 }
5054
55+ public WnsAccessTokenManager AccessTokenManager { get ; private set ; }
5156 public WnsConfiguration Configuration { get ; private set ; }
52- public string AccessToken { get ; private set ; }
53- public string TokenType { get ; private set ; }
5457
5558 public async Task Send ( WnsNotification notification )
5659 {
57- //See if we need an access token
58- if ( string . IsNullOrEmpty ( AccessToken ) )
59- await RenewAccessToken ( ) ;
60-
60+ // Get or renew our access token
61+ var accessToken = await AccessTokenManager . GetAccessToken ( ) ;
62+
6163 //https://cloud.notify.windows.com/?token=.....
6264 //Authorization: Bearer {AccessToken}
6365 //
6466
6567 http . DefaultRequestHeaders . TryAddWithoutValidation ( "X-WNS-Type" , string . Format ( "wns/{0}" , notification . Type . ToString ( ) . ToLower ( ) ) ) ;
66- //http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue ("Bearer", AccessToken);
67- http . DefaultRequestHeaders . TryAddWithoutValidation ( "Authorization" , "Bearer " + AccessToken ) ;
68+ http . DefaultRequestHeaders . TryAddWithoutValidation ( "Authorization" , "Bearer " + accessToken ) ;
6869
6970 if ( notification . RequestForStatus . HasValue )
7071 http . DefaultRequestHeaders . TryAddWithoutValidation ( "X-WNS-RequestForStatus" , notification . RequestForStatus . Value . ToString ( ) . ToLower ( ) ) ;
@@ -131,6 +132,12 @@ public async Task Send (WnsNotification notification)
131132 return ;
132133 }
133134
135+ //401
136+ if ( status . HttpStatus == HttpStatusCode . Unauthorized ) {
137+ AccessTokenManager . InvalidateAccessToken ( accessToken ) ;
138+ throw new RetryAfterException ( "Access token expired" , DateTime . UtcNow . AddSeconds ( 5 ) ) ;
139+ }
140+
134141 //404 or 410
135142 if ( status . HttpStatus == HttpStatusCode . NotFound || status . HttpStatus == HttpStatusCode . Gone ) {
136143 throw new DeviceSubscriptonExpiredException {
@@ -139,40 +146,11 @@ public async Task Send (WnsNotification notification)
139146 } ;
140147 }
141148
149+
142150 // Any other error
143151 throw new WnsNotificationException ( status ) ;
144152 }
145153
146- async Task RenewAccessToken ( )
147- {
148- var p = new Dictionary < string , string > {
149- { "grant_type" , "client_credentials" } ,
150- { "client_id" , Configuration . PackageSecurityIdentifier } ,
151- { "client_secret" , Configuration . ClientSecret } ,
152- { "scope" , "notify.windows.com" }
153- } ;
154-
155- var result = await http . PostAsync ( "https://login.live.com/accesstoken.srf" , new FormUrlEncodedContent ( p ) ) ;
156-
157- var data = await result . Content . ReadAsStringAsync ( ) ;
158-
159- var json = new JObject ( ) ;
160-
161- try { json = JObject . Parse ( data ) ; }
162- catch { }
163-
164- var accessToken = json . Value < string > ( "access_token" ) ;
165- var tokenType = json . Value < string > ( "token_type" ) ;
166-
167- if ( ! string . IsNullOrEmpty ( accessToken ) && ! string . IsNullOrEmpty ( tokenType ) ) {
168- AccessToken = accessToken ;
169- TokenType = tokenType ;
170- } else {
171- throw new UnauthorizedAccessException ( "Could not retrieve access token for the supplied Package Security Identifier (SID) and client secret" ) ;
172- }
173- }
174-
175-
176154 WnsNotificationStatus ParseStatus ( HttpResponseMessage resp , WnsNotification notification )
177155 {
178156 var result = new WnsNotificationStatus ( ) ;
0 commit comments