Asked  7 Months ago    Answers:  5   Viewed   19 times

If I get a JWT and I can decode the payload, how is that secure? Couldn't I just grab the token out of the header, decode and change the user information in the payload, and send it back with the same correct encoded secret?

I know they must be secure, but I just would really like to understand the technologies. What am I missing?

 Answers

45

JWTs can be either signed, encrypted or both. If a token is signed, but not encrypted, everyone can read its contents, but when you don't know the private key, you can't change it. Otherwise, the receiver will notice that the signature won't match anymore.

Answer to your comment: I'm not sure if I understand your comment the right way. Just to be sure: do you know and understand digital signatures? I'll just briefly explain one variant (HMAC, which is symmetrical, but there are many others).

Let's assume Alice wants to send a JWT to Bob. They both know some shared secret. Mallory doesn't know that secret, but wants to interfere and change the JWT. To prevent that, Alice calculates Hash(payload + secret) and appends this as signature.

When receiving the message, Bob can also calculate Hash(payload + secret) to check whether the signature matches. If however, Mallory changes something in the content, she isn't able to calculate the matching signature (which would be Hash(newContent + secret)). She doesn't know the secret and has no way of finding it out. This means if she changes something, the signature won't match anymore, and Bob will simply not accept the JWT anymore.

Let's suppose, I send another person the message {"id":1} and sign it with Hash(content + secret). (+ is just concatenation here). I use the SHA256 Hash function, and the signature I get is: 330e7b0775561c6e95797d4dd306a150046e239986f0a1373230fda0235bda8c. Now it's your turn: play the role of Mallory and try to sign the message {"id":2}. You can't because you don't know which secret I used. If I suppose that the recipient knows the secret, he CAN calculate the signature of any message and check if it's correct.

Tuesday, June 1, 2021
 
capsid
answered 7 Months ago
31

There are a number of workflows you can use here. Some examples are:

  1. Comment on the pull request, and have Bob make some changes. See Pull Request Discussion for more info.

  2. Merge the pull request onto a different branch, then make your changes before merging to master. You need to do this from the command line; see Merging a Pull Request for step-by-step instructions.

  3. Edit the patch before applying it with git am. See Patch and Apply. This is probably the most flexible option, but also the most manual.

    git checkout master
    curl http://github.com/<username>/<project_name>/pull/<patch_number>.patch
    sensible-editor <patchfile>
    git am <patchfile>
    git push origin master
    
Monday, August 9, 2021
 
Exoon
answered 4 Months ago
44

If you want to gets claims i.e, preferred_username you can get that from ClaimsPrincipal.

var user = User as ClaimsPrincipal;
string username = user.Claims.Where(c => c.Type == "preferred_username")
    .Select(x => x.Value).FirstOrDefault();

User will come from Claims. For that write

using System.Security.Claims;

It seems that User is not available in all versions. Another way to get claims will be something similar.

var prinicpal = (ClaimsPrincipal)Thread.CurrentPrincipal;
var email = prinicpal.Claims.Where(c => c.Type == ClaimTypes.Email)
    .Select(c => c.Value).SingleOrDefault();

Assign all the values for AuthenticationDTO.

public AuthenticationDTO DecodeToken(String Input)
{
    var key = Encoding.ASCII.GetBytes(HostConfig.SecurityKey);
    var handler = new JwtSecurityTokenHandler();
    var tokenSecure = handler.ReadToken(Input) as SecurityToken;
    var validations = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(key),
        ValidateIssuer = false,
        ValidateAudience = false
    };
    var claims = handler.ValidateToken(Input, validations, out tokenSecure);
    var prinicpal = (ClaimsPrincipal)Thread.CurrentPrincipal;
    if (principal is ClaimsPrincipal claims)
    {
         return new ApplicationDTO
             {
                 Id = claims.Claims.FirstOrDefault(x => x.Type == "sub")?.Value ?? "",
                 UserName = claims.Claims.FirstOrDefault(x => x.Type == "preferred_username")?.Value ?? "",
                 Email = claims.Claims.FirstOrDefault(x => x.Type == "email")?.Value ?? ""
             };
    }
    return null;
}
Wednesday, August 11, 2021
 
Manse
answered 4 Months ago
30

To generate a secret programatically you could use node's crypto.randomBytes()

var crypto = require('crypto');
var jwt = require('jsonwebtoken');

crypto.randomBytes(256, function(ex, buf) {
  if (ex) throw ex;
  var token = jwt.sign({foo: 'bar'}, buf);
  var decoded = jwt.verify(token, buf);
});

As for storing this, you're absolutely correct, you should definitely not store secrets in your source control. A better way would be to load such sensitive information from environment variables, eg process.env.MY_SECRET.

Another less common pattern I've seen is to load secrets from a file stored separate from your code. You could have your node app look for a JSON file in ~/.myapp/secrets.json for instance.

Saturday, September 4, 2021
 
Gerardo
answered 3 Months ago
38

After a lot of research and tests, I finally found that some properties names for TokenValidationParameters had changed and JwtSecurityTokenHandler.ValidateToken() method signature too.

So here's the modified working version of the above code.

private static void ValidateJwt(string jwt)
{
    var handler = new JwtSecurityTokenHandler();   
    var validationParameters = new TokenValidationParameters()
    {
        ValidAudience = "https://my-rp.com",
        IssuerSigningTokens = new List<X509SecurityToken>() { new X509SecurityToken(
           X509
           .LocalMachine
           .My
           .Thumbprint
           .Find("UYTUYTVV99999999999YTYYTYTY88888888", false)
           .First()) },
        ValidIssuer = "https://my-issuer.com/trust/issuer",
        CertificateValidator = X509CertificateValidator.None,
        RequireExpirationTime = true
    };

    try
    {
        SecurityToken validatedToken;
        var principal = handler.ValidateToken(jwt, validationParameters, out validatedToken);
    }
    catch (Exception e)
    {

        Console.WriteLine("{0}n {1}", e.Message, e.StackTrace);
    }

    Console.WriteLine();
}

And for the reference, the JwtSecurityTokenHandler lives in the System.IdentityModel.Tokens namespace. Don't forget to add the package "JSON Web Token Handler For the Microsoft .Net Framework 4.5" (version 4.0.0 at the time I write theses lines).

Hope it can save a few hours of search for some of you guys!

Monday, September 6, 2021
 
mariaoialvarez
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share