Tweak google, unify callback endpoint

This commit is contained in:
shamoon 2024-10-04 11:30:33 -07:00
parent 9cef15313e
commit 1610bab0d8
4 changed files with 54 additions and 43 deletions

View File

@ -13,7 +13,7 @@
<button type="button" class="btn btn-sm btn-outline-primary ms-4" (click)="editMailAccount()" *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.MailAccount }"> <button type="button" class="btn btn-sm btn-outline-primary ms-4" (click)="editMailAccount()" *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.MailAccount }">
<i-bs name="plus-circle"></i-bs>&nbsp;<ng-container i18n>Add Account</ng-container> <i-bs name="plus-circle"></i-bs>&nbsp;<ng-container i18n>Add Account</ng-container>
</button> </button>
<a class="btn btn-sm btn-outline-primary ms-2" [href]="googleOAuthUrl" target="_blank" i18n>Connect with Google</a> <a class="btn btn-sm btn-outline-primary ms-2" [href]="googleOAuthUrl" i18n>Connect with Google</a>
</h4> </h4>
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item"> <li class="list-group-item">

View File

@ -1558,8 +1558,8 @@ class UiSettingsView(GenericAPIView):
def generate_google_oauth_url(self) -> str: def generate_google_oauth_url(self) -> str:
token_request_uri = "https://accounts.google.com/o/oauth2/auth" token_request_uri = "https://accounts.google.com/o/oauth2/auth"
response_type = "code" response_type = "code"
client_id = settings.GOOGLE_OAUTH_CLIENT_ID client_id = settings.GMAIL_OAUTH_CLIENT_ID
redirect_uri = "http://localhost:8000/api/oauth/google/callback/" redirect_uri = "http://localhost:8000/api/oauth/callback/"
scope = "https://mail.google.com/" scope = "https://mail.google.com/"
access_type = "offline" access_type = "offline"
url = f"{token_request_uri}?response_type={response_type}&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&access_type={access_type}" url = f"{token_request_uri}?response_type={response_type}&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&access_type={access_type}"
@ -1595,7 +1595,7 @@ class UiSettingsView(GenericAPIView):
ui_settings["auditlog_enabled"] = settings.AUDIT_LOG_ENABLED ui_settings["auditlog_enabled"] = settings.AUDIT_LOG_ENABLED
if settings.GOOGLE_OAUTH_ENABLED: if settings.GMAIL_OAUTH_ENABLED:
ui_settings["google_oauth_url"] = self.generate_google_oauth_url() ui_settings["google_oauth_url"] = self.generate_google_oauth_url()
user_resp = { user_resp = {
@ -2146,23 +2146,36 @@ class TrashView(ListModelMixin, PassUserMixin):
# Outlook https://stackoverflow.com/questions/73902642/office-365-imap-authentication-via-oauth2-and-python-msal-library # Outlook https://stackoverflow.com/questions/73902642/office-365-imap-authentication-via-oauth2-and-python-msal-library
class GoogleOauthCallbackView(GenericAPIView): class OauthCallbackView(GenericAPIView):
# permission_classes = (AllowAny,) # permission_classes = (AllowAny,)
def get(self, request, format=None): def get(self, request, format=None):
# Guide: https://postmansmtp.com/how-to-configure-post-smtp-with-gmailgsuite-using-oauth/ # Gmail setup guide: https://postmansmtp.com/how-to-configure-post-smtp-with-gmailgsuite-using-oauth/
# http://localhost:4200/api/oauth/google/callback?code=4%2F0AQlEd8yxIwqjz95p82tWMq4ogn4KxRdprtjjGqjEHW4x7X1roEgswzn9EfiAit1cOLfSog&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=0&hd=michaelshamoon.com&prompt=consent # Outlok setup guide: https://medium.com/@manojkumardhakad/python-read-and-send-outlook-mail-using-oauth2-token-and-graph-api-53de606ecfa1
code = request.query_params.get("code") code = request.query_params.get("code")
if code is None: scope = request.query_params.get("scope")
return HttpResponseBadRequest("Code required") if code is None or scope is None:
logger.error(
f"Invalid oauth callback request, code: {code}, scope: {scope}",
)
return HttpResponseBadRequest("Invalid request, see logs for more detail")
if "google" in scope:
# Google
imap_server = "imap.gmail.com"
defaults = {
"name": f"Gmail {datetime.now()}",
"username": "",
"imap_security": MailAccount.ImapSecurity.SSL,
"imap_port": 993,
}
token_request_uri = "https://accounts.google.com/o/oauth2/token" token_request_uri = "https://accounts.google.com/o/oauth2/token"
client_id = settings.GOOGLE_OAUTH_CLIENT_ID client_id = settings.GMAIL_OAUTH_CLIENT_ID
client_secret = settings.GOOGLE_OAUTH_CLIENT_SECRET client_secret = settings.GMAIL_OAUTH_CLIENT_SECRET
redirect_uri = "http://localhost:8000/api/oauth/google/callback/" redirect_uri = "http://localhost:8000/api/oauth/callback/"
grant_type = "authorization_code" grant_type = "authorization_code"
scope = "https://mail.google.com/" scope = "https://mail.google.com/"
url = f"{token_request_uri}"
data = { data = {
"code": code, "code": code,
"client_id": client_id, "client_id": client_id,
@ -2174,8 +2187,11 @@ class GoogleOauthCallbackView(GenericAPIView):
headers = { headers = {
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
} }
response = httpx.post(url, data=data, headers=headers) response = httpx.post(token_request_uri, data=data, headers=headers)
data = response.json() data = response.json()
elif "outlook" in scope:
data = {}
if "error" in data: if "error" in data:
return HttpResponseBadRequest(data["error"]) return HttpResponseBadRequest(data["error"])
elif "access_token" in data: elif "access_token" in data:
@ -2186,13 +2202,8 @@ class GoogleOauthCallbackView(GenericAPIView):
account, _ = MailAccount.objects.update_or_create( account, _ = MailAccount.objects.update_or_create(
password=access_token, password=access_token,
is_token=True, is_token=True,
imap_server="imap.gmail.com", imap_server=imap_server,
defaults={ defaults=defaults,
"name": f"Gmail {datetime.now()}",
"username": "",
"imap_security": MailAccount.ImapSecurity.SSL,
"imap_port": 993,
},
) )
return HttpResponseRedirect( return HttpResponseRedirect(

View File

@ -1200,6 +1200,6 @@ EMPTY_TRASH_DELAY = max(__get_int("PAPERLESS_EMPTY_TRASH_DELAY", 30), 1)
############################################################################### ###############################################################################
# Oauth Email Providers # # Oauth Email Providers #
############################################################################### ###############################################################################
GOOGLE_OAUTH_CLIENT_ID = os.getenv("PAPERLESS_GOOGLE_OAUTH_CLIENT_ID") GMAIL_OAUTH_CLIENT_ID = os.getenv("PAPERLESS_GMAIL_OAUTH_CLIENT_ID")
GOOGLE_OAUTH_CLIENT_SECRET = os.getenv("PAPERLESS_GOOGLE_OAUTH_CLIENT_SECRET") GMAIL_OAUTH_CLIENT_SECRET = os.getenv("PAPERLESS_GMAIL_OAUTH_CLIENT_SECRET")
GOOGLE_OAUTH_ENABLED = bool(GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET) GMAIL_OAUTH_ENABLED = bool(GMAIL_OAUTH_CLIENT_ID and GMAIL_OAUTH_CLIENT_SECRET)

View File

@ -22,9 +22,9 @@ from documents.views import CorrespondentViewSet
from documents.views import CustomFieldViewSet from documents.views import CustomFieldViewSet
from documents.views import DocumentTypeViewSet from documents.views import DocumentTypeViewSet
from documents.views import GlobalSearchView from documents.views import GlobalSearchView
from documents.views import GoogleOauthCallbackView
from documents.views import IndexView from documents.views import IndexView
from documents.views import LogViewSet from documents.views import LogViewSet
from documents.views import OauthCallbackView
from documents.views import PostDocumentView from documents.views import PostDocumentView
from documents.views import RemoteVersionView from documents.views import RemoteVersionView
from documents.views import SavedViewViewSet from documents.views import SavedViewViewSet
@ -167,9 +167,9 @@ urlpatterns = [
name="trash", name="trash",
), ),
re_path( re_path(
r"^oauth/google/callback/", r"^oauth/callback/",
GoogleOauthCallbackView.as_view(), OauthCallbackView.as_view(),
name="google_oauth_callback", name="oauth_callback",
), ),
*api_router.urls, *api_router.urls,
], ],