我正在尝试升级我的MVC网站以使用新的OpenID Connect标准。OWIN中间件似乎非常健壮,但不幸的是只支持“form_post”响应类型。这意味着Google不兼容,因为它在“#”之后返回url中的所有令牌,因此它们永远不会到达服务器,也永远不会触发中间件。
我自己尝试过在中间件中触发响应处理程序,但似乎根本不起作用,所以我有一个简单的javascript文件,它解析出返回的声明,并将它们发送到控制器操作进行处理。
问题是,即使我在服务器端获取它们,也无法正确解析它们。我得到的错误看起来像这样:
IDX10500: Signature validation failed. Unable to resolve
SecurityKeyIdentifier: 'SecurityKeyIdentifier
(
IsReadOnly = False,
Count = 1,
Clause[0] = System.IdentityModel.Tokens.NamedKeySecurityKeyIdentifierClause
),
token: '{
"alg":"RS256",
"kid":"073a3204ec09d050f5fd26460d7ddaf4b4ec7561"
}.
{
"iss":"accounts.google.com",
"sub":"100330116539301590598",
"azp":"1061880999501-b47blhmmeprkvhcsnqmhfc7t20gvlgfl.apps.googleusercontent.com",
"nonce":"7c8c3656118e4273a397c7d58e108eb1",
"email_verified":true,
"aud":"1061880999501-b47blhmmeprkvhcsnqmhfc7t20gvlgfl.apps.googleusercontent.com",
"iat":1429556543,"exp\":1429560143
}'."
}
我的令牌验证码遵循好人开发身份服务器概述的例子
private async Task<IEnumerable<Claim>> ValidateIdentityTokenAsync(string idToken, string state)
{
// New Stuff
var token = new JwtSecurityToken(idToken);
var jwtHandler = new JwtSecurityTokenHandler();
byte[][] certBytes = getGoogleCertBytes();
for (int i = 0; i < certBytes.Length; i++)
{
var certificate = new X509Certificate2(certBytes[i]);
var certToken = new X509SecurityToken(certificate);
// Set up token validation
var tokenValidationParameters = new TokenValidationParameters();
tokenValidationParameters.ValidAudience = googleClientId;
tokenValidationParameters.IssuerSigningToken = certToken;
tokenValidationParameters.ValidIssuer = "accounts.google.com";
try
{
// Validate
SecurityToken jwt;
var claimsPrincipal = jwtHandler.ValidateToken(idToken, tokenValidationParameters, out jwt);
if (claimsPrincipal != null)
{
// Valid
idTokenStatus = "Valid";
}
}
catch (Exception e)
{
if (idTokenStatus != "Valid")
{
// Invalid?
}
}
}
return token.Claims;
}
private byte[][] getGoogleCertBytes()
{
// The request will be made to the authentication server.
WebRequest request = WebRequest.Create(
"https://www.googleapis.com/oauth2/v1/certs"
);
StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());
string responseFromServer = reader.ReadToEnd();
String[] split = responseFromServer.Split(':');
// There are two certificates returned from Google
byte[][] certBytes = new byte[2][];
int index = 0;
UTF8Encoding utf8 = new UTF8Encoding();
for (int i = 0; i < split.Length; i++)
{
if (split[i].IndexOf(beginCert) > 0)
{
int startSub = split[i].IndexOf(beginCert);
int endSub = split[i].IndexOf(endCert) + endCert.Length;
certBytes[index] = utf8.GetBytes(split[i].Substring(startSub, endSub).Replace("\\n", "\n"));
index++;
}
}
return certBytes;
}
我知道签名验证对于JWT来说并不是完全必要的,但我丝毫不知道如何关闭它。
微软的人员发布了支持 OpenId 连接的 Azure V2 B2C 预览版终结点的代码示例。请参阅此处,使用帮助程序类 OpenId 连接获取安全性提供代码简化如下:
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
AccessTokenFormat = new JwtFormat(new TokenValidationParameters
{
ValidAudiences = new[] { googleClientId },
}, new OpenIdConnectCachingSecurityTokenProvider("https://accounts.google.com/.well-known/openid-configuration"))});
这个类是必需的,因为OAuthBearer中间件不利用它。默认情况下,STS公开的OpenID连接元数据endpoint。
public class OpenIdConnectCachingSecurityTokenProvider : IIssuerSecurityTokenProvider
{
public ConfigurationManager<OpenIdConnectConfiguration> _configManager;
private string _issuer;
private IEnumerable<SecurityToken> _tokens;
private readonly string _metadataEndpoint;
private readonly ReaderWriterLockSlim _synclock = new ReaderWriterLockSlim();
public OpenIdConnectCachingSecurityTokenProvider(string metadataEndpoint)
{
_metadataEndpoint = metadataEndpoint;
_configManager = new ConfigurationManager<OpenIdConnectConfiguration>(metadataEndpoint);
RetrieveMetadata();
}
/// <summary>
/// Gets the issuer the credentials are for.
/// </summary>
/// <value>
/// The issuer the credentials are for.
/// </value>
public string Issuer
{
get
{
RetrieveMetadata();
_synclock.EnterReadLock();
try
{
return _issuer;
}
finally
{
_synclock.ExitReadLock();
}
}
}
/// <summary>
/// Gets all known security tokens.
/// </summary>
/// <value>
/// All known security tokens.
/// </value>
public IEnumerable<SecurityToken> SecurityTokens
{
get
{
RetrieveMetadata();
_synclock.EnterReadLock();
try
{
return _tokens;
}
finally
{
_synclock.ExitReadLock();
}
}
}
private void RetrieveMetadata()
{
_synclock.EnterWriteLock();
try
{
OpenIdConnectConfiguration config = _configManager.GetConfigurationAsync().Result;
_issuer = config.Issuer;
_tokens = config.SigningTokens;
}
finally
{
_synclock.ExitWriteLock();
}
}
}
问题是JWT中的孩子
,其值是密钥的密钥标识符,用于对JWT进行签名。由于您从JWKs URI手动构建证书数组,因此您会丢失密钥标识符信息。但是验证过程需要它。
您需要将令牌验证参数.颁发者签名密钥解析器
设置为一个函数,该函数将返回您在令牌验证参数
中设置的相同密钥。此委托的目的是指示运行时忽略任何“匹配”语义,只尝试键。
更多信息请参见本文:JwtSecurityTokenHandler 4.0.0重大变更?
编辑:代码:
tokenValidationParameters.IssuerSigningKeyResolver = (token, securityToken, kid, validationParameters) => { return new X509SecurityKey(certificate); };
我想我会发布使用JSON的稍微改进的版本。Net解析Google的X509证书,并根据“kid”(密钥id)匹配要使用的密钥。这比尝试每个证书更有效,因为非对称加密通常非常昂贵。
还删除了过时的 Web 客户端和手动字符串解析代码:
static Lazy<Dictionary<string, X509Certificate2>> Certificates = new Lazy<Dictionary<string, X509Certificate2>>( FetchGoogleCertificates );
static Dictionary<string, X509Certificate2> FetchGoogleCertificates()
{
using (var http = new HttpClient())
{
var json = http.GetStringAsync( "https://www.googleapis.com/oauth2/v1/certs" ).Result;
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>( json );
return dictionary.ToDictionary( x => x.Key, x => new X509Certificate2( Encoding.UTF8.GetBytes( x.Value ) ) );
}
}
JwtSecurityToken ValidateIdentityToken( string idToken )
{
var token = new JwtSecurityToken( idToken );
var jwtHandler = new JwtSecurityTokenHandler();
var certificates = Certificates.Value;
try
{
// Set up token validation
var tokenValidationParameters = new TokenValidationParameters();
tokenValidationParameters.ValidAudience = _clientId;
tokenValidationParameters.ValidIssuer = "accounts.google.com";
tokenValidationParameters.IssuerSigningTokens = certificates.Values.Select( x => new X509SecurityToken( x ) );
tokenValidationParameters.IssuerSigningKeys = certificates.Values.Select( x => new X509SecurityKey( x ) );
tokenValidationParameters.IssuerSigningKeyResolver = ( s, securityToken, identifier, parameters ) =>
{
return identifier.Select( x =>
{
if (!certificates.ContainsKey( x.Id ))
return null;
return new X509SecurityKey( certificates[ x.Id ] );
} ).First( x => x != null );
};
SecurityToken jwt;
var claimsPrincipal = jwtHandler.ValidateToken( idToken, tokenValidationParameters, out jwt );
return (JwtSecurityToken)jwt;
}
catch (Exception ex)
{
_trace.Error( typeof( GoogleOAuth2OpenIdHybridClient ).Name, ex );
return null;
}
}
使用OpenAM OpenID连接代理,我创建了一个名为Test-Client的OAuth 2.0/OpenID连接客户端,其作用域为openid。 我的OpenAM实例部署在Tomcat 7上,我调整了/etc/hosts文件,将localhost显示为OpenAM。实例通用域名格式。 使用默认凭据,我可以使用以下方式检索OpenID Connect id令牌: 然后,如果我的承载令牌仍然有效,
我得到例外: 签名异常java.security.signatureException:签名长度不正确:得到294,但预期为256 因此,我成功地生成了bu在: 参考:谷歌播放订单ID更新为新格式 DefaultSignatureValidator.class: 有什么想法如何验证它吗?
我正在遵循官方的Google身份验证流程。我的应用程序已经使用了最新版本的Google地图。 项目 应用程序 地图下方有一条红线,弹出窗口显示找到了11.8.0和11.4.2。构建错误消息如下:, 错误:任务“:应用程序:进程”的执行失败。 请通过更新谷歌服务插件的版本来修复版本冲突(有关最新版本的信息,请访问https://bintray.com/android/android-tools/co
接下来,我生成了自己的OAuth2客户机ID并使用它。这种方法很简单,直到我开始收到来自Google的“匿名使用过期”错误,一段时间后我意识到这是因为密钥没有启用只读日历范围。 我的下一个想法是公开日历,并使用静态API密钥,但日历是从一个名为Peak Pro的预订服务中同步的,该服务用参加活动的客户的姓名、电子邮件和电话号码填充日历描述。我不能公开揭露那些。 接下来,我被吸引到了CalDAV A
请帮帮我! 我到处找,但还是不明白。 我有域domain1.com,我想访问我的项目-快速启动-111111的“https://www.googleapis.com/auth/spreadsheetshttps://www.googleapis.com/auth/drive”范围。 我已经添加了我的域名,并通过DNS TXT记录进行验证 问题是为什么谷歌说“应用程序未验证”。我在哪里可以验证它?
我们正在做一个项目,这个项目依赖PSA (0.2.1)与google oauth2(离线)进行认证。不知何故,我们失去了一些用户的刷新令牌,我们想迫使这些用户重新认证,以便我们可以从谷歌获得新的刷新令牌 我们尝试了两者: 去连接那些使用 /diconnect/google-oauth2的用户,我们得到了一个NotAllo的断开连接异常,即使从中删除了,我们也没有得到异常,但是当用户重新认证时,go