Implementing JWT credentials (a.k.a JWT ID Tokens).
- Not tested end to end yet
diff --git a/src/core/security/auth.c b/src/core/security/auth.c
index 58679a8..92878e3 100644
--- a/src/core/security/auth.c
+++ b/src/core/security/auth.c
@@ -48,6 +48,7 @@
typedef struct {
grpc_credentials *creds;
grpc_mdstr *host;
+ grpc_mdstr *method;
grpc_call_op op;
} call_data;
@@ -56,6 +57,7 @@
grpc_channel_security_context *security_context;
grpc_mdctx *md_ctx;
grpc_mdstr *authority_string;
+ grpc_mdstr *path_string;
grpc_mdstr *error_msg_key;
} channel_data;
@@ -89,6 +91,26 @@
grpc_call_next_op(elem, &((call_data *)elem->call_data)->op);
}
+static char *build_service_url(const char *url_scheme, call_data *calld) {
+ char *service_url;
+ char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
+ char *last_slash = strrchr(service, '/');
+ if (last_slash == NULL) {
+ gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
+ service[0] = '\0';
+ } else if (last_slash == service) {
+ /* No service part in fully qualified method name: will just be "/". */
+ service[1] = '\0';
+ } else {
+ *last_slash = '\0';
+ }
+ if (url_scheme == NULL) url_scheme = "";
+ gpr_asprintf(&service_url, "%s://%s%s", url_scheme,
+ grpc_mdstr_as_c_string(calld->host), service);
+ gpr_free(service);
+ return service_url;
+}
+
static void send_security_metadata(grpc_call_element *elem, grpc_call_op *op) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
@@ -106,9 +128,12 @@
}
if (channel_creds != NULL &&
grpc_credentials_has_request_metadata(channel_creds)) {
+ char *service_url =
+ build_service_url(channeld->security_context->base.url_scheme, calld);
calld->op = *op; /* Copy op (originates from the caller's stack). */
- grpc_credentials_get_request_metadata(channel_creds,
+ grpc_credentials_get_request_metadata(channel_creds, service_url,
on_credentials_metadata, elem);
+ gpr_free(service_url);
} else {
grpc_call_next_op(elem, op);
}
@@ -146,6 +171,9 @@
if (op->data.metadata->key == channeld->authority_string) {
if (calld->host != NULL) grpc_mdstr_unref(calld->host);
calld->host = grpc_mdstr_ref(op->data.metadata->value);
+ } else if (op->data.metadata->key == channeld->path_string) {
+ if (calld->method != NULL) grpc_mdstr_unref(calld->method);
+ calld->method = grpc_mdstr_ref(op->data.metadata->value);
}
grpc_call_next_op(elem, op);
break;
@@ -194,6 +222,7 @@
call_data *calld = elem->call_data;
calld->creds = NULL;
calld->host = NULL;
+ calld->method = NULL;
}
/* Destructor for call_data */
@@ -230,6 +259,7 @@
channeld->md_ctx = metadata_context;
channeld->authority_string =
grpc_mdstr_from_string(channeld->md_ctx, ":authority");
+ channeld->path_string = grpc_mdstr_from_string(channeld->md_ctx, ":path");
channeld->error_msg_key =
grpc_mdstr_from_string(channeld->md_ctx, "grpc-message");
}