/**
 * @brief helper method to retrieve a user model of the currently authenticated user
 *
 * the function parses the authorization header of a request,
 * validates its format and ensures a proper session token is set.
 * it then takes the token and finds the user it belongs to.
 *
 * @param request a request
 * @return model of the currently authenticated user, taken from the storage
 * @throw kdbrest::exception::NoCurrentUserException
 * @throw kdbrest::exception::UserNotFoundException
 */
model::User AuthenticationApp::getCurrentUser (cppcms::http::request & request)
{
	// authentication validation
	std::string headerAuthorization = request.http_authorization ();
	std::string token;
	if (headerAuthorization.empty ())
	{
		// find token in get_parameters
		token = request.get (PARAM_TOKEN);
		if (token.empty ())
		{
			throw exception::NoCurrentUserException ();
		}
	}
	else
	{
		if (!boost::starts_with (headerAuthorization, AUTH_HEADER_PREFIX))
		{
			throw exception::NoCurrentUserException ();
		}
		token = headerAuthorization.substr (AUTH_HEADER_PREFIX.size ());
	}

	/* request seems fine, lets build the jwt */
	jwt_t * jwt;

	if (jwt_decode (&jwt, token.c_str (),
			reinterpret_cast<const unsigned char *> (
				Config::instance ().getConfig ().get<std::string> ("jwt.encryption.secret").c_str ()),
			Config::instance ().getConfig ().get<std::string> ("jwt.encryption.secret").size ()) != 0)
	{
		throw exception::NoCurrentUserException ();
	}

	std::unique_ptr<jwt_t, void (*) (jwt_t *)> jwt_ptr (jwt, jwt_free);

	// check issuer and other grants
	if (std::string (jwt_get_grant (jwt_ptr.get (), "issuer")) != std::string (ELEKTRA_REST_AUTHENTICATION_JWT_ISSUER) ||
	    jwt_get_grant_int (jwt_ptr.get (), "expires") < std::time (NULL))
	{
		throw exception::NoCurrentUserException ();
	}

	std::string username = std::string (jwt_get_grant (jwt_ptr.get (), "username"));
	if (username.empty ())
	{
		throw exception::NoCurrentUserException ();
	}

	try
	{
		model::User user = service::StorageEngine::instance ().getUser (username);
		return user;
	}
	catch (exception::UserNotFoundException const & e)
	{
		throw exception::UserNotFoundException ();
	}
}
Example #2
0
END_TEST

START_TEST(test_jwt_del_grant)
{
	jwt_t *jwt = NULL;
	const char *val;
	const char testval[] = "testing";
	int ret = 0;

	ret = jwt_new(&jwt);
	ck_assert_int_eq(ret, 0);
	ck_assert(jwt != NULL);

	ret = jwt_add_grant(jwt, "iss", testval);
	ck_assert_int_eq(ret, 0);

	ret = jwt_del_grant(jwt, "iss");
	ck_assert_int_eq(ret, 0);

	val = jwt_get_grant(jwt, "iss");
	ck_assert(val == NULL);

	/* Delete non existent. */
	ret = jwt_del_grant(jwt, "iss");
	ck_assert_int_eq(ret, 0);

	jwt_free(jwt);
}
Example #3
0
END_TEST

START_TEST(test_jwt_grants_json)
{
	const char *json = "{\"ref\":\"385d6518-fb73-45fc-b649-0527d8576130\""
		",\"id\":\"FVvGYTr3FhiURCFebsBOpBqTbzHdX/DvImiA2yheXr8=\","
		"\"iss\":\"localhost\",\"scopes\":\"storage\",\"sub\":"
		"\"user0\"}";
	jwt_t *jwt = NULL;
	const char *val;
	int ret = 0;

	ret = jwt_new(&jwt);
	ck_assert_int_eq(ret, 0);
	ck_assert(jwt != NULL);

	ret = jwt_add_grants_json(jwt, json);
	ck_assert_int_eq(ret, 0);

	val = jwt_get_grant(jwt, "ref");
	ck_assert(val != NULL);
	ck_assert_str_eq(val, "385d6518-fb73-45fc-b649-0527d8576130");

	jwt_free(jwt);
}
/**
 * @brief validates the authorization header of a request()
 *
 * helper method that allows to validate whether a request contains a valid
 * session token or not. it checks for the authorization header, format and
 * validity of the token.
 * additionally the method can do checks on the authenticated users rank and
 * username (i.e. check for permissions or if is owner of something).
 *
 * @note if a rank and a username are given, it is sufficient that one of both matches the
 *       requirement in order for the validation to succeed.
 *
 * @param request a request
 * @param response a response
 * @param rank optionally the rank of a user can be checked
 * @param orUser optionally the name of a user can be checked
 * @return true if an authentication is present and the authenticated user
 *		   matches all requirements, false otherwise
 */
