|  |  |  | @@ -1080,7 +1080,7 @@ static JSValue _authenticate_jwt(JSContext* context, const char* jwt) | 
		
	
		
			
				|  |  |  |  | 	tf_task_t* task = tf_task_get(context); | 
		
	
		
			
				|  |  |  |  | 	tf_ssb_t* ssb = tf_task_get_ssb(task); | 
		
	
		
			
				|  |  |  |  | 	char public_key_b64[k_id_base64_len] = { 0 }; | 
		
	
		
			
				|  |  |  |  | 	tf_ssb_db_identity_visit(ssb, ":auth", _public_key_visit, public_key_b64); | 
		
	
		
			
				|  |  |  |  | 	tf_ssb_db_identity_visit(ssb, ":admin", _public_key_visit, public_key_b64); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	const char* payload = jwt + dot[0] + 1; | 
		
	
		
			
				|  |  |  |  | 	size_t payload_length = dot[1] - dot[0] - 1; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1150,15 +1150,12 @@ static void _visit_auth_identity(const char* identity, void* user_data) | 
		
	
		
			
				|  |  |  |  | static bool _get_auth_private_key(tf_ssb_t* ssb, uint8_t* out_private_key) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	char id[k_id_base64_len] = { 0 }; | 
		
	
		
			
				|  |  |  |  | 	tf_ssb_db_identity_visit(ssb, ":auth", _visit_auth_identity, id); | 
		
	
		
			
				|  |  |  |  | 	tf_ssb_db_identity_visit(ssb, ":admin", _visit_auth_identity, id); | 
		
	
		
			
				|  |  |  |  | 	if (*id) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		return tf_ssb_db_identity_get_private_key(ssb, ":auth", id, out_private_key, crypto_sign_SECRETKEYBYTES); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		return tf_ssb_db_identity_create(ssb, ":auth", out_private_key + crypto_sign_PUBLICKEYBYTES, out_private_key); | 
		
	
		
			
				|  |  |  |  | 		return tf_ssb_db_identity_get_private_key(ssb, ":admin", id, out_private_key, crypto_sign_SECRETKEYBYTES); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	return false; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static const char* _make_session_jwt(tf_ssb_t* ssb, const char* name) | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1167,21 +1164,15 @@ static const char* _make_session_jwt(tf_ssb_t* ssb, const char* name) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		return NULL; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	uint8_t private_key[crypto_sign_SECRETKEYBYTES] = { 0 }; | 
		
	
		
			
				|  |  |  |  | 	if (!_get_auth_private_key(ssb, private_key)) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		return NULL; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uv_timespec64_t now = { 0 }; | 
		
	
		
			
				|  |  |  |  | 	uv_clock_gettime(UV_CLOCK_REALTIME, &now); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	JSContext* context = tf_ssb_get_context(ssb); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	const char* header_json = "{\"alg\":\"HS256\",\"typ\":\"JWT\"}"; | 
		
	
		
			
				|  |  |  |  | 	char header_base64[256]; | 
		
	
		
			
				|  |  |  |  | 	sodium_bin2base64(header_base64, sizeof(header_base64), (uint8_t*)header_json, strlen(header_json), sodium_base64_VARIANT_URLSAFE_NO_PADDING); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	JSContext* context = tf_ssb_get_context(ssb); | 
		
	
		
			
				|  |  |  |  | 	JSValue payload = JS_NewObject(context); | 
		
	
		
			
				|  |  |  |  | 	JS_SetPropertyStr(context, payload, "name", JS_NewString(context, name)); | 
		
	
		
			
				|  |  |  |  | 	JS_SetPropertyStr(context, payload, "exp", JS_NewInt64(context, now.tv_sec * 1000 + now.tv_nsec / 1000000LL + k_refresh_interval)); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1196,12 +1187,17 @@ static const char* _make_session_jwt(tf_ssb_t* ssb, const char* name) | 
		
	
		
			
				|  |  |  |  | 	unsigned long long signature_length = 0; | 
		
	
		
			
				|  |  |  |  | 	char signature_base64[256] = { 0 }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (crypto_sign_detached(signature, &signature_length, (const uint8_t*)payload_base64, strlen(payload_base64), private_key) == 0) | 
		
	
		
			
				|  |  |  |  | 	uint8_t private_key[crypto_sign_SECRETKEYBYTES] = { 0 }; | 
		
	
		
			
				|  |  |  |  | 	if (_get_auth_private_key(ssb, private_key)) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		sodium_bin2base64(signature_base64, sizeof(signature_base64), signature, sizeof(signature), sodium_base64_VARIANT_URLSAFE_NO_PADDING); | 
		
	
		
			
				|  |  |  |  | 		size_t size = strlen(header_base64) + 1 + strlen(payload_base64) + 1 + strlen(signature_base64) + 1; | 
		
	
		
			
				|  |  |  |  | 		result = tf_malloc(size); | 
		
	
		
			
				|  |  |  |  | 		snprintf(result, size, "%s.%s.%s", header_base64, payload_base64, signature_base64); | 
		
	
		
			
				|  |  |  |  | 		if (crypto_sign_detached(signature, &signature_length, (const uint8_t*)payload_base64, strlen(payload_base64), private_key) == 0) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			sodium_bin2base64(signature_base64, sizeof(signature_base64), signature, sizeof(signature), sodium_base64_VARIANT_URLSAFE_NO_PADDING); | 
		
	
		
			
				|  |  |  |  | 			size_t size = strlen(header_base64) + 1 + strlen(payload_base64) + 1 + strlen(signature_base64) + 1; | 
		
	
		
			
				|  |  |  |  | 			result = tf_malloc(size); | 
		
	
		
			
				|  |  |  |  | 			snprintf(result, size, "%s.%s.%s", header_base64, payload_base64, signature_base64); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		sodium_memzero(private_key, sizeof(private_key)); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	JS_FreeCString(context, payload_string); | 
		
	
	
		
			
				
					
					|  |  |  |   |