This guide takes you through JWT authentication without using a Box SDK.
JWT does not require end-user interaction and is designed to authenticate
directly with the Box API.To learn how to use this token visit our guide on making API
calls.
By default, the Access Token acquired with JWT is tied to the Service
Account for the application. Any API call made with this token will come
from the application. This account does not have access to any existing files
or folders until the application’s Service Account is added as a collaborator.It is possible to act as another user
using the as-user header or by requesting a
User Access Token.
To use this object in the application it needs to be read from file.
Report incorrect code
Copy
Ask AI
using System;using System.IO;using Newtonsoft.Json;class Config{ public class BoxAppSettings { public class AppAuth { public string privateKey { get; set; } public string passphrase { get; set; } public string publicKeyID { get; set; } } public string clientID { get; set; } public string clientSecret { get; set; } public AppAuth appAuth { get; set; } } public string enterpriseID { get; set; } public BoxAppSettings boxAppSettings { get; set; }}var reader = new StreamReader("config.json");var json = reader.ReadToEnd();var config = JsonConvert.DeserializeObject<Config>(json);
Parsing JSONIn some programming languages there is more than one way to read and parse
JSON from a file. Refer to guides on your preferred programming language for
more complete guides, including error handling.
To create the JWT assertion the application needs the private key from the
configuration object. This private key is encrypted and requires a passcode to
unlock. Both the encrypted key and passcode are provided in the configuration
object.
Report incorrect code
Copy
Ask AI
using System.Security.Cryptography;using Org.BouncyCastle.OpenSsl;using Org.BouncyCastle.Crypto.Parameters;using Org.BouncyCastle.Math;// https://www.bouncycastle.org/csharp/index.htmlclass PasswordFinder : IPasswordFinder{ private string password; public PasswordFinder(string _password) { password = _password; } public char[] GetPassword() { return password.ToCharArray(); }}var appAuth = config.boxAppSettings.appAuth;var stringReader = new StringReader(appAuth.privateKey);var passwordFinder = new PasswordFinder(appAuth.passphrase);var pemReader = new PemReader(stringReader, passwordFinder);var keyParams = (RsaPrivateCrtKeyParameters) pemReader.ReadObject();public RSA CreateRSAProvider(RSAParameters rp){ var rsaCsp = RSA.Create(); rsaCsp.ImportParameters(rp); return rsaCsp;}public RSAParameters ToRSAParameters(RsaPrivateCrtKeyParameters privKey){ RSAParameters rp = new RSAParameters(); rp.Modulus = privKey.Modulus.ToByteArrayUnsigned(); rp.Exponent = privKey.PublicExponent.ToByteArrayUnsigned(); rp.P = privKey.P.ToByteArrayUnsigned(); rp.Q = privKey.Q.ToByteArrayUnsigned(); rp.D = ConvertRSAParametersField(privKey.Exponent, rp.Modulus.Length); rp.DP = ConvertRSAParametersField(privKey.DP, rp.P.Length); rp.DQ = ConvertRSAParametersField(privKey.DQ, rp.Q.Length); rp.InverseQ = ConvertRSAParametersField(privKey.QInv, rp.Q.Length); return rp;}public byte[] ConvertRSAParametersField(BigInteger n, int size){ byte[] bs = n.ToByteArrayUnsigned(); if (bs.Length == size) return bs; if (bs.Length > size) throw new ArgumentException("Specified size too small", "size"); byte[] padded = new byte[size]; Array.Copy(bs, 0, padded, size - bs.Length, bs.Length); return padded;}var key = CreateRSAProvider(ToRSAParameters(keyParams));
An alternative to loading private key from filethe application might not want to keep both the private key and password
stored on disk. An alternative option would be to pass in the password as an
environment variable, separating the private key from the token used to unlock
the key.
To authenticate to the Box API the application needs to create a signed JWT
assertion that can be exchanged for an Access Token.A JWT assertion is an encrypted JSON object, consisting of a
header, claims, and signature. Let’s start by creating the claims,
sometimes also referred to as the payload.
Report incorrect code
Copy
Ask AI
using System.IdentityModel.Tokens.Jwt;using System.Security.Claims;using System.Collections.Generic;byte[] randomNumber = new byte[64];RandomNumberGenerator.Create().GetBytes(randomNumber);var jti = Convert.ToBase64String(randomNumber);DateTime expirationTime = DateTime.UtcNow.AddSeconds(45);var claims = new List<Claim>{ new Claim("sub", config.enterpriseID), new Claim("box_sub_type", "enterprise"), new Claim("jti", jti),};
Parameter
Type
Description
iss, required
String
The Box Application’s OAuth client ID
sub, required
String
The Box Enterprise ID if this app is to act on behalf of the Service Account of that application, or the User ID if this app wants to act on behalf of another user.
box_sub_type, required
String
enterprise or user depending on the type of token being requested in the sub claim
aud, required
String
Always https://api.box.com/oauth2/token
jti, required
String
A universally unique identifier specified by the application for this JWT. A unique string of at least 16 characters and at most 128 characters.
exp, required
Integer
The Unix time when this JWT is to expire. Can be set to a maximum value of 60 seconds beyond the issue time. It is recommended to set this to less than the maximum allowed.
iat, optional
Integer
Issued at time. The token cannot be used before this time.
nbf, optional
Integer
Not before. Not Specifies when the token will start being valid.
Next, these claims need to be signed using the private key. Depending on the
language and library used, the header of the JWT is configured by defining the
encryption algorithm and the ID of the public key used to sign the claims.
Report incorrect code
Copy
Ask AI
using Microsoft.IdentityModel.Tokens;String authenticationUrl = "https://api.box.com/oauth2/token";var payload = new JwtPayload( config.boxAppSettings.clientID, authenticationUrl, claims, null, expirationTime);var credentials = new SigningCredentials( new RsaSecurityKey(key), SecurityAlgorithms.RsaSha512);var header = new JwtHeader(signingCredentials: credentials);var jst = new JwtSecurityToken(header, payload);var tokenHandler = new JwtSecurityTokenHandler();string assertion = tokenHandler.WriteToken(jst);
For the header the following parameters are supported.
Parameter
Type
Description
algorithm, required
String
The encryption algorithm used to sign the JWT claim. This can be one of RS256, RS384, or RS512.
keyid, required
String
The ID of the public key used to sign the JWT. Not required, though essential when multiple key pairs are defined for an application.
Using JWT librariesSigning your own JWT can be a complicated and painful process. Luckily, the
hard work has already been done for you and libraries exist in pretty much
every language. Head over to JWT.io for an overview.
The final step is to exchange the short lived JWT assertion for a more long
lived Access Token by calling the token endpoint with the
assertion as a parameter.
Report incorrect code
Copy
Ask AI
using System.Net;using System.Net.Http;var content = new FormUrlEncodedContent(new[]{ new KeyValuePair<string, string>( "grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"), new KeyValuePair<string, string>( "assertion", assertion), new KeyValuePair<string, string>( "client_id", config.boxAppSettings.clientID), new KeyValuePair<string, string>( "client_secret", config.boxAppSettings.clientSecret)});var client = new HttpClient();var response = client.PostAsync(authenticationUrl, content).Result;class Token{ public string access_token { get; set; }}var data = response.Content.ReadAsStringAsync().Result;var token = JsonConvert.DeserializeObject<Token>(data);var accessToken = token.access_token;