我已经浏览了大量的Google文档和SO Q / A,但没有运气。我想知道是否还有人按照谷歌的建议成功使用OpenId进行OpenId Connect迁移。
这就是我们过去做的事情:
IAuthenticationResponse response = _openid.GetResponse();
if (response != null) {
//omitted for brevity
} else {
IAuthenticationRequest req = _openid.CreateRequest("https://www.google.com/accounts/o8/id");
req.AddExtension(new ClaimsRequest
{
Country = DemandLevel.Request,
Email = DemandLevel.Request,
Gender = DemandLevel.Require,
PostalCode = DemandLevel.Require,
TimeZone = DemandLevel.Require
});
req.RedirectToProvider();
}
这是使用可追溯到几年的DotNetOpenAuth版本完成的。由于Google已弃用OpenId身份验证,因此我们正在尝试迁移到OpenID Connect。这里的关键问题是:我能以某种方式使用最新版本的DotNetOpenAuth库或任何其他方式获取OpenId标识符(以https://www.google.com/accounts/o8/id?id=xyz的形式)吗?
我已经尝试了最新的DotNetOpenAuth,我可以让它工作,但它给了我一个新的Id(这是预期的)。我也尝试使用这个URL的Javascript方式(换行符的换行符):
https://accounts.google.com/o/oauth2/auth?
scope=openid%20profile%20email
&openid.realm=http://localhost/palkkac/
&client_id=//here is the client id I created in google developer console
&redirect_uri=http://localhost/palkkac/someaspxpagehere
&response_type=id_token%20token
我检查了(使用Fiddler)我们当前使用旧的DotNetOpenAuth代码发送的领域值,它是http://localhost/palkkac/
。我把相同的域放在上面的url中。重定向网址以领域值开始,但不完全相同。
当我重定向到一个解析id_token并解密它的简单页面时(使用https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=zyx
端点),我得到了这个:
audience "client id is here"
email "mikkark@gmail.com"
expires_in 3597
issued_at //some numbers here
issued_to "client id is here"
issuer "accounts.google.com"
user_id "here is a sequence of numbers, my id in the OpenID Connect format that is"
verified_email true
所以没有你期望在这里找到的openid_id字段的迹象,尽管消息的整个结构似乎与Google文档不同,例如,没有标题为sub的字段。我想知道我是否真的使用了错误的端点,参数或什么?
我一直在阅读的是迁移指南:https://developers.google.com/accounts/docs/OpenID
。我跳过了第2步,因为它似乎是一个可选步骤。在第3步中讨论了openid_id字段,我希望首先将其作为概念验证。
我们在Google上注册了该应用,以便创建客户端ID等。现在还有许多允许的重定向网址以及Google开发者控制台中列出的javascript来源。请告诉我,如果这些可能会搞乱系统,我会将它们发布在此处进行审核。
旁注:我们应该将我们的应用程序移到严格防火墙的环境中,我们需要打开端口以便在服务器端执行此操作。因此,优先考虑使用客户端Javascript解决方案来访问Google并将结果重定向到服务器(除非存在其他与此相关的问题)。
关于同样的问题,关于SO还有其他资源,虽然所有这些似乎都使用服务器端的不同库来完成这项工作,似乎没有人尝试过使用Javascript:
答案 0 :(得分:2)
您可以使用GoogleAuthentication owin中间件。
app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions
{
SignInAsAuthenticationType = signAs,
AuthenticationType = "Google",
ClientId = "xxx.apps.googleusercontent.com",
ClientSecret = "xx",
CallbackPath = PathString.FromUriComponent("/oauth2callback"),
Provider = new GoogleOAuth2AuthenticationProvider
{
OnApplyRedirect = context =>
{
context.Response.Redirect(context.RedirectUri + "&openid.realm=https://mydomain.com/"); // DotNetOpenAuth by default add a trailing slash, it must be exactly the same as before
}
},
BackchannelHttpHandler = new MyWebRequestHandler()
}
然后,添加一个名为MyWebRequestHandler的新类:
public class MyWebRequestHandler : WebRequestHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var httpResponse = await base.SendAsync(request, cancellationToken);
if (request.RequestUri == new Uri("https://www.googleapis.com/plus/v1/people/me")) return httpResponse;
var configuration = await OpenIdConnectConfigurationRetriever.GetAsync("https://accounts.google.com/.well-known/openid-configuration", cancellationToken); // read the configuration to get the signing tokens (todo should be cached or hard coded)
// google is unclear as the openid_id is not in the access_token but in the id_token
// as the middleware dot not expose the id_token we need to parse it again
var jwt = httpResponse.Content.ReadAsStringAsync().Result;
JObject response = JObject.Parse(jwt);
string idToken = response.Value<string>((object)"id_token");
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
try
{
SecurityToken token;
var claims = tokenHandler.ValidateToken(idToken, new TokenValidationParameters()
{
ValidAudience = "xxx.apps.googleusercontent.com",
ValidIssuer = "accounts.google.com",
IssuerSigningTokens = configuration.SigningTokens
}, out token);
var claim = claims.FindFirst("openid_id");
// claim.Value will contain the old openid identifier
if (claim != null) Debug.WriteLine(claim.Value);
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
return httpResponse;
}
}
如果像我一样,你发现这不是很直白,请通过提出这个问题来帮助https://katanaproject.codeplex.com/workitem/359