Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(85)

Side by Side Diff: Src/GoogleApis.Auth/OAuth2/UserCredential.cs

Issue 94340043: Issue 463: Provide a signout\logout method (Closed) Base URL: https://google-api-dotnet-client.googlecode.com/hg/
Patch Set: Gus' comments Created 10 years, 2 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 Copyright 2013 Google Inc 2 Copyright 2013 Google Inc
3 3
4 Licensed under the Apache License, Version 2.0 (the "License"); 4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License. 5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at 6 You may obtain a copy of the License at
7 7
8 http://www.apache.org/licenses/LICENSE-2.0 8 http://www.apache.org/licenses/LICENSE-2.0
9 9
10 Unless required by applicable law or agreed to in writing, software 10 Unless required by applicable law or agreed to in writing, software
(...skipping 16 matching lines...) Expand all
27 27
28 namespace Google.Apis.Auth.OAuth2 28 namespace Google.Apis.Auth.OAuth2
29 { 29 {
30 /// <summary> 30 /// <summary>
31 /// OAuth 2.0 credential for accessing protected resources using an access t oken, as well as optionally refreshing· 31 /// OAuth 2.0 credential for accessing protected resources using an access t oken, as well as optionally refreshing·
32 /// the access token when it expires using a refresh token. 32 /// the access token when it expires using a refresh token.
33 /// </summary> 33 /// </summary>
34 public class UserCredential : IHttpExecuteInterceptor, IHttpUnsuccessfulResp onseHandler, 34 public class UserCredential : IHttpExecuteInterceptor, IHttpUnsuccessfulResp onseHandler,
35 IConfigurableHttpClientInitializer 35 IConfigurableHttpClientInitializer
36 { 36 {
37 private static readonly ILogger Logger = ApplicationContext.Logger.ForTy pe<UserCredential>(); 37 protected static readonly ILogger Logger = ApplicationContext.Logger.For Type<UserCredential>();
38 38
39 private TokenResponse token; 39 private TokenResponse token;
40 private object lockObject = new object(); 40 private object lockObject = new object();
41 41
42 /// <summary>Gets the token response which contains the access token.</s ummary> 42 /// <summary>Gets or sets the token response which contains the access t oken.</summary>
43 public TokenResponse Token 43 public TokenResponse Token
44 { 44 {
45 get 45 get
46 { 46 {
47 lock (lockObject) 47 lock (lockObject)
48 { 48 {
49 return token; 49 return token;
50 } 50 }
51 } 51 }
52 private set 52 set
53 { 53 {
54 lock (lockObject) 54 lock (lockObject)
55 { 55 {
56 token = value; 56 token = value;
57 } 57 }
58 } 58 }
59 } 59 }
60 60
61 /// <summary>Gets the authorization code flow.</summary>
62 public IAuthorizationCodeFlow Flow
63 {
64 get { return flow; }
65 }
66
67 /// <summary>Gets the user identity.</summary>
68 public string UderId
69 {
70 get { return userId; }
71 }
72
61 private readonly IAuthorizationCodeFlow flow; 73 private readonly IAuthorizationCodeFlow flow;
62 private readonly string userId; 74 private readonly string userId;
63 75
64 /// <summary>Constructs a new credential instance.</summary> 76 /// <summary>Constructs a new credential instance.</summary>
65 /// <param name="flow">Authorization code flow.</param> 77 /// <param name="flow">Authorization code flow.</param>
66 /// <param name="userId">User identifier.</param> 78 /// <param name="userId">User identifier.</param>
67 /// <param name="token">An initial token for the user.</param> 79 /// <param name="token">An initial token for the user.</param>
68 public UserCredential(IAuthorizationCodeFlow flow, string userId, TokenR esponse token) 80 public UserCredential(IAuthorizationCodeFlow flow, string userId, TokenR esponse token)
69 { 81 {
70 this.flow = flow; 82 this.flow = flow;
71 this.userId = userId; 83 this.userId = userId;
72 this.token = token; 84 this.token = token;
73 } 85 }
74 86
87 #region IHttpExecuteInterceptor
88
75 /// <summary> 89 /// <summary>
76 /// Default implementation is to try to refresh the access token if ther e is no access token or if we are 1· 90 /// Default implementation is to try to refresh the access token if ther e is no access token or if we are 1·
77 /// minute away from expiration. If token server is unavailable, it will try to use the access token even if· 91 /// minute away from expiration. If token server is unavailable, it will try to use the access token even if·
78 /// has expired. If successful, it will call <seealso cref="IAccessMetho d.Intercept"/>. 92 /// has expired. If successful, it will call <seealso cref="IAccessMetho d.Intercept"/>.
79 /// </summary> 93 /// </summary>
80 public async Task InterceptAsync(HttpRequestMessage request, Cancellatio nToken taskCancellationToken) 94 public async Task InterceptAsync(HttpRequestMessage request, Cancellatio nToken taskCancellationToken)
81 { 95 {
82 if (Token.IsExpired(flow.Clock)) 96 if (Token.IsExpired(flow.Clock))
83 { 97 {
84 Logger.Debug("Token has expired, trying to refresh it."); 98 Logger.Debug("Token has expired, trying to refresh it.");
85 if (!await RefreshTokenAsync(taskCancellationToken).ConfigureAwa it(false)) 99 if (!await RefreshTokenAsync(taskCancellationToken).ConfigureAwa it(false))
86 { 100 {
87 throw new InvalidOperationException("The access token has ex pired but we can't refresh it"); 101 throw new InvalidOperationException("The access token has ex pired but we can't refresh it");
88 } 102 }
89 } 103 }
90 104
91 flow.AccessMethod.Intercept(request, Token.AccessToken); 105 flow.AccessMethod.Intercept(request, Token.AccessToken);
92 } 106 }
93 107
108 #endregion
109
110 #region IHttpUnsuccessfulResponseHandler
111
112 public async Task<bool> HandleResponseAsync(HandleUnsuccessfulResponseAr gs args)
113 {
114 // TODO(peleyal): check WWW-Authenticate header.
115 if (args.Response.StatusCode == HttpStatusCode.Unauthorized)
116 {
117 return !Object.Equals(Token.AccessToken, flow.AccessMethod.GetAc cessToken(args.Request))
118 || await RefreshTokenAsync(args.CancellationToken).Configure Await(false);
119 }
120
121 return false;
122 }
123
124 #endregion
125
126 #region IConfigurableHttpClientInitializer
127
128 public void Initialize(ConfigurableHttpClient httpClient)
129 {
130 httpClient.MessageHandler.ExecuteInterceptors.Add(this);
131 httpClient.MessageHandler.UnsuccessfulResponseHandlers.Add(this);
132 }
133
134 #endregion
135
94 /// <summary> 136 /// <summary>
95 /// Refreshes the token by calling to <seealso cref="IAuthorizationCodeF low.RefreshTokenAsync"/>. Then it· 137 /// Refreshes the token by calling to <seealso cref="IAuthorizationCodeF low.RefreshTokenAsync"/>. Then it·
96 /// updates the <see cref="TokenResponse"/> with the new token instance. 138 /// updates the <see cref="TokenResponse"/> with the new token instance.
97 /// </summary> 139 /// </summary>
98 /// <param name="taskCancellationToken">Cancellation token to cancel an operation.</param> 140 /// <param name="taskCancellationToken">Cancellation token to cancel an operation.</param>
99 /// <returns><c>true</c> if the token was refreshed.</returns> 141 /// <returns><c>true</c> if the token was refreshed.</returns>
100 public async Task<bool> RefreshTokenAsync(CancellationToken taskCancella tionToken) 142 public async Task<bool> RefreshTokenAsync(CancellationToken taskCancella tionToken)
101 { 143 {
102 if (Token.RefreshToken == null) 144 if (Token.RefreshToken == null)
103 { 145 {
(...skipping 10 matching lines...) Expand all
114 156
115 if (newToken.RefreshToken == null) 157 if (newToken.RefreshToken == null)
116 { 158 {
117 newToken.RefreshToken = Token.RefreshToken; 159 newToken.RefreshToken = Token.RefreshToken;
118 } 160 }
119 161
120 Token = newToken; 162 Token = newToken;
121 return true; 163 return true;
122 } 164 }
123 165
124 public async Task<bool> HandleResponseAsync(HandleUnsuccessfulResponseAr gs args) 166 /// <summary>
167 /// Asynchronously revokes the token by calling
168 /// <see cref="Google.Apis.Auth.OAuth2.Flows.IAuthorizationCodeFlow.Revo keTokenAsync"/>.
169 /// </summary>
170 /// <param name="taskCancellationToken">Cancellation token to cancel an operation.</param>
171 /// <returns><c>true</c> if the token was revoked successfully.</returns >
172 public async Task<bool> RevokeTokenAsync(CancellationToken taskCancellat ionToken)
125 { 173 {
126 // TODO(peleyal): check WWW-Authenticate header. 174 if (Token == null)
127 if (args.Response.StatusCode == HttpStatusCode.Unauthorized)
128 { 175 {
129 return !Object.Equals(Token.AccessToken, flow.AccessMethod.GetAc cessToken(args.Request)) 176 Logger.Warning("Token is already null, no need to revoke it.");
130 || await RefreshTokenAsync(args.CancellationToken).Configure Await(false); 177 return false;
131 } 178 }
132 179
133 return false; 180 await flow.RevokeTokenAsync(userId, Token.AccessToken, taskCancellat ionToken).ConfigureAwait(false);
134 } 181 Logger.Info("Access token was revoked successfully");
135 182 // We don't set the token to null, cause we want that the next reque st (without reauthorizing) will fail).
136 public void Initialize(ConfigurableHttpClient httpClient) 183 return true;
137 {
138 httpClient.MessageHandler.ExecuteInterceptors.Add(this);
139 httpClient.MessageHandler.UnsuccessfulResponseHandlers.Add(this);
140 } 184 }
141 } 185 }
142 } 186 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b