Closed apognu closed 3 years ago
Currently, Goth doesn't support multiple accounts, unfortunately. I definitely think it's worth adding, and would be happy to accept an PR that adds that functionality.
I'll take a look at implementing this when I get a chance.
I should mention that Goth does, however, allow you to pass in "the email address of the user for which the application is requesting delegated access" as a second argument to certain functions like Token.for_scope/2
(this optional email address will be added as a sub
claim on the JWT that is generated when requesting a token from the API). This will allow your application to make authenticated requests on behalf of another user:
{:ok, token} =
Goth.Token.for_scope(
"https://www.googleapis.com/auth/pubsub",
"delegating-user@example.com"
)
See https://developers.google.com/identity/protocols/OAuth2ServiceAccount#additionalclaims for details on how the sub
claim works.
The argument for Token.for_scope/2
serves its own purpose, but as I understand it, it is used to impersonate a user for the same project. What I am looking for a a way to parse, store and use credentials from projects that might have nothing to do with each other.
I might find some time to craft a PR around this, but my guess is this would change the anatomy of the project quite a lot, so it may warrant some discussion beforehand.
The way I imagined it would be using a credentials file in the form of a JSON array instead of plain maps in that particular case. Something like this:
[
{
"client_email": "xxx@project.iam.gserviceaccount.com",
...
},
{
"client_email", "yyy@project.iam.gserviceaccount.com",
...
}
]
All internals would then allow for a new argument, which would specify which service account it targets, while still keeping compatibility with regular-shape credentials file transparently (some kind of default for when only one service account is specified).
This would still allow the sub
parametter, to be able to impersonate a user from each of the service account.
What do you think?
I have something that works, I'll submit a PR when I get home tonight.
I would also love this functionality. Let me know if I can assist with the PR.
The PR I submitted should cover it. Waiting for merge or comment.
From reading the current source code, looks like it should be possible with:
# config.ex
config :goth, json: "[]"
# client.ex
config = "new.json" |> File.read!() |> Poison.decode!()
Goth.Config.add_config(config)
{:ok, token} = Goth.Token.for_scope({ config["client_email"], "https://www.googleapis.com/auth/..." })
Hey, guys. Allow me to introduce you a new repo that I created to resolve this issue, Gotham
we can put current service account into process dictionary, thus make our APIs invoking more naturally.
Welcome for any criticism and PR, any time.
Honestly, I believe this issue is actually resolved by #41 and should probably be closed.
@xingxing can you help me understand what problem Gotham solves that #41 doesn't?
Honestly, I believe this issue is actually resolved by #41 and should probably be closed.
@xingxing can you help me understand what problem Gotham solves that #41 doesn't?
Hi @peburrows, #41 requires to add at least one parameter/option (sub) to every method you need applying multiple GCP service accounts.
That seems OK for this single library, but what if you want to make some library where used Goth (e.g. kane) to support multiple service accounts, that will be come to a nightmare. I found so many option/sub-sentence need to add, actually, I have tried to deal with it (peburrows/kane#27) and given up when I thought we can do it better.
Usage looks like:
config :gotham,
default_account: :account1,
accounts: [
{:account1, file_path: "path/to/google/json/creds.json"},
{:account2, file_path: "path/to/google/json/creds.json"}
]
# Use default account
{:ok, token} = Gotham.for_scope("https://www.googleapis.com/auth/pubsub")
%Gotham.Token{
project_id: "test",
access_token: "TOKEN",
account_name: :account1,
expire_at: 1561090622,
scope: "https://www.googleapis.com/auth/pubsub",
token_type: "Bearer"
}
# Change acocunt
Gotham.put_account_name(:account2)
Gotham.for_scope("https://www.googleapis.com/auth/pubsub")
{:ok,
%Gotham.Token{
project_id: "test",
access_token: "TOKEN",
account_name: :account2,
expire_at: 1561092261,
scope: "https://www.googleapis.com/auth/pubsub",
token_type: "Bearer"
}}
# Run a function with a specific account
Gotham.with_account_name(:account2, fn ->
Gotham.for_scope("https://www.googleapis.com/auth/pubsub")
end)
{:ok,
%Gotham.Token{
project_id: "test",
access_token: "TOKEN",
account_name: :account2,
expire_at: 1561092261,
scope: "https://www.googleapis.com/auth/pubsub",
token_type: "Bearer"
}}
Hi @all,
Any update on this one. I need to load the account info dynamically. Please Let me know if somebody found and any solution or workaround for this.
Hi @ALL,
Any update on this one. I need to load the account info dynamically. Please Let me know if somebody found and any solution or workaround for this.
Let's check my repo https://github.com/xingxing/gotham, hopefully it can solve your requirement.
That's my solution in case that helps.
Closing in favour or #82.
Is there a way to use different service account (possibly related to completely different projects)?
In the context of my current project, I need to call the Google APIs as a dozen different users in order to retrieve data from all my projects. Does the feature already exist?
Thanks.