Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server-to-server Oauth ? #152

Open
mboisson opened this issue Nov 1, 2023 · 7 comments
Open

Server-to-server Oauth ? #152

mboisson opened this issue Nov 1, 2023 · 7 comments
Labels
help wanted Extra attention is needed

Comments

@mboisson
Copy link

mboisson commented Nov 1, 2023

Hi,
The Zoom API supports what they call "Server-to-server Oauth", which does not seem to require a call back URL. Can this be supported ?

@mboisson
Copy link
Author

mboisson commented Nov 1, 2023

@licht1stein
Copy link
Owner

licht1stein commented Nov 1, 2023

Hi, this is already built in. To generate credentials locally just run in your terminal:

python -c "from pyzoom import oauth_wizard; oauth_wizard()"

And follow the instructions.

@licht1stein
Copy link
Owner

Ok, I read more carefully. We don't have support for s2s-oauth, only normal oauth. If you want you can make a PR to add it.

@owen9825
Copy link
Contributor

Example of how to use it https://www.makeuseof.com/generate-server-to-server-oauth-zoom-meeting-link-python/

Thanks, I've used it here, which other people might also like to use as a base 🙂 https://github.com/owen9825/zoom_attendance

@licht1stein
Copy link
Owner

@owen9825

So basically we need something similar to this as one of the ways to initialise the ZoomClient?

def get_access_token(account_id: str) -> Optional[str]:
    # https://developers.zoom.us/docs/internal-apps/s2s-oauth/
    client_id = os.getenv("ZOOM_CLIENT_ID")
    client_secret = os.getenv("ZOOM_CLIENT_SECRET")
    # https://www.makeuseof.com/generate-server-to-server-oauth-zoom-meeting-link-python/
    data = {
        "grant_type": "account_credentials",
        "account_id": account_id,
        "client_secret": client_secret,
    }
    headers = {"Host": "zoom.us"}
    response = requests.post(
        auth_token_url, auth=(client_id, client_secret), data=data, headers=headers
    )
    if not response.ok:
        logger.warning(
            "There was an error (%s) authenticating at %s: %s",
            response.status_code,
            response.url,
            response.text,
        )
        return None
    body = response.json()
    return body.get("access_token")

@licht1stein licht1stein added the help wanted Extra attention is needed label Mar 11, 2024
@mboisson
Copy link
Author

I forgot I had opened this, but we ended-up developing our own class for interfacing with Zoom. Here is the portion of the class code for getting the authorization headers:

    auth_token_url = "https://zoom.us/oauth/token"
    api_base_url = "https://api.zoom.us/v2"


    def __init__(self, account_id, client_id, client_secret, timezone = "America/Montreal", user = "me"):
        '''Initialize the Zoom interface object with API credentials

        Reference: https://developers.zoom.us/docs/zoom-rooms/s2s-oauth/

        Arguments:
            account_id -- string. Usually stored secretly
            client_id -- string. Usually stored secretly
            client_secret -- string. Usually stored secretly
            timezone -- string. Valid values are in all_timezones from pytz
                https://pythonhosted.org/pytz/#helpers
            user -- string. Zoom username, either email address or "me"
        '''

        self.account_id = account_id
        self.client_id = client_id
        self.client_secret = client_secret
        self.timezone = timezone
        self.user = user


    def get_authorization_header(self):
        '''Get the OAuth temporary authorization token

        Reference:
            https://developers.zoom.us/docs/zoom-rooms/s2s-oauth/
            https://www.makeuseof.com/generate-server-to-server-oauth-zoom-meeting-link-python/

        Returns: dictionary with keys "Authorization" and "Content-Type"
        '''

        response = requests.post(
            self.auth_token_url,
            auth=(self.client_id, self.client_secret),
            data={
                "grant_type": "account_credentials",
                "account_id": self.account_id,
                "client_secret": self.client_secret
            })

        response_data = response.json()

        assert response.status_code == 200, response_data['message']

        access_token = response_data["access_token"]
        headers = {
            "Authorization": f"Bearer {access_token}",
            "Content-Type": "application/json"
        }

        return headers

Then it can be used, for example:

    def create_meeting(self, topic, duration, start_date, start_time):
        headers = self.get_authorization_header()

        # https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/meetingCreate
        payload = {
            "topic": topic,
            #"schedule_for": "user@a",
            #"alternative_hosts": "a,b,c,d",
            "duration": duration,
            #"host_video": true,
            #"jbh_time": 5,
            #"join_before_host": "true",
            'start_time': f'{start_date}T{start_time}',
            "timezone": self.timezone,
            "type": 2,
        }

        resp = requests.post(f"{self.api_base_url}/users/{self.user}/meetings",
                             headers=headers,
                             json=payload)

        if resp.status_code!=201:
            print("Unable to generate meeting link")
        response_data = resp.json()

        content = {
                    "meeting_url": response_data["join_url"],
                    "password": response_data["password"],
                    "meetingTime": response_data["start_time"],
                    "purpose": response_data["topic"],
                    "duration": response_data["duration"],
                    "message": "Success",
                    "status":1
        }
        return content

@owen9825
Copy link
Contributor

@owen9825

So basically we need something similar to this as one of the ways to initialise the ZoomClient?

def get_access_token(account_id: str) -> Optional[str]:
    # https://developers.zoom.us/docs/internal-apps/s2s-oauth/
    client_id = os.getenv("ZOOM_CLIENT_ID")
    client_secret = os.getenv("ZOOM_CLIENT_SECRET")
    # https://www.makeuseof.com/generate-server-to-server-oauth-zoom-meeting-link-python/
    data = {
        "grant_type": "account_credentials",
        "account_id": account_id,
        "client_secret": client_secret,
    }
    headers = {"Host": "zoom.us"}
    response = requests.post(
        auth_token_url, auth=(client_id, client_secret), data=data, headers=headers
    )
    if not response.ok:
        logger.warning(
            "There was an error (%s) authenticating at %s: %s",
            response.status_code,
            response.url,
            response.text,
        )
        return None
    body = response.json()
    return body.get("access_token")

sorry, I've finished work on this. I don't wish to return to it and go through the implementation a 2nd time. All the best

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants