View Source Goth.Token (Goth v1.4.2)

Functions for retrieving the token from the Google API.

Summary

Functions

Fetch the token from the Google API using the given config.

Types

@type t() :: %Goth.Token{
  account: term(),
  expires: non_neg_integer(),
  scope: String.t(),
  sub: String.t() | nil,
  token: String.t(),
  type: String.t()
}

Functions

Link to this function

fetch(config)

View Source (since 1.3.0)
@spec fetch(keyword() | map()) :: {:ok, t()} | {:error, Exception.t()}

Fetch the token from the Google API using the given config.

Config may contain the following keys:

  • :source - the source to retrieve the token from.

    Supported values include:

    • {:service_account, credentials} - for fetching token using service account credentials

    • {:refresh_token, credentials} - for fetching token using refresh token

    • :metadata - for fetching token using Google internal metadata service

    If :source is not set, Goth will:

    • Check application environment. You can set it with: config :goth, json: File.read!("credentials.json").

    • Check GOOGLE_APPLICATION_CREDENTIALS env variable that contains path to credentials file.

    • Check GOOGLE_APPLICATION_CREDENTIALS_JSON env variable that contains credentials JSON.

    • Check ~/.config/gcloud/application_default_credentials.json file.

    • Check Google internal metadata service

    • Otherwise, raise an error.

    See "Source" section below for more information.

  • :http_client - a function that makes the HTTP request.

    Can be one of the following:

    • fun - same as {fun, []}

    • {fun, opts} - fun must be a 1-arity function that receives a keyword list with fields :method, :url, :headers, and :body along with any passed opts. The function must return {:ok, %{status: status, headers: headers, body: body}} or {:error, exception}.

      See "Custom HTTP Client" section below for more information.

    fun can also be an atom :finch to use the built-in Finch-based client.

    Defaults to {:finch, []}.

Source

Source can be one of:

Service account - {:service_account, credentials}

Same as {:service_account, credentials, []}

Service account - {:service_account, credentials, options}

The credentials is a map and can contain the following keys:

  • "private_key"

  • "client_email"

The options is a keywords list and can contain the following keys:

  • :url - the URL of the authentication service, defaults to: "https://www.googleapis.com/oauth2/v4/token"

  • :scopes - the list of token scopes, defaults to ["https://www.googleapis.com/auth/cloud-platform"] (ignored if :claims present)

  • :claims - self-signed JWT extra claims. Should be a map with string keys only. A self-signed JWT will be exchanged for a Google-signed ID token

Refresh token - {:refresh_token, credentials}

Same as {:refresh_token, credentials, []}

Refresh token - {:refresh_token, credentials, options}

The credentials is a map and can contain the following keys:

  • "refresh_token"

  • "client_id"

  • "client_secret"

The options is a keywords list and can contain the following keys:

  • :url - the URL of the authentication service, defaults to: "https://www.googleapis.com/oauth2/v4/token"

Google metadata server - :metadata

Same as {:metadata, []}

Google metadata server - {:metadata, options}

The options is a keywords list and can contain the following keys:

  • :account - the name of the account to generate the token for, defaults to "default"

  • :url - the URL of the metadata server, defaults to "http://metadata.google.internal"

  • :audience - the audience you want an identity token for, default to nil If this parameter is provided, an identity token is returned instead of an access token

Custom HTTP Client

To use a custom HTTP client, define a function that receives a keyword list with fields :method, :url, :headers, and :body. The function must return {:ok, %{status: status, headers: headers, body: body}} or {:error, exception}.

Here's an example with Finch:

defmodule MyApp do
  def request_with_finch(options) do
    {method, options} = Keyword.pop!(options, :method)
    {url, options} = Keyword.pop!(options, :url)
    {headers, options} = Keyword.pop!(options, :headers)
    {body, options} = Keyword.pop!(options, :body)

    Finch.build(method, url, headers, body)
    |> Finch.request(Goth.Finch, options)
  end
end

And here is how it can be used:

iex> Goth.Token.fetch(source: source, http_client: &MyApp.request_with_finch/1)
{:ok, %Goth.Token{...}}

iex> Goth.Token.fetch(source: source, http_client: {&MyApp.request_with_finch/1, receive_timeout: 5000})
{:ok, %Goth.Token{...}}

Examples

Generate a token using a service account credentials file:

iex> credentials = "credentials.json" |> File.read!() |> Jason.decode!()
iex> Goth.Token.fetch(source: {:service_account, credentials})
{:ok, %Goth.Token{...}}

You can generate a credentials file containing service account using gcloud utility like this:

$ gcloud iam service-accounts keys create --key-file-type=json --iam-account=... credentials.json

Generate a cloud function invocation token using a service account credentials file:

iex> credentials = "credentials.json" |> File.read!() |> Jason.decode!()
...> claims = %{"target_audience" => "https://<GCP_REGION>-<PROJECT_ID>.cloudfunctions.net/<CLOUD_FUNCTION_NAME>"}
...> Goth.Token.fetch(source: {:service_account, credentials, [claims: claims]})
{:ok, %Goth.Token{...}}

Generate an impersonated token using a service account credentials file:

iex> credentials = "credentials.json" |> File.read!() |> Jason.decode!()
...> claims = %{"sub" => "<IMPERSONATED_ACCOUNT_EMAIL>"}
...> Goth.Token.fetch(source: {:service_account, credentials, [claims: claims]})
{:ok, %Goth.Token{...}}

Retrieve the token using a refresh token:

iex> credentials = "credentials.json" |> File.read!() |> Jason.decode!()
iex> Goth.Token.fetch(source: {:refresh_token, credentials})
{:ok, %Goth.Token{...}}

You can generate a credentials file containing refresh token using gcloud utility like this:

$ gcloud auth application-default login

Retrieve the token using the Google metadata server:

iex> Goth.Token.fetch(source: :metadata)
{:ok, %Goth.Token{...}}

See Storing and retrieving instance metadata for more information on metadata server.

Passing custom Finch options

iex> Goth.Token.fetch(source: source, http_client: {:finch, pool_timeout: 5000})
{:ok, %Goth.Token{...}}
Link to this function

for_scope(info, sub \\ nil)

View Source
This function is deprecated. Use Goth.fetch/1 instead.
@spec for_scope(scope :: String.t(), sub :: String.t() | nil) ::
  {:ok, t()} | {:error, any()}
@spec for_scope(info :: {String.t() | atom(), String.t()}, sub :: String.t() | nil) ::
  {:ok, t()} | {:error, any()}