JWT claims
Hi,
For the claims required for jwt authentication, I don't understand exactly what is expected for the "exp" field. Does it expect the UTC time in seconds? The number shown in the example does not make sense to me.
I am using python and am utilizing datetime's utcnow() to gather the current utc time, but the format does not match up at all to the single number string shown in the example.
Any guidance on what exactly is expected in the "exp" field is great.
Thank you!
-
Hi ,
Please check out the JWT page on Box Developer Site: https://docs.box.com/docs/app-auth#section-5-constructing-the-claims
The "exp" parameter is expecting a Epoch / Unix time value such as 1468262189 at the time of writing.
Check out this time converter or use python to get the exact time right now.
>>> import time >>> time.time()
1468262189.884993Below is an example python script which will help you get started with generating JWT assertions. You will first need to install a couple of libraries (pyjwt and cryptography) - Check out https://jwt.io/ for this and other library options.
procks@box:~/VENV$ virtualenv jwt ##Optional - create a python Virtual Environment New python executable in jwt/bin/python Installing setuptools, pip, wheel...done. procks@box:~/VENV$ source jwt/bin/activate ##Activate Virtual Environment (jwt)procks@box:~/VENV$ pip install --upgrade pip ##Get latest pip Collecting pip ....... Successfully installed pip-8.1.2 (jwt)procks@box:~/VENV$ pip install cryptography ##To load JWT private key in next step Collecting cryptography ....... Successfully installed cffi-1.7.0 cryptography-1.4 enum34-1.1.6 idna-2.1 ipaddress-1.0.16 pyasn1-0.1.9 pycparser-2.14 six-1.10.0 (jwt)procks@box:~/VENV$ pip install pyjwt ##To encode assertion in next step Collecting pyjwt Downloading PyJWT-1.4.0-py2.py3-none-any.whl Installing collected packages: pyjwt Successfully installed pyjwt-1.4.0 (jwt)procks@box:~/VENV$
Update the following script with the location of your Private key, Client ID and password.
import jwt import uuid import datetime from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import dsa, rsa from cryptography.hazmat.primitives.serialization import load_pem_private_key # Loads the private key # Change the path to the path to your private key # Change the password to the password you used when generating the private key key = load_pem_private_key(open('/Users/procks/Box Sync/Coding/private_key.pem').read(), password="YOUR_PRIVATE_KEY_PW", backend=default_backend()) print '\n####################################################################' print '# Building JWT Assertion #' print '####################################################################' client_id = "YOUR_CLIENT_ID" # (find out from https://app.box.com/developers/services) aud = "https://api.box.com/oauth2/token" iat = int(((datetime.datetime.utcnow() - datetime.datetime(1970,1,1)).total_seconds())+0) iat_time = datetime.datetime.fromtimestamp(iat).strftime('%c') exp = int(((datetime.datetime.utcnow() - datetime.datetime(1970,1,1)).total_seconds())+60) exp_time = datetime.datetime.fromtimestamp(exp).strftime('%c') # Generates a random hex for the jti jti = (uuid.uuid4()).hex print "Application Client ID (issuer): " + str(client_id) print "JWT Audience: " + str(aud) print "JWT Issued at Time (UNIX Epoch): " + str(iat)
print "JWT Issued at Time: " + str(iat_time)
print "Expiry Time for JWT (UNIX Epoch): " + str(exp)
print "Expiry Time for JWT: " + str(exp_time) print "jti unique identifier: " + str(jti) print '####################################################################' + "\n" # Creates an assertion for an enterprise token # Change the iss to your client id # Change the sub to your enterprise id enterprise_assertion = jwt.encode({"iss": client_id,"sub": "YOUR_TENANT_ENTERPRISE_ID","box_sub_type": "enterprise","aud": aud,"jti": jti,"exp": exp,}, key, algorithm='RS256', headers={"alg": "RS256","typ": "JWT"}) print "Below is your JWT Assertion in the base64URLencoded format......" + "\n" print enterprise_assertion # Creates an assertion for a user token # Change the iss to your client id # Change the sub to your user id #user_assertion = jwt.encode({"iss": "p0271k1w3vtdf1nk660cfhrx204qotfg","sub": "USER_ID_HERE","box_sub_type": "user","aud": aud,"jti": jti,"exp": exp, "iat": iat}, key, algorithm='RS256', headers={"alg": "RS256","typ": "JWT"}) #print user_assertionYour Terminal Output should look similar to below:
(jwt)procks@box:~/Box Sync/Coding/Python$ python jwt-builder.py #################################################################### # Building JWT Assertion # #################################################################### Application Client ID (issuer): MY_CLIENT_ID JWT Audience: https://api.box.com/oauth2/token JWT Issued at Time (UNIX Epoch): 1468261926 JWT Issued at Time: Mon Jul 11 19:32:06 2016 Expiry Time for JWT (UNIX Epoch): 1468261986 Expiry Time for JWT: Mon Jul 11 19:33:06 2016 jti unique identifier: e29c30cacfc24664a9ed4c5007451cab #################################################################### Below is your JWT Assertion in the base64URLencoded format
...... eyJhbGciOiJSUNiIsInR5cCI6IXVCJ9.eyJzdWIiOiI0NjM0MTYiLCJpc3MiOiJwMDI3MWsxdzN2dGRmMW5rNjYwY2ZocngyMDRxb3RmZyIsImp0aSI6ImUyOWMzMGNhY2ZjMjQ2NjRhOWVkNGM1MDA3NDUxY2FiIiwiZXhwIjoxNDY4MjYxOTg2LCJib3hfc3ViX3R5cGUiOiJlbnRlcnBlIiwiYXVkIjoiaHR0cHM6Ly9hcGkuYm94LmNvbS9vYXvdG9rZW4ifQ.NVY5XHidst-sjWJ3RThCp9w-UB2RcqEqMQtlz-19QXAYVHIONw5Axw9YR7Kr1nHCckbYNtWxjiFe62qlxewNp4_2eOhcj_24uTzDdmwm9pM5eAegh_WHPh2PQP1WStr8c7owMxztQuPXvEiIH2VS7zrlVPG2Gg-NVbr7VcLCSf6ZaoTZcgfh04CeNS_PBzUbqOGVrEeFnoK5T84nrB71jFkEKAEexeVs3Pca0OhmPZ1zCS9TZ1-5ovgoraC_YYfKasCmIxavNceCpSgHjvMzh_MQQEGSE36sZE6Mp2p0YjgDtHXC64ZUTsG7nBskYYcwCdGGxU9QZmuJzw -
For those using Python, I highly recommend using our Box Python SDK: http://pypi.python.org/pypi/boxsdk , https://github.com/box/box-python-sdk . The JWTAuth class takes care of all of these details for you. All you need to do is provide the required information in the constructor and the authenticate methods.
If you're using a different language, our other SDKs also support JWT auth for app users: https://docs.box.com/page/sdks
-
I am trying to use the boxsdk with jwt and I am following an example I found. I keep getting this error...
jwt.exceptions.InvalidTokenError: Key ID header parameter must be a string
from boxsdk import JWTAuth, Client
from settings import BoxCredentialsboxcreds = BoxCredentials()
def store_tokens(access_token, refresh_token):
print access_token
print refresh_tokenauth = JWTAuth(
client_id=boxcreds.client_id,
client_secret=boxcreds.client_secret,
enterprise_id=boxcreds.enterprise_id,
jwt_key_id=boxcreds.jwt_key_id,
rsa_private_key_file_sys_path=boxcreds.rsa_private_key_file_sys_path,
store_tokens=store_tokens,
)access_token = auth.authenticate_instance()
print access_token
client = Client(auth)
Suggestions?
-
Hi there. I am getting "invalid grant ... Please check the 'exp' claim."
No matter what I use.... even when copied directly from http://www.epochconverter.com/ - the link suggested in this thread. I even added the milliseconds.
Example
***number removed for privacy***4.884993 2/11/20***phone number removed for privacy***:53:04 AM
Can someone tell me the issue? Thanks!
Please sign in to leave a comment.
Comments
5 comments