This is my decode method written in python:
import base64
from flask import request, jsonify
import jwt
from jwt.exceptions import InvalidTokenError
from config import SECRET_KEY
def authenticate_token(func, require_premium=False):
"""
:param require_premium: True if the endpoint is only for premium users
:param func: the function that is being wrapped around
:return: returns the wrapped function itself
"""
def wrapper(*args, **kwargs):
token = request.headers.get('Authorization')
print(token)
if not token:
return jsonify(message='Authorization token is missing'), 401
# encoded_secret = base64.urlsafe_b64encode(SECRET_KEY.encode('utf-8'))
try:
encoded_secret = base64.urlsafe_b64encode(SECRET_KEY.encode('utf-8')).decode('utf-8')
decoded = jwt.decode(token, encoded_secret, algorithms=['HS512'])
# Perform additional validation or retrieve user information from the decoded token if needed
# ...
if require_premium:
pass
# Add a premium user check here
except InvalidTokenError as e:
return jsonify(message=f'Invalid token: {e}'), 401
return func(*args, **kwargs)
return wrapper
The secret key:
SECRET_KEY = 'exampleSecret'
However, this doesn't work when decoding this token: eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsIm5nbyI6Ik5HTyIsInZlcmlmaWVkIjp0cnVlLCJleHAiOjE2ODQ1MTc5NTQsImlhdCI6MTY4NDQzMTU1NCwiYXV0aG9yaXRpZXMiOlsiTk9STUFMX1VTRVIiLCJBRE1JTiJdfQ.xzXMd7GmK_ZEqY2DaSkMiv0axgfMXHZavXTnmNBTn-q96b39coGy2MZL7txNbtDZ1DaUIDzjN6_mVMbtZH1ONg
.
I tried it out in the debugger available in jwt.io. You can find it here.
I have also set the secret key correctly before decoding it. I tried it both with and without this line: encoded_secret = base64.urlsafe_b64encode(SECRET_KEY.encode('utf-8')).decode('utf-8')
but didn't work on both the cases. What exactly could be the issue here?
The reason I do the base64 encoding is because in the jwt.io debugger, the signature was not verified without it. I had to check "secret base64 encoded" for it to work.
When I print out the error, I get Invalid Header Padding
.
Edit (added java code for generating token):
@Component
public class JwtTokenGenerator {
/**
* Time in milliseconds the JWT token is valid for.
*/
public static final long JWT_TOKEN_VALIDITY = 24 * 60 * 60 * 1000;
/**
* Time provider to make testing easier.
*/
private final transient TimeProvider timeProvider;
@Value("${jwt.secret}") // automatically loads jwt.secret from resources/application.properties
private transient String jwtSecret;
@Autowired
public JwtTokenGenerator(TimeProvider timeProvider) {
this.timeProvider = timeProvider;
}
/**
* Generate a JWT token for the provided user.
*
* @param userDetails The user details
* @return the JWT token
*/
public String generateToken(CustomUserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put("ngo", (userDetails).getNgo());
claims.put("verified", (userDetails).isVerified());
List<String> authorities = userDetails.getAuthorities()
.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
claims.put("authorities", authorities);
return Jwts.builder().setClaims(claims).setSubject(userDetails.getUsername())
.setIssuedAt(new Date(timeProvider.getCurrentTime().toEpochMilli()))
.setExpiration(new Date(timeProvider.getCurrentTime().toEpochMilli() + JWT_TOKEN_VALIDITY))
.signWith(SignatureAlgorithm.HS512, jwtSecret).compact();
}
}
I notice that the .signWith()
method expects a base64 encoded key. So it does decode it before signing.
Edit 2 (problem with decoding the encoded key):
import base64
from flask import request, jsonify
import jwt
from jwt.exceptions import InvalidTokenError
from config import SECRET_KEY
def authenticate_token(func, require_premium=False):
"""
:param require_premium: True if the endpoint is only for premium users
:param func: the function that is being wrapped around
:return: returns the wrapped function itself
"""
def wrapper(*args, **kwargs):
token = request.headers.get('Authorization').split()[1]
print(token)
if not token:
return jsonify(message='Authorization token is missing'), 401
try:
decoded_key = base64.b64decode(SECRET_KEY).decode('utf-8')
print(decoded_key)
decoded = jwt.decode(token, decoded_key, algorithms=['HS512'])
# Perform additional validation or retrieve user information from the decoded token if needed
# ...
if require_premium:
pass
# Add a premium user check here
except InvalidTokenError as e:
return jsonify(message=f'Invalid token: {e}'), 401
return func(*args, **kwargs)
return wrapper
This is how my code looks right now. However, I have a problem base64 decoding the key. My encoded key is: pZStXzAznM4xjxnRNgM2Nr5GQYtktG664iFxsVmvj3mPWqki9WrO1y/eGPmo/8T83BDR9l7hRJihRgwe7UGV5A==
After the base64.b64decode(SECRET_KEY)
, I get this: b'\xa5\x94\xad_03\x9c\xce1\x8f\x19\xd16\x0366\xbeFA\x8bd\xb4n\xba\xe2!q\xb1Y\xaf\x8fy\x8fZ\xa9"\xf5j\xce\xd7/\xde\x18\xf9\xa8\xff\xc4\xfc\xdc\x10\xd1\xf6^\xe1D\x98\xa1F\x0c\x1e\xedA\x95\xe4'
which clearly is a byte string. So to I used decode('utf-8')
and now I get this error:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa5 in position 0: invalid start byte