def get_user_info_after_auth(request):
    flow = get_flow(request.session['reddit-redirect-url'])
    del request.session['reddit-redirect-url']

    state = request.session['reddit-state']
    del request.session['reddit-state']

    # Verify that the state matches
    if str(request.GET['state']) != str(state):
        raise FlowExchangeError('State does not match! Expected %s got %s' %
                                (state, request.GET['state']))

    code = request.GET['code']
    credentials = step2_exchange(flow,
                                 code)  # Needs to be modified for reddit OAuth

    # get the nice name
    http = httplib2.Http(".cache")
    http = credentials.authorize(http)
    (resp_headers,
     content) = http.request("https://oauth.reddit.com/api/v1/me", "GET")

    response = json.loads(content)

    name = response['name']

    return {
        'type': 'reddit',
        'user_id': name,
        'name': name,
        'info': {
            'name': name
        },
        'token': {}
    }
Exemple #2
0
async def test_expired_after_exchange(
    hass: HomeAssistant,
    mock_code_flow: Mock,
    component_setup: ComponentSetup,
) -> None:
    """Test credential exchange expires."""
    assert await component_setup()

    result = await hass.config_entries.flow.async_init(
        DOMAIN, context={"source": config_entries.SOURCE_USER})
    assert result.get("type") == "progress"
    assert result.get("step_id") == "auth"
    assert "description_placeholders" in result
    assert "url" in result["description_placeholders"]

    # Fail first attempt then advance clock past exchange timeout
    with patch(
            "homeassistant.components.google.api.OAuth2WebServerFlow.step2_exchange",
            side_effect=FlowExchangeError(),
    ):
        now = utcnow()
        await fire_alarm(hass, now + datetime.timedelta(seconds=65))
        await hass.async_block_till_done()

    result = await hass.config_entries.flow.async_configure(
        flow_id=result["flow_id"])
    assert result.get("type") == "abort"
    assert result.get("reason") == "code_expired"
Exemple #3
0
    def exchange(self, code=None, redirect_uri=None):
        if code and redirect_uri != None:
            self.auth = [{'code': code, 'redirect_uri': redirect_uri}] + self.auth

        error = ''
        if len(self.auth) == 0:
            raise FlowExchangeError("Can't exchange without auth code")
        for auth in self.auth:
            body = urllib.urlencode({
                'grant_type': 'authorization_code',
                'client_id': self.client_id,
                'client_secret': self.client_secret,
                'code': auth['code'],
                'redirect_uri': auth['redirect_uri'],
                'scope': self.scope
                })
            headers = {
                'content-type': 'application/x-www-form-urlencoded',
            }
            http = httplib2.Http(timeout=0.5)

            logger.info("Exchanging code {code} for new token".format(**auth))
            try:
                resp, content = http.request(self.token_uri, method='POST', body=body,
                                             headers=headers)
                logger.info("Token exchange response: %s", content)
                if resp.status == 200:
                    d = dict([el.split('=') for el in content.split('&')])
                    access_token = d['access_token']
                    refresh_token = d.get('refresh_token', None)
                    token_expiry = None
                    if 'expires' in d:
                        token_expiry = datetime.datetime.utcnow() + datetime.timedelta(
                                                            seconds=int(d['expires']))

                    self._credentials = OAuth2Credentials(access_token, self.client_id,
                                             self.client_secret, refresh_token, token_expiry,
                                             self.token_uri, self.user_agent,
                                             id_token=d.get('id_token', None))
                    return self._credentials
                else: error = error + str(content) + "\n"
            except SSLError as e:
                logger.warn("SSLError occurred exchanging facebook code for token")
                error = error + "SSLError: " + e.message + "\n"
        else:
            raise FlowExchangeError(error)
Exemple #4
0
    def test_reply_server_fail(self):
        msg = 'Whut!'
        self.OAuth2WebServerFlow(
        ).step2_exchange.side_effect = FlowExchangeError(msg)

        return self._test_command(
            'oauth somebiglongoauthreturncode',
            'Sorry {0} "{1}" happened. Try "!v1 oauth" again from the start'.
            format(self.nick, msg),
            to_nick=True,
        )
Exemple #5
0
    def test_run_flow_no_webserver_exchange_error(self, input_mock,
                                                  logging_mock):
        input_mock.return_value = 'auth_code'
        self.flow.step2_exchange.side_effect = FlowExchangeError()

        # Error while exchanging.
        with self.assertRaises(SystemExit):
            tools.run_flow(self.flow, self.storage, flags=self.flags)

        self.flow.step2_exchange.assert_called_once_with('auth_code',
                                                         http=None)
Exemple #6
0
async def test_exchange_error(
    hass: HomeAssistant,
    mock_code_flow: Mock,
    component_setup: ComponentSetup,
    mock_notification: Mock,
) -> None:
    """Test an error while exchanging the code for credentials."""

    with patch(
            "oauth2client.client.OAuth2WebServerFlow.step2_exchange",
            side_effect=FlowExchangeError(),
    ):
        assert await component_setup()

        now = utcnow()
        await fire_alarm(hass, now + CODE_CHECK_ALARM_TIMEDELTA)

    assert not hass.states.get("calendar.backyard_light")

    mock_notification.assert_called()
    assert "In order to authorize Home-Assistant" in mock_notification.call_args[
        0][1]
async def test_exchange_error(
    hass: HomeAssistant,
    mock_code_flow: Mock,
    mock_exchange: Mock,
    component_setup: ComponentSetup,
) -> None:
    """Test an error while exchanging the code for credentials."""
    assert await component_setup()

    result = await hass.config_entries.flow.async_init(
        DOMAIN, context={"source": config_entries.SOURCE_USER})
    assert result.get("type") == "progress"
    assert result.get("step_id") == "auth"
    assert "description_placeholders" in result
    assert "url" in result["description_placeholders"]

    # Run one tick to invoke the credential exchange check
    now = utcnow()
    with patch(
            "oauth2client.client.OAuth2WebServerFlow.step2_exchange",
            side_effect=FlowExchangeError(),
    ):
        now += CODE_CHECK_ALARM_TIMEDELTA
        await fire_alarm(hass, now)
        await hass.async_block_till_done()

    # Status has not updated, will retry
    result = await hass.config_entries.flow.async_configure(
        flow_id=result["flow_id"])
    assert result.get("type") == "progress"
    assert result.get("step_id") == "auth"

    # Run another tick, which attempts credential exchange again
    with patch("homeassistant.components.google.async_setup_entry",
               return_value=True) as mock_setup:
        now += CODE_CHECK_ALARM_TIMEDELTA
        await fire_alarm(hass, now)
        await hass.async_block_till_done()
        result = await hass.config_entries.flow.async_configure(
            flow_id=result["flow_id"])

    assert result.get("type") == "create_entry"
    assert result.get("title") == "Configuration.yaml"
    assert "data" in result
    data = result["data"]
    assert "token" in data
    data["token"].pop("expires_at")
    data["token"].pop("expires_in")
    assert data == {
        "auth_implementation": "device_auth",
        "token": {
            "access_token": "ACCESS_TOKEN",
            "refresh_token": "REFRESH_TOKEN",
            "scope": "https://www.googleapis.com/auth/calendar",
            "token_type": "Bearer",
        },
    }

    assert len(mock_setup.mock_calls) == 1
    entries = hass.config_entries.async_entries(DOMAIN)
    assert len(entries) == 1
 def test_get_credentials_failure(self, authenticator):
     from ..authenticator import AuthenticationError
     authenticator.flow = flow = mock.Mock(name='flow')
     flow.step2_exchange.side_effect = FlowExchangeError('testing')
     with pytest.raises(AuthenticationError):
         authenticator._get_credentials('CODE')
 def local_throws(code):
     raise FlowExchangeError("test")
Exemple #10
0
    def must_crach_flow_exception_and_reraise(self, credentials_from_code):
        credentials_from_code.return_value = mock.MagicMock(access_token='bar')
        credentials_from_code.side_effect = FlowExchangeError('some_error')

        with pytest.raises(google.GoogleOAuth2Exception):
            google.get_credentials('foo', '')
Exemple #11
0
    def step2_exchange(self, code, http=None):
        """
        Don't send scope in step2
        """

        if not (isinstance(code, str) or isinstance(code, unicode)):
            if 'code' not in code:
                if 'error' in code:
                    error_msg = code['error']
                else:
                    error_msg = 'No code was supplied in the query parameters.'
                raise FlowExchangeError(error_msg)
            else:
                code = code['code']

        body = urllib.urlencode({
            'grant_type': 'authorization_code',
            'client_id': self.client_id,
            'client_secret': self.client_secret,
            'code': code,
            'redirect_uri': self.redirect_uri,
        })
        headers = {
            'content-type': 'application/x-www-form-urlencoded',
        }

        if self.user_agent is not None:
            headers['user-agent'] = self.user_agent

        if http is None:
            http = httplib2.Http()

        resp, content = http.request(self.token_uri,
                                     method='POST',
                                     body=body,
                                     headers=headers)
        d = _parse_exchange_token_response(content)
        if resp.status == 200 and 'access_token' in d:
            access_token = d['access_token']
            refresh_token = d.get('refresh_token', None)
            token_expiry = None
            if 'expires_in' in d:
                token_expiry = datetime.datetime.utcnow() + datetime.timedelta(
                    seconds=int(d['expires_in']))

            if 'id_token' in d:
                d['id_token'] = _extract_id_token(d['id_token'])

            logger.info('Successfully retrieved access token')
            return OAuth2Credentials(access_token,
                                     self.client_id,
                                     self.client_secret,
                                     refresh_token,
                                     token_expiry,
                                     self.token_uri,
                                     self.user_agent,
                                     id_token=d.get('id_token', None))
        else:
            logger.info('Failed to retrieve access token: %s' % content)
            if 'error' in d:
                # you never know what those providers got to say
                error_msg = unicode(d['error'])
            else:
                error_msg = 'Invalid response: %s.' % str(resp.status)
            raise FlowExchangeError(error_msg)
def step2_exchange(self, code, http=None):
    """Exhanges a code for OAuth2Credentials.

  Args:
    code: string or dict, either the code as a string, or a dictionary
      of the query parameters to the redirect_uri, which contains
      the code.
    http: httplib2.Http, optional http instance to use to do the fetch

  Returns:
    An OAuth2Credentials object that can be used to authorize requests.

  Raises:
    FlowExchangeError if a problem occured exchanging the code for a
    refresh_token.
  """

    if not (isinstance(code, str) or isinstance(code, unicode)):
        if 'code' not in code:
            if 'error' in code:
                error_msg = code['error']
            else:
                error_msg = 'No code was supplied in the query parameters.'
            raise FlowExchangeError(error_msg)
        else:
            code = code['code']

    body = urllib.urlencode({
        'grant_type': 'authorization_code',
        'code': code,
        'redirect_uri': self.redirect_uri,
    })
    headers = {
        'content-type': 'application/x-www-form-urlencoded',
    }

    if self.user_agent is not None:
        headers['user-agent'] = self.user_agent

    if http is None:
        http = httplib2.Http()

    http.add_credentials(self.client_id, self.client_secret)

    resp, content = http.request(self.token_uri,
                                 method='POST',
                                 body=body,
                                 headers=headers)
    d = _parse_exchange_token_response(content)
    if resp.status == 200 and 'access_token' in d:
        access_token = d['access_token']
        refresh_token = d.get('refresh_token', None)
        token_expiry = None
        if 'expires_in' in d:
            token_expiry = datetime.datetime.utcnow() + datetime.timedelta(
                seconds=int(d['expires_in']))

        if 'id_token' in d:
            d['id_token'] = _extract_id_token(d['id_token'])

        logger.info('Successfully retrieved access token')
        return OAuth2Credentials(access_token,
                                 self.client_id,
                                 self.client_secret,
                                 refresh_token,
                                 token_expiry,
                                 self.token_uri,
                                 self.user_agent,
                                 revoke_uri=self.revoke_uri,
                                 id_token=d.get('id_token', None),
                                 token_response=d)
    else:
        logger.info('Failed to retrieve access token: %s' % content)
        if 'error' in d:
            # you never know what those providers got to say
            error_msg = unicode(d['error'])
        else:
            error_msg = 'Invalid response: %s.' % str(resp.status)
        raise FlowExchangeError(error_msg)