如何延长使用刷新令牌访问令牌? [英] How to renew the access token using the refresh token?
问题描述
我使用的 ASP.NET MVC 5 是 OWIN
我已经做了很多研究,并没有发现如何使用刷新令牌续订访问令牌。
我的情况是:第一次用户访问我的应用程序,他或她将访问权限授予我读API返回的刷新令牌的帐户。当用户回来我的应用程序,我需要的基础上,刷新令牌。
刷新访问令牌任何人可以提供一些code?
这里是我所取得的成绩至今:
Startup.Auth.cs:
VAR googleOAuth2AuthenticationOptions =新GoogleOAuth2AuthenticationOptions
{
标题=Google+的
客户端Id = Parameters.Instance.Authentication.oAuth.GooglePlus.ClientId,
ClientSecret = Parameters.Instance.Authentication.oAuth.GooglePlus.ClientSecret,
CallbackPath =新PathString(/ OAuth的登录回报),
供应商=新GoogleOAuth2AuthenticationProvider
{
OnAuthenticated =异步上下文=>
{
context.Identity.AddClaim(新索赔(ClaimTypes.Name,context.Identity.FindFirstValue(ClaimTypes.Name)));
context.Identity.AddClaim(新索赔(ClaimTypes.Email,context.Identity.FindFirstValue(ClaimTypes.Email)));
context.Identity.AddClaim(新索赔(图片,context.User.GetValue(图片)的ToString()));
context.Identity.AddClaim(新索赔(配置文件,context.User.GetValue(档案)的ToString()));
context.Identity.AddClaim(
新的索赔(Parameters.Instance.Authentication.oAuth.GooglePlus.AccessTokenClaimType,
context.AccessToken));
}
}
};
googleOAuth2AuthenticationOptions.Scope.Add(https://www.googleapis.com/auth/plus.login);
googleOAuth2AuthenticationOptions.Scope.Add(https://www.googleapis.com/auth/userinfo.email);
AuthenticationController:
[HttpPost]
[使用AllowAnonymous]
公众的ActionResult ExternalLogin(字符串提供商,串RETURNURL)
{
RedirectIfAuthenticated(); 返回新ChallengeResult(供应商,Url.Content(〜/ OAuth的登录回调));
}[ActionName(OAuth的登录回)]
公共异步任务<&的ActionResult GT; ExternalLoginCallback(字符串RETURNURL)
{
}//用于保护XSRF添加外部登录时
私人常量字符串XsrfKey =XsrfId;私人IAuthenticationManager的AuthenticationManager
{
得到
{
返回HttpContext.GetOwinContext()认证。
}
}私有类ChallengeResult:HttpUnauthorizedResult
{
公共ChallengeResult(字符串提供商,串redirectUri)
:这个(供应商,redirectUri,NULL)
{
} 私人ChallengeResult(字符串提供商,串redirectUri,字符串userid)
{
LoginProvider =供应商;
RedirectUri = redirectUri;
用户ID =用户id;
} 私人字符串LoginProvider {搞定;组; } 私人字符串RedirectUri {搞定;组; } 私人字符串userid {搞定;组; } 公共覆盖无效的ExecuteReuslt(ControllerContext上下文)
{
VAR性能=新AuthenticationProperties {RedirectUri = RedirectUri};
如果(用户ID!= NULL)
{
properties.Dictionary [XsrfKey] =用户ID;
}
。context.HttpContext.GetOwinContext()Authentication.Challenge(属性,LoginProvider);
}
}
这问题是不能重复的。我希望这种帮助别人不花钱的日子就像我花了。
在近4天,我已经找到了如何让使用OWIN谷歌的API一个新的访问令牌。
我要发布的解决方案,但首先,我要说的是什么帮助我开始得到关于我的错误是为武士刀项目设置调试符号线索。请参阅此链接:
<一href=\"http://www.symbolsource.org/Public/Home/VisualStudio\">http://www.symbolsource.org/Public/Home/VisualStudio
这形象展示如何配置调试符号服务器。
而这其中显示正在加载的武士刀调试符号。
在这之后,我发现我的问题是,谷歌API是返回403:禁止
访问未配置。请使用谷歌开发者控制台启用API为您的项目
然后,堆栈溢出这个帖子发现:
<一href=\"http://stackoverflow.com/questions/21014129/access-not-configured-please-use-google-developers-console-to-activate-the-api\">"Access未配置。请使用谷歌开发者控制台启用API为您的项目&QUOT;。
更具体地说这样的回答: http://stackoverflow.com/a/24401189/833846
在那之后,我去了谷歌开发者控制台和设置在Google+ API
然后,voillá!它的工作。
现在,code使用刷新令牌获取新的访问令牌(我还没有发现任何的方式来完成,使用的OWIN API)。
公共静态类TokenValidator
{
///&LT;总结&gt;
///Obtém嗯从头访问令牌呐API做谷歌。
///&LT; /总结&gt;
///&LT; PARAM NAME =的clientId&GT;&LT; /参数&GT;
///&LT; PARAM NAME =clientSecret&GT;&LT; /参数&GT;
///&LT; PARAM NAME =refreshToken&GT;&LT; /参数&GT;
///&LT;&回报GT;&LT; /回报&GT;
公共静态GoogleRefreshTokenModel ValidateGoogleToken(字符串客户端ID,字符串clientSecret,串refreshToken)
{
常量字符串URL =https://accounts.google.com/o/oauth2/token; VAR参数=新的List&LT; KeyValuePair&LT;字符串,字符串&GT;&GT;
{
新KeyValuePair&LT;字符串,字符串&GT;(CLIENT_ID的clientId)
新KeyValuePair&LT;字符串,字符串&GT;(client_secret,clientSecret)
新KeyValuePair&LT;字符串,字符串&GT;(grant_type,refresh_token),
新KeyValuePair&LT;字符串,字符串&GT;(refresh_token,refreshToken)
}; VAR内容= GetContentAsync(URL,POST,参数); VAR令牌= JsonConvert.DeserializeObject&LT; GoogleRefreshTokenModel&GT;(内容); 返回记号。
} 私人静态字符串GetContentAsync(字符串URL,
字符串的方法=POST
IEnumerable的&LT; KeyValuePair&LT;字符串,字符串&GT;&GT;参数= NULL)
{
返回方法==POST? PostAsync(URL参数):GetAsync(URL,参数);
} 私人静态字符串PostAsync(字符串URL,IEnumerable的&LT; KeyValuePair&LT;字符串,字符串&GT;&GT;参数= NULL)
{
VAR URI =新的URI(URL); VAR请求= WebRequest.Create(URI)为HttpWebRequest的;
request.Method =POST;
request.KeepAlive = TRUE;
request.ContentType =应用/的X WWW的形式urlen codeD; 变种postParameters = GetPostParameters(参数); 变种BS = Encoding.UTF8.GetBytes(postParameters);
使用(VAR reqStream = request.GetRequestStream())
{
reqStream.Write(BS,0,bs.Length);
} 使用(VAR响应= request.GetResponse())
{
VAR SR =新的StreamReader(response.GetResponseStream());
变种jsonResponse = sr.ReadToEnd();
sr.Close(); 返回jsonResponse;
}
} 私人静态字符串GetPostParameters(IEnumerable的&LT; KeyValuePair&LT;字符串,字符串&GT;&GT;参数= NULL)
{
VAR postParameters =的String.Empty;
的foreach(在参数变量参数)
{
postParameters + =的String.Format(与&amp; {0} = {1},parameter.Key,
HttpUtility.HtmlEn code(parameter.Value));
}
postParameters = postParameters.Substring(1); 返回postParameters;
} 私人静态字符串GetAsync(字符串URL,IEnumerable的&LT; KeyValuePair&LT;字符串,字符串&GT;&GT;参数= NULL)
{
网址+ =? + GetQueryStringParameters(参数); VAR forIdsWebRequest = WebRequest.Create(URL);
使用(VAR响应=(HttpWebResponse)forIdsWebRequest.GetResponse())
{
使用(VAR数据= response.GetResponseStream())
使用(VAR读者=新的StreamReader(数据))
{
变种jsonResponse = reader.ReadToEnd(); 返回jsonResponse;
}
}
} 私人静态字符串GetQueryStringParameters(IEnumerable的&LT; KeyValuePair&LT;字符串,字符串&GT;&GT;参数= NULL)
{
VAR queryStringParameters =的String.Empty;
的foreach(在参数变量参数)
{
queryStringParameters + =的String.Format(与&amp; {0} = {1},parameter.Key,
HttpUtility.HtmlEn code(parameter.Value));
}
queryStringParameters = queryStringParameters.Substring(1); 返回queryStringParameters;
}
}
重要1::要获得刷新令牌,你必须设置ACCESS_TYPE到线下中的的ExecuteReuslt 的方法,这种方式:
properties.Dictionary [ACCESS_TYPE] =离线;
重要2:一旦你得到你的刷新令牌,则必须存放在一些安全的源头。谷歌API不会发出你一个新的刷新令牌,除非你调用线(在同一个方法)之前设置approval_prompt到力:
context.HttpContext.GetOwinContext()Authentication.Challenge(属性,LoginProvider);
我还建议采取一看:
I am using ASP.NET MVC 5 with OWIN.
I have done a lot of research and haven't found how to renew the access token using the refresh token.
My scenario is: The first time the user accesses my app, he or she grants access to the account I read the refresh token returned from the API. When the users come back to my app, I need to refresh the access token based on the "Refresh Token".
Could anybody provide some code?
Here is what I've achieved till now:
Startup.Auth.cs:
var googleOAuth2AuthenticationOptions = new GoogleOAuth2AuthenticationOptions
{
Caption = "Google+",
ClientId = Parameters.Instance.Authentication.oAuth.GooglePlus.ClientId,
ClientSecret = Parameters.Instance.Authentication.oAuth.GooglePlus.ClientSecret,
CallbackPath = new PathString("/oauth-login-return"),
Provider = new GoogleOAuth2AuthenticationProvider
{
OnAuthenticated = async context =>
{
context.Identity.AddClaim(new Claim(ClaimTypes.Name, context.Identity.FindFirstValue(ClaimTypes.Name)));
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Identity.FindFirstValue(ClaimTypes.Email)));
context.Identity.AddClaim(new Claim("picture", context.User.GetValue("picture").ToString()));
context.Identity.AddClaim(new Claim("profile", context.User.GetValue("profile").ToString()));
context.Identity.AddClaim(
new Claim(Parameters.Instance.Authentication.oAuth.GooglePlus.AccessTokenClaimType,
context.AccessToken));
}
}
};
googleOAuth2AuthenticationOptions.Scope.Add("https://www.googleapis.com/auth/plus.login");
googleOAuth2AuthenticationOptions.Scope.Add("https://www.googleapis.com/auth/userinfo.email");
AuthenticationController:
[HttpPost]
[AllowAnonymous]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
RedirectIfAuthenticated();
return new ChallengeResult(provider, Url.Content("~/oauth-login-callback"));
}
[ActionName("oauth-login-back")]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
}
// Used for XSRF protection when adding external logins
private const string XsrfKey = "XsrfId";
private IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.GetOwinContext().Authentication;
}
}
private class ChallengeResult : HttpUnauthorizedResult
{
public ChallengeResult(string provider, string redirectUri)
: this(provider, redirectUri, null)
{
}
private ChallengeResult(string provider, string redirectUri, string userId)
{
LoginProvider = provider;
RedirectUri = redirectUri;
UserId = userId;
}
private string LoginProvider { get; set; }
private string RedirectUri { get; set; }
private string UserId { get; set; }
public override void ExecuteResult(ControllerContext context)
{
var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
if (UserId != null)
{
properties.Dictionary[XsrfKey] = UserId;
}
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}
}
This question isn't duplicate AT ALL. I hope this help others not spending days like I have spent.
After almost 4 days I have found out how to get a fresh access token in the google api using OWIN.
I'm going to post the solution, but first, I MUST say that what helped me to start getting a clue about my error was setting up the Debug Symbols for the Katana project. See this link: http://www.symbolsource.org/Public/Home/VisualStudio
This image show how to configure Debug Symbols Servers.
And this one shows the Katana Debug Symbols being loaded.
After that, I found out that my problem was that Google API was returning 403: Forbidden
"Access Not Configured. Please use Google Developers Console to activate the API for your project"
Then, found on stack overflow this post: "Access Not Configured. Please use Google Developers Console to activate the API for your project."
more specifically this Answer: http://stackoverflow.com/a/24401189/833846
After that, I went to Google Developers Console and setup up Google+ API
And then, voillá! It worked.
Now, the code to get a fresh access token using the refresh token (I haven't found any way to accomplish that using the OWIN API).
public static class TokenValidator
{
/// <summary>
/// Obtém um novo access token na API do google.
/// </summary>
/// <param name="clientId"></param>
/// <param name="clientSecret"></param>
/// <param name="refreshToken"></param>
/// <returns></returns>
public static GoogleRefreshTokenModel ValidateGoogleToken(string clientId, string clientSecret, string refreshToken)
{
const string url = "https://accounts.google.com/o/oauth2/token";
var parameters = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("client_id", clientId),
new KeyValuePair<string, string>("client_secret", clientSecret),
new KeyValuePair<string, string>("grant_type", "refresh_token"),
new KeyValuePair<string, string>("refresh_token", refreshToken)
};
var content = GetContentAsync(url, "POST", parameters);
var token = JsonConvert.DeserializeObject<GoogleRefreshTokenModel>(content);
return token;
}
private static string GetContentAsync(string url,
string method = "POST",
IEnumerable<KeyValuePair<string, string>> parameters = null)
{
return method == "POST" ? PostAsync(url, parameters) : GetAsync(url, parameters);
}
private static string PostAsync(string url, IEnumerable<KeyValuePair<string, string>> parameters = null)
{
var uri = new Uri(url);
var request = WebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";
request.KeepAlive = true;
request.ContentType = "application/x-www-form-urlencoded";
var postParameters = GetPostParameters(parameters);
var bs = Encoding.UTF8.GetBytes(postParameters);
using (var reqStream = request.GetRequestStream())
{
reqStream.Write(bs, 0, bs.Length);
}
using (var response = request.GetResponse())
{
var sr = new StreamReader(response.GetResponseStream());
var jsonResponse = sr.ReadToEnd();
sr.Close();
return jsonResponse;
}
}
private static string GetPostParameters(IEnumerable<KeyValuePair<string, string>> parameters = null)
{
var postParameters = string.Empty;
foreach (var parameter in parameters)
{
postParameters += string.Format("&{0}={1}", parameter.Key,
HttpUtility.HtmlEncode(parameter.Value));
}
postParameters = postParameters.Substring(1);
return postParameters;
}
private static string GetAsync(string url, IEnumerable<KeyValuePair<string, string>> parameters = null)
{
url += "?" + GetQueryStringParameters(parameters);
var forIdsWebRequest = WebRequest.Create(url);
using (var response = (HttpWebResponse)forIdsWebRequest.GetResponse())
{
using (var data = response.GetResponseStream())
using (var reader = new StreamReader(data))
{
var jsonResponse = reader.ReadToEnd();
return jsonResponse;
}
}
}
private static string GetQueryStringParameters(IEnumerable<KeyValuePair<string, string>> parameters = null)
{
var queryStringParameters = string.Empty;
foreach (var parameter in parameters)
{
queryStringParameters += string.Format("&{0}={1}", parameter.Key,
HttpUtility.HtmlEncode(parameter.Value));
}
queryStringParameters = queryStringParameters.Substring(1);
return queryStringParameters;
}
}
IMPORTANT 1: To get a refresh token you must set the "access_type" to "offline" in the "ExecuteResult" method, this way:
properties.Dictionary["access_type"] = "offline";
IMPORTANT 2: Once you get your refresh token, you must store it and in some secure source. Google API won't issue you a new refresh token, unless you set "approval_prompt" to "force" before you call the line (in the same method):
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
I also recommend taking a look at:
这篇关于如何延长使用刷新令牌访问令牌?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!