如何使用对称密钥配置Microsoft智威汤逊?(How to configure MIcrosof

2019-07-19 10:43发布

我想我的配置ASP.NET应用程序接受JSON网络令牌(JWT)是用对称密钥签署。 该STS是不能够使用证书进行如此,所以我们使用了对称密钥的支持。

在我结束,我使用微软的JWT开发者预览版 。 不幸的是,我还没有看到如何使用与对称密钥的任何实例。 一些周围挖有各种工具后,我发现NamedKeyIssuerTokenResolver ,发现我可以配置它使用对称密钥。 例如:

<securityTokenHandlers>
  <add type="Microsoft.IdentityModel.Tokens.JWT.JWTSecurityTokenHandler,Microsoft.IdentityModel.Tokens.JWT" />
  <securityTokenHandlerConfiguration>
    <certificateValidation certificateValidationMode="PeerTrust" />
    <issuerTokenResolver
      type="Microsoft.IdentityModel.Tokens.JWT.NamedKeyIssuerTokenResolver,
        Microsoft.IdentityModel.Tokens.JWT">
      <securityKey
          symmetricKey="+zqf97FD/xyzzyplugh42ploverFeeFieFoeFooxqjE="
             name="https://localhost/TestRelyingParty" />
    </issuerTokenResolver>
  </securityTokenHandlerConfiguration>
</securityTokenHandlers>

我不完全知道什么我应该使用的name出现。 它应该是观众开放的,也许是发行人乌里? 在任何情况下,我知道,如果我不包括name ,我得到一个异常时,我的程序启动,因为securityKey元素要求的属性。

无论如何,这仍然没有解决问题。 之后,我对STS进行身份验证,我得到以下异常:

[SecurityTokenValidationException: JWT10310: Unable to validate signature. validationParameters.SigningTokenResolver type: 'Microsoft.IdentityModel.Tokens.JWT.NamedKeyIssuerTokenResolver', was unable to resolve key to a token.
The SecurityKeyIdentifier is: 
'SecurityKeyIdentifier
    (
    IsReadOnly = False,
    Count = 1,
    Clause[0] = Microsoft.IdentityModel.Tokens.JWT.NamedKeyIdentifierClause
    )
'. validationParameters.SigningToken was null.]
   Microsoft.IdentityModel.Tokens.JWT.JWTSecurityTokenHandler.ValidateSignature(JWTSecurityToken jwt, TokenValidationParameters validationParameters) +2111
   Microsoft.IdentityModel.Tokens.JWT.JWTSecurityTokenHandler.ValidateToken(JWTSecurityToken jwt, TokenValidationParameters validationParameters) +138
   Microsoft.IdentityModel.Tokens.JWT.JWTSecurityTokenHandler.ValidateToken(SecurityToken token) +599
   System.IdentityModel.Tokens.SecurityTokenHandlerCollection.ValidateToken(SecurityToken token) +135
   System.IdentityModel.Services.TokenReceiver.AuthenticateToken(SecurityToken token, Boolean ensureBearerToken, String endpointUri) +117
   System.IdentityModel.Services.WSFederationAuthenticationModule.SignInWithResponseMessage(HttpRequestBase request) +698
   System.IdentityModel.Services.WSFederationAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs args) +123924
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +165

我失去了一些其他的配置步骤? 我是不是把错误的东西在name属性? 或者,这是在JWT开发者预览版中的已知错误?

Answer 1:

更新2014年2月13日:

正如下面@leastprivilege指出,这种情况很容易与智威汤逊的RTM版本一大堆。 我强烈建议你忽略了这一点,并提供他的例子去http://leastprivilege.com/2013/07/16/identityserver-using-ws-federation-with-jwt-tokens-and-symmetric-signatures/ 。

请注意,下面原来答案是为测试版,Microsoft.IdentityModel.Tokens.JWT。 升级到的版本,System.IdentityModel.Tokens.Jwt,需要一点点更多的工作。 见下文。

首要问题原来是,该方法JWTSecurityTokenHandler.ValidateToken(token)不完全填充TokenValidationParameters它传递到JWTSecurityTokenHandler.ValidateToken(token, validationParameters) 特别是,它不填充SigningToken构件或ValidIssuers (或ValidIssuer )。

有趣的是,我的配置显示在我原来的问题实际上是由令牌解析器加载,并且可在运行时,你可以在下面的代码中看到。

我不知道如何指定配置文件中的有效发行的字符串,虽然。 我强烈怀疑有把这些信息的地方,但我还没有想通了属于它的地方。

我的问题的解决方案是创建一个自定义的安全令牌处理程序,它派生自JWTSecurityTokenHandler 。 重写ValidateToken(token, validationParameters)使我有机会来设置这些,我需要的参数,然后调用基类的ValidateToken方法。

public class CustomJwtSecurityTokenHandler: JWTSecurityTokenHandler
{
    // Override ValidateSignature so that it gets the SigningToken from the configuration if it doesn't exist in
    // the validationParameters object.
    private const string KeyName = "https://localhost/TestRelyingParty";
    private const string ValidIssuerString = "https://mySTSname/trust";
    public override ClaimsPrincipal ValidateToken(JWTSecurityToken jwt, TokenValidationParameters validationParameters)
    {
        // set up valid issuers
        if ((validationParameters.ValidIssuer == null) &&
            (validationParameters.ValidIssuers == null || !validationParameters.ValidIssuers.Any()))
        {
            validationParameters.ValidIssuers = new List<string> {ValidIssuerString};
        }
        // and signing token.
        if (validationParameters.SigningToken == null)
        {
            var resolver = (NamedKeyIssuerTokenResolver)this.Configuration.IssuerTokenResolver;
            if (resolver.SecurityKeys != null)
            {
                List<SecurityKey> skeys;
                if (resolver.SecurityKeys.TryGetValue(KeyName, out skeys))
                {
                    var tok = new NamedKeySecurityToken(KeyName, skeys);
                    validationParameters.SigningToken = tok;
                }
            }
        }
        return base.ValidateToken(jwt, validationParameters);
    }
}

在我的web.config,我不得不改变安全令牌处理程序:

  <securityTokenHandlers>
    <!--<add type="Microsoft.IdentityModel.Tokens.JWT.JWTSecurityTokenHandler,Microsoft.IdentityModel.Tokens.JWT" />-->
    <!-- replaces the default JWTSecurityTokenHandler -->
    <add type="TestRelyingParty.CustomJwtSecurityTokenHandler,TestRelyingParty" />

没有像花三四天研究是解决了的代码一对夫妇十几行的问题。 。 。

另外新版本

在2013年6月,微软正式发布了智威汤逊。 他们改变了命名空间System.IdentityModel.Tokens.Jwt。 升级到在此之后,上述解决方案停止工作。 得到它的工作,我有以下添加到我的CustomJwtSecurityTokenHandler 。 这是除了现有的代码。

public override ClaimsPrincipal ValidateToken(JwtSecurityToken jwt)
{
    var vparms = new TokenValidationParameters
        {
            AllowedAudiences = Configuration.AudienceRestriction.AllowedAudienceUris.Select(s => s.ToString())
        };
    return ValidateToken(jwt, vparms);
}


Answer 2:

下面是这个库与.NET 4.5的问题有关的使用实例和验证一个JWT基于HMAC SHA256(所有代码和不WIF)对称密钥签署:

string jwtIssuer = "MyIssuer";
string jwtAudience = "MyAudience";

// Generate symmetric key for HMAC-SHA256 signature
RNGCryptoServiceProvider cryptoProvider = new RNGCryptoServiceProvider();
byte[] keyForHmacSha256 = new byte[64];
cryptoProvider.GetNonZeroBytes(keyForHmacSha256);

///////////////////////////////////////////////////////////////////
// Create signing credentials for the signed JWT.
// This object is used to cryptographically sign the JWT by the issuer.
SigningCredentials sc = new SigningCredentials(
                                new InMemorySymmetricSecurityKey(keyForHmacSha256),
                                "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256",
                                "http://www.w3.org/2001/04/xmlenc#sha256");

///////////////////////////////////////////////////////////////////
// Create token validation parameters for the signed JWT
// This object will be used to verify the cryptographic signature of the received JWT
TokenValidationParameters validationParams =
    new TokenValidationParameters()
    {
        AllowedAudience = s_jwtAudience,
        ValidIssuer = s_jwtIssuer,
        ValidateExpiration = true,
        ValidateNotBefore = true,
        ValidateIssuer = true,
        ValidateSignature = true,
        SigningToken = new BinarySecretSecurityToken(keyForHmacSha256),
    };

///////////////////////////////////////////////////////////////////
// Create JWT handler
// This object is used to write/sign/decode/validate JWTs
JWTSecurityTokenHandler jwtHandler = new JWTSecurityTokenHandler();

// Create a simple JWT claim set
IList<Claim> payloadClaims = new List<Claim>() { new Claim("clm1", "clm1 value"), };

// Create a JWT with signing credentials and lifetime of 12 hours
JWTSecurityToken jwt =
    new JWTSecurityToken(jwtIssuer, jwtAudience, payloadClaims, sc, DateTime.UtcNow, DateTime.UtcNow.AddHours(12.0));

// Serialize the JWT
// This is how our JWT looks on the wire: <Base64UrlEncoded header>.<Base64UrlEncoded body>.<signature>
string jwtOnTheWire = jwtHandler.WriteToken(jwt);

// Validate the token signature (we provide the shared symmetric key in `validationParams`)
// This will throw if the signature does not validate
jwtHandler.ValidateToken(jwtOnTheWire, validationParams);

// Parse JWT from the Base64UrlEncoded wire form (<Base64UrlEncoded header>.<Base64UrlEncoded body>.<signature>)
JWTSecurityToken parsedJwt = jwtHandler.ReadToken(jwtOnTheWire) as JWTSecurityToken;


Answer 3:

吉姆

感谢您试用预览,遗憾的是,你有这样的不明显:-(一些问题。

NamedKeyIssuerTokenResolver从两个想法诞生了:

  1. 需要一个关键的检查是共享秘密的签名进行关联;
  2. 多个有效密钥可能是在同一时间使用。

它被设计与合作NamedKeySecurityToken有一个名字和数字键的。 该NKITR可以返回NKST当多个键在起作用从而简化了检查签名。

为一个目标NKITR是提供所述JWT之间的映射iss权利要求(在报头)和密钥。 当它的时间来检查签名的JWTHandler检查:

  1. TokenValidationParamerter.SigningToken ,如果发现使用它;
  2. SecurityKeyIdentifier从获得JWT.Header.SigningKeyIdentifier (目前仅x5t支持)被发送到当前的INR ;
  3. 一个NamedKeyIdentifierClause从创建Jwt.Issuer和发送给当前INR

由于SecurityToken可以包含多个键,每个键一个为了用于检查,首先成功停止签名和JWT.SigningToken将包含SecurityToken审定签名。

吉姆和威利,

遗憾与混乱ValidateToken(SecurityToken)过载的方法。 参数从移动ConfigurationValidationParameters ,但不喜欢的属性ValidIssuer有一个单一的项目,但

IssuerNameRegistry -> VP.IssuerNameRegistry
IssuerTokenResolver -> VP.SigningTokenResolver
AllowedAudienceUris -> VP.AllowedAudiences
CertificateValidator -> VP.CertificateValidator
SaveBootStrapContext -> VP.SaveBootStrapContext

黑雁



Answer 4:

据我所知,该JWtSecurityTokenHandler还没有准备好从一个配置文件中。 维托里奥Bertocci给出的例子也是“代码示例”。 在这方面,他明确地包含做验证(如对称密钥)所需的所有东西附加tokenValidationParameters参数调用重载ValidateToken。
不幸的是,超载不是由正常的Wif管道(它只是令牌作为参数调用ValidateToken)我决心继承了jwtsecurity标记处理程序,覆盖LoadCustomConfiguration手动加载创建tokenValidationParemeter对象所需的东西叫(我有为此创造一些配置对象)。 然后我做了validateToken的覆盖,以显式调用带有附加参数(这我可以与我从配置读取参数动态创建)的过载。 一切都非常繁琐的事,但只有这样才能进军tokenValidationparameters的力量。 (但我可能是错的,当然)

  <issuerTokenResolver type="Microsoft.IdentityModel.Tokens.JWT.NamedKeyIssuerTokenResolver, Microsoft.IdentityModel.Tokens.JWT">
    <securityKey symmetricKey="01234567890123456789012345678901" name="MyIssuer"/>
  </issuerTokenResolver>
  <securityTokenHandlers>


Answer 5:

下面是它如何与JWT处理程序的RTM版本的工作原理: http://leastprivilege.com/2013/07/16/identityserver-using-ws-federation-with-jwt-tokens-and-symmetric-signatures/



文章来源: How to configure MIcrosoft JWT with symmetric key?
标签: .net wif jwt