Skip to content

Commit

Permalink
Source Google Directory #6265 - add oauth support
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaliizazmic committed Oct 27, 2021
1 parent 19f2541 commit 7e93198
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,54 @@
import json
from abc import ABC, abstractmethod
from functools import partial
from typing import Callable, Dict, Iterator, Sequence
from typing import Callable, Dict, Iterator, Sequence, Mapping, Any

import backoff
from google.oauth2 import service_account
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import Resource, build
from googleapiclient.errors import HttpError as GoogleApiHttpError
from google.auth.transport.requests import Request

from .utils import rate_limit_handling

SCOPES = ["https://www.googleapis.com/auth/admin.directory.user.readonly", "https://www.googleapis.com/auth/admin.directory.group.readonly"]


class API:
def __init__(self, credentials_json: str, email: str):
def __init__(self, credentials: Mapping[str, Any]):
self._creds = None
self._credentials_json = credentials_json
self._admin_email = email
self._raw_credentials = credentials

def _load_account_info(self) -> Dict:
account_info = json.loads(self._credentials_json)
@staticmethod
def _load_account_info(credentials_json: str) -> Dict:
account_info = json.loads(credentials_json)
return account_info

def _obtain_creds(self) -> service_account.Credentials:
account_info = self._load_account_info()
def _obtain_service_account_creds(self) -> service_account.Credentials:
credentials_json = self._raw_credentials.get("credentials_json")
admin_email = self._raw_credentials.get("email")
account_info = self._load_account_info(credentials_json)
creds = service_account.Credentials.from_service_account_info(account_info, scopes=SCOPES)
self._creds = creds.with_subject(self._admin_email)
self._creds = creds.with_subject(admin_email)

def _obtain_web_app_creds(self) -> Credentials:
info = {
"client_id": self._raw_credentials.get("client_id"),
"client_secret": self._raw_credentials.get("client_secret"),
"refresh_token": self._raw_credentials.get("refresh_token"),
"scopes": self._raw_credentials.get("scopes"),
}
creds = Credentials.from_authorized_user_info(info)
if creds.expired:
creds.refresh(Request())
self._creds = creds

def _obtain_creds(self):
if "credentials_json" in self._raw_credentials:
self._obtain_service_account_creds()
elif "client_id" and "client_secret" in self._raw_credentials:
self._obtain_web_app_creds()

def _construct_resource(self) -> Resource:
if not self._creds:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@


class Client(BaseClient):
def __init__(self, credentials_json: str, email: str):
self._api = API(credentials_json, email)
def __init__(self, credentials: Mapping[str, Any]):
self._api = API(credentials)
self._apis = {"users": UsersAPI(self._api), "groups": GroupsAPI(self._api), "group_members": GroupMembersAPI(self._api)}
super().__init__()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,95 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Google Directory Spec",
"type": "object",
"required": ["credentials_json", "email"],
"required": ["credentials"],
"additionalProperties": false,
"properties": {
"credentials_json": {
"type": "string",
"description": "The contents of the JSON service account key. See the <a href=\"https://developers.google.com/admin-sdk/directory/v1/guides/delegation\">docs</a> for more information on how to generate this key.",
"airbyte_secret": true
},
"email": {
"type": "string",
"description": "The email of the user, which has permissions to access the Google Workspace Admin APIs."
"credentials": {
"title": "Google Credentials",
"description": "Google APIs use the OAuth 2.0 protocol for authentication and authorization. The Source supports <a href=\"https://developers.google.com/identity/protocols/oauth2#webserver\" target=\"_blank\">Web server application</a> and <a href=\"https://developers.google.com/identity/protocols/oauth2#serviceaccount\" target=\"_blank\">Service accounts</a> scenarios",
"type": "object",
"oneOf": [
{
"title": "Web server application",
"description": "For these scenario user only needs to give permission to read Google Directory data",
"type": "object",
"required": ["client_id", "client_secret", "refresh_token", "scopes"],
"properties": {
"credentials_title": {
"type": "string",
"title": "Credentials title",
"description": "Authentication scenario",
"const": "Web server app",
"enum": ["Web server app"],
"default": "Web server app",
"order": 0
},
"client_id": {
"title": "Client ID",
"type": "string",
"description": "The client ID of developer application",
"airbyte_secret": true
},
"client_secret": {
"title": "Client secret",
"type": "string",
"description": "The client secret of developer application",
"airbyte_secret": true
},
"refresh_token": {
"title": "Refresh Token",
"type": "string",
"description": "The token for obtaining new access token",
"airbyte_secret": true
},
"scopes": {
"title": "Scopes",
"type": "string",
"description": "The scopes used to obtain authorization separated by space."
}
}
},
{
"title": "Service accounts",
"description": "For these scenario user should obtain service account's credentials from the Google API Console and provide delegated email",
"type": "object",
"required": ["credentials_json", "email"],
"properties": {
"credentials_title": {
"type": "string",
"title": "Credentials title",
"description": "Authentication scenario",
"const": "Service accounts",
"enum": ["Service accounts"],
"default": "Service accounts",
"order": 0
},
"credentials_json": {
"type": "string",
"title": "Credentials JSON",
"description": "The contents of the JSON service account key. See the <a href=\"https://developers.google.com/admin-sdk/directory/v1/guides/delegation\">docs</a> for more information on how to generate this key.",
"airbyte_secret": true
},
"email": {
"type": "string",
"title": "Email",
"description": "The email of the user, which has permissions to access the Google Workspace Admin APIs."
}
}
}
]
}
}
},
"authSpecification": {
"auth_type": "oauth2.0",
"oauth2Specification": {
"rootObject": ["credentials", 0],
"oauthFlowInitParameters": [
["client_id"],
["client_secret"]
],
"oauthFlowOutputParameters": [["access_token"], ["refresh_token"]]
}
}
}

0 comments on commit 7e93198

Please sign in to comment.