Skip to main content

Manual Token request, with public key

Manual Token request, with public key
AndrewC
  • Participating Frequently
  • 5 replies

Hello,
I have been attempting to do a request to :
https://api.box.com/oauth2/token

My dev setup, is almost identical to my prod setup with one exception. In prod i use a Public Key. I am rewriting a tool i made using the NodeSDK in Rust. The issue I have is, in the NodeSDK you can pass it a thing like this:
{
“boxAppSettings”: {
“clientID”: “hvauxhjq98474895cej49uq2na1k4m3hca”,
“clientSecret”: “********************************”,
“appAuth”: {
“publicKeyID”: “”,
“privateKey”: “”,
“passphrase”: “”
}
},
“enterpriseID”: “42069”
}

Then i just pass it to my sdk as a preConfigured instance. HOWEVER, I have my Rust based Wrapper working with my dev account, but when I go to move into prod, I must be missing something, as i cant find examples of how to do this using a direct http request:

For example:

Where is the documentation on this process but with ‘curl’ or some other direct http calls?
I bet it exists but there seems to be no clear linking to it?

Any help and guidance on where to find this information would be greatly appreciated.
Thank you,
Andrew

Did this topic help you find an answer to your question?

2 replies

AndrewC
  • Author
  • Participating Frequently
  • 5 replies
  • April 16, 2024

Ok also something else super wierd while digging into this:
On the Left is my Prod console. On the Right is my Devconsole:


As I was comparing them to make sure I didnt miss anything, um, why is there different text in these boxes. They are configured exactly the same with the single exception being the PublicKey Pair.

Does this indicate something?!


rbarbosa Box
Forum|alt.badge.img
  • Developer Advocate
  • 556 replies
  • April 17, 2024

Hi @AndrewC , welcome to the forum!

You can absolutely do a manual HTTP POST request to get a new access token.

The issue might be how to generate a JWT assertion that you must include in that request.

For example in our postman collection, we have this pre-request script for getting and access token using JWT:

1async function refresh_jwt (assertion) {
2 const urlencoded = [
3 { key: 'client_id', value: pm.environment.get('client_id'), disabled: false },
4 { key: 'client_secret', value: pm.environment.get('client_secret'), disabled: false },
5 { key: 'box_subject_type', value: pm.environment.get('box_subject_type'), disabled: false },
6 { key: 'box_subject_id', value: pm.environment.get('box_subject_id'), disabled: false },
7 { key: 'grant_type', value: 'urn:ietf:params:oauth:grant-type:jwt-bearer', disabled: false },
8 { key: 'assertion', value: assertion, disabled: false }
9 ]
10
11 return await get_token(urlencoded).then((data) => {
12 const expires_at = Date.now() + (data.expires_in - 30) * 1000
13 pm.environment.set('access_token', data.access_token)
14 pm.environment.set('expires_at', expires_at)
15 })
16}
17

and we create the assertion like this:

1 // libJSRSASign lib
2 const libJSRSASign = pm.collectionVariables.get('libJSRSASign')
3 /* eslint-disable no-global-assign */
4 navigator = {}
5 window = {}
6 /* eslint-disable no-eval */
7
8 eval(libJSRSASign)
9
10 // UUID
11 const uuid = require('uuid')
12
13 const private_key_encrypted = pm.environment.get('private_key_encrypted').replace(/\\n/g, '')
14 const private_key_passphrase = pm.environment.get('private_key_passphrase')
15
16 const private_key = KEYUTIL.getKey(private_key_encrypted, private_key_passphrase)
17
18 const kid = pm.environment.get('key_id')
19 const iss = pm.environment.get('client_id')
20 const sub = pm.environment.get('box_subject_id')
21 const box_sub_type = pm.environment.get('box_subject_type')
22 const aud = 'https://' + pm.collectionVariables.get('api.box.com') + '/oauth2/token'
23 const jti = uuid.v4()
24 // const exp = KJUR.jws.IntDate.get("now + 1minute")
25 const exp = Math.floor(Date.now() / 1000) + 45
26 const iat = KJUR.jws.IntDate.get('now')
27
28 const header = { alg: 'RS512', typ: 'JWT', kid: kid }
29 // console.log(`header: ${JSON.stringify(header)}`)
30
31 const claims =
32 {
33 iss: iss,
34 sub: sub,
35 box_sub_type: box_sub_type,
36 aud: aud,
37 jti: jti,
38 exp: exp,
39 iat: iat
40 }
41
42 // console.log(`claim set: ${JSON.stringify(claims)}`)
43
44 const jwt = KJUR.jws.JWS.sign(null, header, claims, private_key)
45 // console.log('JWT Assertion: ', jwt)
46
47 return jwt
48}
49

This is javascript inside Postman, so it might not be that helpful, but it does illustrate the process.

However I do have a rust example for you…

Fair warning, this is incomplete, poorly implemented, and not supported! you have been warned 😉

https://crates.io/crates/rusty-box

In the examples you’ll find:

1// use cargo run --example users_main to run this file
2// use dotenv;
3
4use rusty_box::{
5 auth::auth_jwt::JWTAuth,
6 auth::auth_jwt::SubjectType,
7 client::{box_client::BoxClient, client_error::BoxAPIError},
8 config::Config,
9 rest_api::users::users_api,
10};
11use std::env;
12
13#[tokio::main]
14async fn main() -> Result<(), BoxAPIError> {
15 dotenv::from_filename(".jwt.env").ok();
16
17 let client_id = env::var("CLIENT_ID").expect("CLIENT_ID must be set");
18 let client_secret = env::var("CLIENT_SECRET").expect("CLIENT_SECRET must be set");
19
20 let env_subject_type = env::var("BOX_SUBJECT_TYPE").expect("BOX_SUBJECT_TYPE must be set");
21 let box_subject_type = match env_subject_type.as_str() {
22 "user" => SubjectType::User,
23 "enterprise" => SubjectType::Enterprise,
24 _ => panic!("BOX_SUBJECT_TYPE must be either 'user' or 'enterprise'"),
25 };
26
27 let box_subject_id = env::var("BOX_SUBJECT_ID").expect("BOX_SUBJECT_ID must be set");
28
29 let public_key_id = env::var("PUBLIC_KEY_ID").expect("PUBLIC_KEY_ID must be set");
30
31 let encrypted_private_key =
32 env::var("ENCRYPTED_PRIVATE_KEY").expect("ENCRYPTED_PRIVATE_KEY must be set");
33
34 let passphrase = env::var("PASSPHRASE").expect("PASSPHRASE must be set");
35
36 let config = Config::new();
37 let auth = JWTAuth::new(
38 config,
39 client_id,
40 client_secret,
41 box_subject_type,
42 box_subject_id,
43 public_key_id,
44 encrypted_private_key,
45 passphrase,
46 );
47
48 let mut client = BoxClient::new(Box::new(auth));
49
50 let fields = vec![];
51
52 let me = users_api::me(&mut client, Some(fields)).await?;
53 println!("Me:\n{me:#?}\n");
54
55 Ok(())
56}
57

As for any differences on your environments, from the info you sent, I can’t see anything wrong with it. Of course I’m assuming you have a specific config.json file for each environment…

Hope this helps

Cheers


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings