Skip to content

Commit

Permalink
[MS Teams] support reset_graph_auth (#29644)
Browse files Browse the repository at this point in the history
* fixed

* pre-commit

* update
  • Loading branch information
michal-dagan committed Sep 13, 2023
1 parent 0784ed7 commit 04da43f
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 24 deletions.
39 changes: 26 additions & 13 deletions Packs/MicrosoftTeams/Integrations/MicrosoftTeams/MicrosoftTeams.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@
EXTERNAL_FORM = "external/form"
MAX_SAMPLES = 10

TOKEN_EXPIRED_ERROR_CODES = {50173, 700082, } # See: https://login.microsoftonline.com/error?code=
REGEX_SEARCH_ERROR_DESC = r"^[^:]*:\s(?P<desc>.*?\.)"


class Handler:
@staticmethod
Expand Down Expand Up @@ -135,19 +138,9 @@ def error_parser(resp_err: requests.Response, api: str = 'graph') -> str:
response: dict = resp_err.json()
demisto.debug(f"Error response from {api=}: {response=}")
if api == 'graph':

# AADSTS50173 points to password change https://login.microsoftonline.com/error?code=50173.
# In that case, the integration context should be overwritten
# and the user should execute the auth process from the beginning.
if "AADSTS50173" in response.get('error_description', ''):
integration_context: dict = get_integration_context()
integration_context['current_refresh_token'] = ''
integration_context['graph_access_token'] = ''
set_integration_context(integration_context)
demisto.debug("Detected Error: AADSTS50173, Successfully reset the current_refresh_token and graph_access_token.")
raise DemistoException(
"The account password has been changed or reset. Please regenerate the 'Authorization code' "
"parameter and then run !microsoft-teams-auth-test to re-authenticate")
error_codes = response.get("error_codes", [""])
if set(error_codes).issubset(TOKEN_EXPIRED_ERROR_CODES):
reset_graph_auth(error_codes, response.get('error_description', ''))

error = response.get('error', {})
err_str = (f"{error.get('code', '')}: {error.get('message', '')}" if isinstance(error, dict)
Expand All @@ -164,6 +157,26 @@ def error_parser(resp_err: requests.Response, api: str = 'graph') -> str:
return resp_err.text


def reset_graph_auth(error_codes: list, error_desc: str):
"""
Reset the Graph API authorization in the integration context.
This function clears the current authorization data and informs the user to regenerate the Authorization code.
:raises DemistoException: Raised with a message instructing the user to regenerate the authorization code.
"""
integration_context: dict = get_integration_context()

integration_context['current_refresh_token'] = ''
integration_context['graph_access_token'] = ''
integration_context['graph_valid_until'] = ''
set_integration_context(integration_context)

demisto.debug(f"Detected Error: {error_codes}, Successfully reset the current_refresh_token and graph_access_token.")
re_search = re.search(REGEX_SEARCH_ERROR_DESC, error_desc)
err_str = re_search['desc'] if re_search else ""
raise DemistoException(f"{err_str} Please regenerate the 'Authorization code' "
"parameter and then run !microsoft-teams-auth-test to re-authenticate")


def translate_severity(severity: str) -> float:
"""
Translates Demisto text severity to int severity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ script:
name: external_form_url_header
description: |-
Sends a message to the specified teams.
To mention a user in the message, add a semicolon ";" at the end of the user mention. For example: @Bruce Willis;
To mention a user in the message, add a semicolon ";" at the end of the user mention. For example: @Bruce Willis;.
name: send-notification
- arguments:
- auto: PREDEFINED
Expand Down Expand Up @@ -228,7 +228,7 @@ script:
description: Creates a new channel in a Microsoft Teams team.
name: create-channel
- arguments:
- description: The channel to which to add the add the member to this channel
- description: The channel to which to add the add the member to this channel.
name: channel
required: true
- description: The channel's team.
Expand Down Expand Up @@ -417,7 +417,7 @@ script:
description: Represents details about an online meeting. If the chat isn't associated with an online meeting, the property is empty.
type: String
- arguments:
- description: The chat ID / group chat name (topic) / oneOnOne member (Display name/mail/UPN)
- description: The chat ID / group chat name (topic) / oneOnOne member (Display name/mail/UPN).
name: chat
required: true
- description: The content of the chat message.
Expand Down Expand Up @@ -523,7 +523,7 @@ script:
description: Adds a member (user) to a group chat.
name: microsoft-teams-chat-add-user
- arguments:
- description: The chat ID / group chat name (topic) / oneOnOne member (Display name/mail/UPN)
- description: The chat ID / group chat name (topic) / oneOnOne member (Display name/mail/UPN).
name: chat
required: true
description: Retrieves a list of members from a chat.
Expand Down Expand Up @@ -554,7 +554,7 @@ script:
description: The timestamp denoting how far back a conversation's history is shared with the conversation member.
type: String
- arguments:
- description: The chat ID / group chat name (topic) / oneOnOne member (Display name/mail/UPN)
- description: The chat ID / group chat name (topic) / oneOnOne member (Display name/mail/UPN).
name: chat
required: true
- description: The number of results to retrieve.
Expand Down Expand Up @@ -648,7 +648,7 @@ script:
description: Used if an operation returns partial results. If a response contains a NextLink element, its value specifies a starting point to use for subsequent calls.
type: String
- arguments:
- description: The chat ID / group chat name (topic) / oneOnOne member (Display name/mail/UPN)
- description: The chat ID / group chat name (topic) / oneOnOne member (Display name/mail/UPN).
name: chat
- description: "Filters results. For example: topic eq 'testing'. For more query examples, see https://learn.microsoft.com/en-us/graph/filter-query-parameter?tabs=http. "
name: filter
Expand Down Expand Up @@ -711,7 +711,7 @@ script:
- description: Generate the login url used for Authorization code flow.
name: microsoft-teams-generate-login-url
arguments: []
dockerimage: demisto/teams:1.0.0.69030
dockerimage: demisto/teams:1.0.0.73705
longRunning: true
longRunningPort: true
script: ''
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import demistomock as demisto
import json
import pytest
from CommonServerPython import entryTypes
from CommonServerPython import * # noqa: F401
from requests import Response

entryTypes['warning'] = 11

Expand Down Expand Up @@ -1459,8 +1460,8 @@ def test_direct_message_handler(mocker, requests_mock):

assert response['type'] == "message"
assert response['text'] == \
"I\'m sorry but I was unable to find you as a Cortex XSOAR user for bwillis@email.com. " \
"You're not allowed to run any command"
"I\'m sorry but I was unable to find you as a Cortex XSOAR user for bwillis@email.com. " \
"You're not allowed to run any command"

# verify create incident successfully
mocker.patch.object(demisto, 'findUser', return_value={'id': 'nice-demisto-id'})
Expand Down Expand Up @@ -2281,3 +2282,38 @@ def test_is_bot_in_chat_parameters(mocker, requests_mock):
is_bot_in_chat(GROUP_CHAT_ID)
filters = request_mock.last_request.qs.get('$filter')[0]
assert f"eq '{bot_id}'" in filters


@pytest.mark.parametrize('error_content, status_code, expected_response', [
(b'{"error": "invalid_grant", "error_description": "AADSTS700082: The refresh token has expired due to inactivity.'
b'\\u00a0The token was issued on 2023-02-06T12:26:14.6448497Z and was inactive for 90.00:00:00.'
b'\\r\\nTrace ID: test\\r\\nCorrelation ID: test\\r\\nTimestamp: 2023-07-02 06:40:26Z", '
b'"error_codes": [700082], "timestamp": "2023-07-02 06:40:26Z", "trace_id": "test", "correlation_id": "test",'
b' "error_uri": "https://login.microsoftonline.com/error?code=700082"}', 400,
'The refresh token has expired due to inactivity. Please regenerate the '
"'Authorization code' parameter and then run !microsoft-teams-auth-test to "
're-authenticate')])
def test_error_parser_with_exception(mocker, error_content, status_code, expected_response):
"""
Given:
- The error_content, status_code, and expected_response for testing the error_parser function.
When:
- The error_parser function is called with the given error_content and status_code.
Then:
- Assert that the error_parser function raises a DemistoException with the expected_response.
"""
from MicrosoftTeams import error_parser
mocker.patch.object(demisto, 'getIntegrationContext', return_value=integration_context)
mocker.patch.object(demisto, 'setIntegrationContext')
mocker.patch.object(demisto, 'error')
err = Response()
err.status_code = status_code
err._content = error_content

with pytest.raises(DemistoException) as ex:
error_parser(err)

assert demisto.getIntegrationContext.call_count == 1
assert demisto.setIntegrationContext.call_count == 1

assert str(ex.value) == expected_response
6 changes: 6 additions & 0 deletions Packs/MicrosoftTeams/ReleaseNotes/1_4_34.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

#### Integrations

##### Microsoft Teams
- Updated the Docker image to: *demisto/teams:1.0.0.73705*.
- Improved the token mechanism for handling expired tokens.
2 changes: 1 addition & 1 deletion Packs/MicrosoftTeams/pack_metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Microsoft Teams",
"description": "Send messages and notifications to your team members.",
"support": "xsoar",
"currentVersion": "1.4.33",
"currentVersion": "1.4.34",
"author": "Cortex XSOAR",
"url": "https://www.paloaltonetworks.com/cortex",
"email": "",
Expand Down

0 comments on commit 04da43f

Please sign in to comment.