From da8eca56e20fcd18fb1e138bc575d07cc49d8f2c Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Mon, 24 Apr 2017 13:55:46 -0700 Subject: [PATCH] Better handling of token lifetime. - In C++, we need a constant for the max lifetime. - In C, make sure that we crop the lifetime in the credentials object itself and not just later during the creation of the token. This will allow the refresh to occur based on the actual token lifetime as opposed to the one from the user (which may be cropped). --- include/grpc++/security/credentials.h | 8 +++- .../credentials/jwt/jwt_credentials.c | 7 ++++ test/core/security/credentials_test.c | 40 +++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/include/grpc++/security/credentials.h b/include/grpc++/security/credentials.h index 1ec9b9728b2..92330d42c68 100644 --- a/include/grpc++/security/credentials.h +++ b/include/grpc++/security/credentials.h @@ -132,13 +132,17 @@ std::shared_ptr SslCredentials( /// services. std::shared_ptr GoogleComputeEngineCredentials(); +/// Constant for maximum auth token lifetime. +constexpr long kMaxAuthTokenLifetimeSecs = 3600; + /// Builds Service Account JWT Access credentials. /// json_key is the JSON key string containing the client's private key. /// token_lifetime_seconds is the lifetime in seconds of each Json Web Token /// (JWT) created with this credentials. It should not exceed -/// \a grpc_max_auth_token_lifetime or will be cropped to this value. +/// \a kMaxAuthTokenLifetimeSecs or will be cropped to this value. std::shared_ptr ServiceAccountJWTAccessCredentials( - const grpc::string& json_key, long token_lifetime_seconds); + const grpc::string& json_key, + long token_lifetime_seconds = kMaxAuthTokenLifetimeSecs); /// Builds refresh token credentials. /// json_refresh_token is the JSON string containing the refresh token along diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.c b/src/core/lib/security/credentials/jwt/jwt_credentials.c index 589a6f94076..4357657defc 100644 --- a/src/core/lib/security/credentials/jwt/jwt_credentials.c +++ b/src/core/lib/security/credentials/jwt/jwt_credentials.c @@ -125,6 +125,13 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key( gpr_ref_init(&c->base.refcount, 1); c->base.vtable = &jwt_vtable; c->key = key; + gpr_timespec max_token_lifetime = grpc_max_auth_token_lifetime(); + if (gpr_time_cmp(token_lifetime, max_token_lifetime) > 0) { + gpr_log(GPR_INFO, + "Cropping token lifetime to maximum allowed value (%d secs).", + (int)max_token_lifetime.tv_sec); + token_lifetime = grpc_max_auth_token_lifetime(); + } c->jwt_lifetime = token_lifetime; gpr_mu_init(&c->cache_mu); jwt_reset_cache(exec_ctx, c); diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index 9d419c78ead..a76cb0499d8 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -816,6 +816,45 @@ static void on_jwt_creds_get_metadata_failure( GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); } +static grpc_service_account_jwt_access_credentials *creds_as_jwt( + grpc_call_credentials *creds) { + GPR_ASSERT(creds != NULL); + GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_JWT) == 0); + return (grpc_service_account_jwt_access_credentials *)creds; +} + +static void test_jwt_creds_lifetime(void) { + char *json_key_string = test_json_key_str(); + + // Max lifetime. + grpc_call_credentials *jwt_creds = + grpc_service_account_jwt_access_credentials_create( + json_key_string, grpc_max_auth_token_lifetime(), NULL); + GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime, + grpc_max_auth_token_lifetime()) == 0); + grpc_call_credentials_release(jwt_creds); + + // Shorter lifetime. + gpr_timespec token_lifetime = {10, 0, GPR_TIMESPAN}; + GPR_ASSERT(gpr_time_cmp(grpc_max_auth_token_lifetime(), token_lifetime) > 0); + jwt_creds = grpc_service_account_jwt_access_credentials_create( + json_key_string, token_lifetime, NULL); + GPR_ASSERT( + gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime, token_lifetime) == 0); + grpc_call_credentials_release(jwt_creds); + + // Cropped lifetime. + gpr_timespec add_to_max = {10, 0, GPR_TIMESPAN}; + token_lifetime = gpr_time_add(grpc_max_auth_token_lifetime(), add_to_max); + jwt_creds = grpc_service_account_jwt_access_credentials_create( + json_key_string, token_lifetime, NULL); + GPR_ASSERT(gpr_time_cmp(creds_as_jwt(jwt_creds)->jwt_lifetime, + grpc_max_auth_token_lifetime()) == 0); + grpc_call_credentials_release(jwt_creds); + + gpr_free(json_key_string); +} + static void test_jwt_creds_success(void) { char *json_key_string = test_json_key_str(); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; @@ -1216,6 +1255,7 @@ int main(int argc, char **argv) { test_compute_engine_creds_failure(); test_refresh_token_creds_success(); test_refresh_token_creds_failure(); + test_jwt_creds_lifetime(); test_jwt_creds_success(); test_jwt_creds_signing_failure(); test_google_default_creds_auth_key();