diff --git a/lib/goth/token.ex b/lib/goth/token.ex index 5356ee5..4cac347 100644 --- a/lib/goth/token.ex +++ b/lib/goth/token.ex @@ -130,7 +130,9 @@ defmodule Goth.Token do * `"subject_token_type"` - * `"credential_source"` - information about how to retrieve the subject token, can contain the following keys: + * `"subject_token"` + + * `"credential_source"` - information about how to retrieve the subject token if not provided, can contain the following keys: * `"format"` - including a `"type"` of `"json"` or `"text"` and optionally `"subject_token_field_name"` if `"json"` * `"file"` - file to read the subject token from @@ -380,10 +382,18 @@ defmodule Goth.Token do %{ "token_url" => token_url, "audience" => audience, - "subject_token_type" => subject_token_type, - "credential_source" => credential_source + "subject_token_type" => subject_token_type } = credentials + subject_token = + case credentials do + %{"subject_token" => subject_token} -> + subject_token + + %{"credential_source" => credential_source} -> + subject_token_from_credential_source(credential_source, config) + end + headers = [{"Content-Type", "application/x-www-form-urlencoded"}] body = @@ -393,7 +403,7 @@ defmodule Goth.Token do "requested_token_type" => "urn:ietf:params:oauth:token-type:access_token", "scope" => List.first(@default_scopes), "subject_token_type" => subject_token_type, - "subject_token" => subject_token_from_credential_source(credential_source, config) + "subject_token" => subject_token }) response = request(config.http_client, method: :post, url: token_url, headers: headers, body: body) diff --git a/test/data/test-credentials-workload-identity-subject-token.json b/test/data/test-credentials-workload-identity-subject-token.json new file mode 100644 index 0000000..deb8cf9 --- /dev/null +++ b/test/data/test-credentials-workload-identity-subject-token.json @@ -0,0 +1,7 @@ +{ + "audience": "//iam.googleapis.com/projects/my-project/locations/global/workloadIdentityPools/my-cluster/providers/my-provider", + "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", + "subject_token": "token", + "token_url": "https://sts.googleapis.com/v1/token", + "type": "external_account" +} diff --git a/test/goth/token_test.exs b/test/goth/token_test.exs index 4aee720..8a804c1 100644 --- a/test/goth/token_test.exs +++ b/test/goth/token_test.exs @@ -276,6 +276,30 @@ defmodule Goth.TokenTest do assert token.scope == nil end + test "fetch/1 from workload identity, subject_token supplied" do + token_bypass = Bypass.open() + + Bypass.expect(token_bypass, fn conn -> + assert conn.request_path == "/v1/token" + + body = ~s|{"access_token":"dummy","expires_in":599,"token_type":"Bearer"}| + Plug.Conn.resp(conn, 200, body) + end) + + credentials = + File.read!("test/data/test-credentials-direct-workload-identity-json.json") + |> Jason.decode!() + |> Map.put("token_url", "http://localhost:#{token_bypass.port}/v1/token") + + config = %{ + source: {:workload_identity, credentials} + } + + {:ok, token} = Goth.Token.fetch(config) + assert token.token == "dummy" + assert token.scope == nil + end + test "fetch/1 from url-based workload identity" do token_bypass = Bypass.open() subject_token_bypass = Bypass.open()