bool AuthenticationApp::validateAuthentication (cppcms::http::request & request, cppcms::http::response & response, const int rank,
						const std::string orUser)
{
	// authentication validation
	std::string headerAuthorization = request.http_authorization ();
	std::string token;
	if (headerAuthorization.empty ())
	{
		// find token in get_parameters
		token = request.get (PARAM_TOKEN);
		if (token.empty ())
		{
			RootApp::setUnauthorized (response, "Session token missing.", "NEED_AUTHENTICATION"); // send HTTP 401
			return false;									      // not successful
		}
	}
	else
	{
		if (!boost::starts_with (headerAuthorization, AUTH_HEADER_PREFIX))
		{
			RootApp::setUnauthorized (response, "Authentication header has wrong format.", "NEED_AUTHENTICATION");
			return false; // not successful
		}
		token = headerAuthorization.substr (AUTH_HEADER_PREFIX.size ());
	}

	/* request seems fine, so lets parse the token */
	jwt_t * jwt;

	// decode it
	if (jwt_decode (&jwt, token.c_str (),
			reinterpret_cast<const unsigned char *> (
				Config::instance ().getConfig ().get<std::string> ("jwt.encryption.secret").c_str ()),
			Config::instance ().getConfig ().get<std::string> ("jwt.encryption.secret").size ()) != 0)
	{
		RootApp::setUnauthorized (response, "Session token is invalid", "NEED_AUTHENTICATION"); // send HTTP 401
		return false;
	}

	std::unique_ptr<jwt_t, void (*) (jwt_t *)> jwt_ptr (jwt, jwt_free);

	// check issuer and other grants
	if (std::string (jwt_get_grant (jwt_ptr.get (), "issuer")) != std::string (ELEKTRA_REST_AUTHENTICATION_JWT_ISSUER) ||
	    jwt_get_grant_int (jwt_ptr.get (), "expires") < std::time (NULL))
	{
		RootApp::setUnauthorized (response, "Session token is invalid", "NEED_AUTHENTICATION"); // send HTTP 401
		return false;
	}

	model::User currentUser = AuthenticationApp::getCurrentUser (request);
	if (currentUser.getRank () < rank && (orUser.empty () || orUser != currentUser.getUsername ()))
	{
		RootApp::setUnauthorized (response, "This action requires higher permissions.", "USER_INSUFFICIENT_PERMISSIONS");
		return false; // not successful
	}

	return true; // authentication successful
}
Example #5
0
END_TEST

START_TEST(test_jwt_grants_json)
{
	const char *json = "{\"ref\":\"385d6518-fb73-45fc-b649-0527d8576130\""
		",\"id\":\"FVvGYTr3FhiURCFebsBOpBqTbzHdX/DvImiA2yheXr8=\","
		"\"iss\":\"localhost\",\"scopes\":\"storage\",\"sub\":"
		"\"user0\"}";
	const char *json2 = "{"
		"\"id\":\"FVvGYTr3FhiURCFebsBOpBqTbzHdX/DvImiA2yheXr8=\","
		"\"iss\":\"localhost\",\"scopes\":\"storage\",\"sub\":"
		"\"user0\", \"nbf\":12345678, \"iat\":12346789}";
	jwt_t *jwt = NULL;
	json_t *js_val;
	const char *val;
	int intval;
	int ret = 0;

	ret = jwt_new(&jwt);
	ck_assert_int_eq(ret, 0);
	ck_assert(jwt != NULL);

	ret = jwt_add_grants_json(jwt, json);
	ck_assert_int_eq(ret, 0);

	val = jwt_get_grant(jwt, "ref");
	ck_assert(val != NULL);
	ck_assert_str_eq(val, "385d6518-fb73-45fc-b649-0527d8576130");

	jwt_free(jwt);

	ret = jwt_new(&jwt);
	ck_assert_int_eq(ret, 0);
	ck_assert(jwt != NULL);

	ret = jwt_add_grants_json(jwt, json2);
	ck_assert_int_eq(ret, 0);

  js_val = jwt_get_grant_obj (jwt, "nbf");
	ck_assert (js_val != NULL);
	ck_assert (json_is_integer (js_val));
	ck_assert (json_integer_value (js_val) == 12345678);

	ret = jwt_get_grant_int_or_str (jwt, "nbf", &val, &intval);
	ck_assert_int_eq(ret, 0);
	ck_assert(val == NULL);
	ck_assert (intval == 12345678);
}
Example #6
0
END_TEST

START_TEST(test_jwt_grant_invalid)
{
	jwt_t *jwt = NULL;
	const char *val;
	int ret = 0;

	ret = jwt_new(&jwt);
	ck_assert_int_eq(ret, 0);
	ck_assert(jwt != NULL);

	ret = jwt_add_grant(jwt, "iss", NULL);
	ck_assert_int_eq(ret, EINVAL);

	ret = jwt_del_grant(jwt, "");
	ck_assert_int_eq(ret, EINVAL);

	val = jwt_get_grant(jwt, NULL);
	ck_assert_int_eq(errno, EINVAL);
	ck_assert(val == NULL);

	jwt_free(jwt);
}
int mosquitto_auth_unpwd_check(void *user_data, const char *username, const char *password) {
  
  jwt_t *jwt;
#ifdef MQAP_DEBUG
  const char* val;
  int i_val;
#endif
  time_t now;
  int iat;
  int exp;
  unsigned char key[32] = "012345678901234567890123456789AB";

  if (username == NULL || password == NULL) {
    return MOSQ_ERR_AUTH;
  }
#ifdef MQAP_DEBUG
  fprintf(stderr, "mosquitto_auth_unpwd_check: username=%s, password=%s\n", username, password);
#endif
  if ( ! strcmp(username, "jwt") ) {

	time(&now);

	int status = jwt_decode(&jwt, password, key , sizeof(key));

	if (( status == 0 ) && (jwt != NULL) ) {
#ifdef MQAP_DEBUG	
		fprintf(stderr, "mosquitto_auth_unpwd_check:  password is a valid JWT token\n");
		val = jwt_get_grant(jwt, "iss");
     		fprintf(stderr, "mosquitto_auth_unpwd_check:  iss : %s\n", val);
		val = jwt_get_grant(jwt, "sub");
     		fprintf(stderr, "mosquitto_auth_unpwd_check:  sub : %s\n", val);
		i_val = get_js_int(jwt->grants, "iat");
     		fprintf(stderr, "mosquitto_auth_unpwd_check:  iat : %d\n", i_val);
		i_val = get_js_int(jwt->grants, "exp");
     		fprintf(stderr, "mosquitto_auth_unpwd_check:  exp : %d\n", i_val);
		val = get_js_object(jwt->grants, "aud");
     		fprintf(stderr, "mosquitto_auth_unpwd_check:  aud : %s\n", val);
     		fprintf(stderr, "mosquitto_auth_unpwd_check:  now : %d\n", (int)now);
#endif
		iat = get_js_int(jwt->grants, "iat");		
		exp = get_js_int(jwt->grants, "exp");		
		if ( (now < iat) || (now > exp) ) {
#ifdef MQAP_DEBUG
                fprintf(stderr, "mosquitto_auth_unpwd_check:  token is expired\n");
#endif
		   jwt_free(jwt);
                   return MOSQ_ERR_AUTH;
		}

		// TODO add here some other controls about iss, sub, ...

		jwt_free(jwt);
        	return MOSQ_ERR_SUCCESS;
  	} else {
#ifdef MQAP_DEBUG
		fprintf(stderr, "mosquitto_auth_unpwd_check:  password is not a valid token %d\n", status);
#endif	
	}
  } 

  return MOSQ_ERR_AUTH;
}