forked from MeltanoLabs/tap-gmail
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerate_refresh_token.py
executable file
·149 lines (127 loc) · 5 KB
/
generate_refresh_token.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env python
#
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Modified from: https://github.com/googleads/googleads-python-lib/blob/master/examples/adwords/authentication/generate_refresh_token.py
"""Generates refresh token for Gmail using the Installed Application flow."""
import argparse
import sys
from google_auth_oauthlib.flow import InstalledAppFlow
from oauthlib.oauth2.rfc6749.errors import InvalidGrantError
# Your OAuth2 Client ID and Secret. If you do not have an ID and Secret yet,
# please go to https://console.developers.google.com and create a set.
DEFAULT_CLIENT_ID = None
DEFAULT_CLIENT_SECRET = None
# The Gmail API OAuth2 scope.
SCOPE = "https://www.googleapis.com/auth/gmail.readonly"
# The redirect URI set for the given Client ID. The redirect URI for Client ID
# generated for an installed application will always have this value.
_REDIRECT_URI = "http://localhost"
parser = argparse.ArgumentParser(
description="Generates a refresh token with " "the provided credentials."
)
parser.add_argument(
"--client_id",
default=DEFAULT_CLIENT_ID,
help="Client Id retrieved from the Developer's Console.",
)
parser.add_argument(
"--client_secret",
default=DEFAULT_CLIENT_SECRET,
help="Client Secret retrieved from the Developer's " "Console.",
)
parser.add_argument(
"--additional_scopes",
default=None,
help="Additional scopes to apply when generating the "
"refresh token. Each scope should be separated by a comma.",
)
class ClientConfigBuilder(object):
"""Helper class used to build a client config dict used in the OAuth 2.0 flow."""
_DEFAULT_AUTH_URI = "https://accounts.google.com/o/oauth2/auth"
_DEFAULT_TOKEN_URI = "https://accounts.google.com/o/oauth2/token"
CLIENT_TYPE_WEB = "web"
CLIENT_TYPE_INSTALLED_APP = "installed"
def __init__(
self,
client_type=None,
client_id=None,
client_secret=None,
auth_uri=_DEFAULT_AUTH_URI,
token_uri=_DEFAULT_TOKEN_URI,
):
self.client_type = client_type
self.client_id = client_id
self.client_secret = client_secret
self.auth_uri = auth_uri
self.token_uri = token_uri
def Build(self):
"""Builds a client config dictionary used in the OAuth 2.0 flow."""
if all(
(
self.client_type,
self.client_id,
self.client_secret,
self.auth_uri,
self.token_uri,
)
):
client_config = {
self.client_type: {
"client_id": self.client_id,
"client_secret": self.client_secret,
"auth_uri": self.auth_uri,
"token_uri": self.token_uri,
}
}
else:
raise ValueError("Required field is missing.")
return client_config
def main(client_id, client_secret, scopes):
"""Retrieve and display the access and refresh token."""
client_config = ClientConfigBuilder(
client_type=ClientConfigBuilder.CLIENT_TYPE_WEB,
client_id=client_id,
client_secret=client_secret,
)
flow = InstalledAppFlow.from_client_config(client_config.Build(), scopes=scopes)
# Note that from_client_config will not produce a flow with the
# redirect_uris (if any) set in the client_config. This must be set
# separately.
flow.redirect_uri = _REDIRECT_URI
auth_url, _ = flow.authorization_url(prompt="consent")
print(
"Log into the Google Account you use to access your Gmail account "
"and go to the following URL: \n%s\n" % auth_url
)
print("After approving the token enter the verification code (if specified).")
code = input("Code: ").strip()
try:
flow.fetch_token(code=code)
except InvalidGrantError as ex:
print("Authentication has failed: %s" % ex)
sys.exit(1)
print("Access token: %s" % flow.credentials.token)
print("Refresh token: %s" % flow.credentials.refresh_token)
if __name__ == "__main__":
args = parser.parse_args()
configured_scopes = [SCOPE]
if not (
any([args.client_id, DEFAULT_CLIENT_ID])
and any([args.client_secret, DEFAULT_CLIENT_SECRET])
):
raise AttributeError("No client_id or client_secret specified.")
if args.additional_scopes:
configured_scopes.extend(args.additional_scopes.replace(" ", "").split(","))
main(args.client_id, args.client_secret, configured_scopes)