A person's own Google account, as a value: the app you registered, and the refresh token they gave it.
The sibling of Sheetshow.ServiceAccount, and a client takes either. A
service account is a robot with a private key and its own email address, which
a spreadsheet has to be shared with; a user account acts as the person who
signed in, and sees the spreadsheets they see. Both are credentials
Sheetshow.connect/1 turns into a Sheetshow.Token, and nothing downstream
of that knows the difference.
iex> account = Sheetshow.UserAccount.new("123.apps.googleusercontent.com", "secret")
iex> Sheetshow.UserAccount.authorized?(account)
falseIt has two stages, which is why refresh_token may be nil. A new account is
the app's own credentials and nothing else, which is enough to send somebody
to a consent screen, which is Sheetshow.OAuth's half of the job. What comes back
from Sheetshow.OAuth.authorize/3 is the same account with a refresh token on
it, and that is the thing worth keeping.
That pair of stages is not an invention: it is exactly the shape of the
authorized_user JSON that gcloud writes, so from_file/1 reads a file
gcloud auth application-default login made, and to_json/1 writes one
anything else that reads the format will take.
Inspecting an account shows neither the secret nor the refresh token.
Summary
Functions
Whether this account can get a token on its own, that is, whether somebody has been through the consent screen for it.
Reads an authorized_user credential file. The path is yours to supply, and
nothing about it is remembered.
Same as from_file/1, raising on failure.
Reads the JSON of an authorized_user credential.
Same as from_json/1, raising on failure.
An account from the client id and secret of an app you registered in the Google Cloud console.
The account as authorized_user JSON, to write somewhere only you can read.
Where that is, and how it is protected, is your application's business.
The token request as data, where to post and what to post, for whichever HTTP client is doing the talking. An account with no refresh token has nothing to ask with, and says so.
Types
Functions
Whether this account can get a token on its own, that is, whether somebody has been through the consent screen for it.
iex> Sheetshow.UserAccount.new("123", "s") |> Sheetshow.UserAccount.authorized?()
false
@spec from_file(Path.t()) :: {:ok, t()} | {:error, Sheetshow.Error.t()}
Reads an authorized_user credential file. The path is yours to supply, and
nothing about it is remembered.
Same as from_file/1, raising on failure.
@spec from_json(String.t()) :: {:ok, t()} | {:error, Sheetshow.Error.t()}
Reads the JSON of an authorized_user credential.
iex> json = ~s({"type":"authorized_user","client_id":"123","client_secret":"s","refresh_token":"1//r"})
iex> {:ok, account} = Sheetshow.UserAccount.from_json(json)
iex> account.client_id
"123"
iex> {:error, %Sheetshow.Error{reason: :invalid_credentials}} =
...> Sheetshow.UserAccount.from_json(~s({"type": "service_account"}))
Same as from_json/1, raising on failure.
An account from the client id and secret of an app you registered in the Google Cloud console.
Options: :refresh_token, when you already hold one, and :token_uri.
iex> account = Sheetshow.UserAccount.new("123.apps.googleusercontent.com", "s", refresh_token: "1//r")
iex> Sheetshow.UserAccount.authorized?(account)
true
The account as authorized_user JSON, to write somewhere only you can read.
Where that is, and how it is protected, is your application's business.
iex> Sheetshow.UserAccount.new("123", "s", refresh_token: "1//r")
...> |> Sheetshow.UserAccount.to_json()
...> |> JSON.decode!()
...> |> Map.get("type")
"authorized_user"
@spec token_request(t()) :: {:ok, %{url: String.t(), form: map()}} | {:error, Sheetshow.Error.t()}
The token request as data, where to post and what to post, for whichever HTTP client is doing the talking. An account with no refresh token has nothing to ask with, and says so.
Sheetshow.UserAccount.token_request(account)
{:ok, %{
url: "https://oauth2.googleapis.com/token",
form: %{grant_type: "refresh_token", refresh_token: "1//r", client_id: "123", client_secret: "s"}
}}