Пример #1
0
def test_get_or_post_with_qp():
    uri = u"https://localhost:8092/authorization?test=testslice"
    method = "GET"
    values = {
        "acr_values": "PASSWORD",
        "state": "urn:uuid:92d81fb3-72e8-4e6c-9173-c360b782148a",
        "redirect_uri":
        "https://localhost:8666/919D3F697FDAAF138124B83E09ECB0B7",
        "response_type": "code",
        "client_id": "ok8tx7ulVlNV",
        "scope": "openid profile email address phone",
    }
    request = AuthorizationRequest(**values)

    path, body, ret_kwargs = util.get_or_post(uri, method, request)

    assert url_compare(
        path,
        u"https://localhost:8092/authorization?test=testslice&acr_values=PASSWORD&state=urn%3A"
        "uuid%3A92d81fb3-72e8-4e6c-9173-c360b782148a&"
        "redirect_uri=https%3A%2F%2Flocalhost%3A8666%2F919D3F697FDAAF138124B83E09ECB0B7&"
        "response_type=code&client_id=ok8tx7ulVlNV&scope=openid+profile+email+address+phone",
    )
    assert not body
    assert not ret_kwargs
Пример #2
0
    def duplicate(self, sinfo):
        _dic = copy.copy(sinfo)
        areq = AuthorizationRequest().from_json(_dic["authzreq"])
        sid = self.token_factory["code"].key(user=_dic["sub"], areq=areq)

        _dic["code"] = self.token_factory["code"](sid=sid, sinfo=sinfo)
        _dic["code_used"] = False

        for key in [
            "access_token",
            "access_token_scope",
            "oauth_state",
            "token_type",
            "token_expires_at",
            "expires_in",
            "client_id_issued_at",
            "id_token",
            "oidreq",
            "refresh_token",
        ]:
            try:
                del _dic[key]
            except KeyError:
                pass

        self._db[sid] = _dic
        self.uid2sid[_dic["sub"]] = sid
        return sid
Пример #3
0
def test_get_or_post_with_qp():
    uri = u'https://localhost:8092/authorization?test=testslice'
    method = 'GET'
    values = {
        'acr_values': 'PASSWORD',
        'state': 'urn:uuid:92d81fb3-72e8-4e6c-9173-c360b782148a',
        'redirect_uri':
        'https://localhost:8666/919D3F697FDAAF138124B83E09ECB0B7',
        'response_type': 'code',
        'client_id': 'ok8tx7ulVlNV',
        'scope': 'openid profile email address phone'
    }
    request = AuthorizationRequest(**values)

    path, body, ret_kwargs = util.get_or_post(uri, method, request)

    assert url_compare(
        path,
        u"https://localhost:8092/authorization?test=testslice&acr_values=PASSWORD&state=urn%3A"
        "uuid%3A92d81fb3-72e8-4e6c-9173-c360b782148a&"
        "redirect_uri=https%3A%2F%2Flocalhost%3A8666%2F919D3F697FDAAF138124B83E09ECB0B7&"
        "response_type=code&client_id=ok8tx7ulVlNV&scope=openid+profile+email+address+phone"
    )
    assert not body
    assert not ret_kwargs
Пример #4
0
    def _handle_authentication_response(self):
        has_error = flask.request.args.get('error', False, lambda x: bool(int(x)))
        if has_error:
            if 'error' in flask.session:
                return self._show_error_response(flask.session.pop('error'))
            return 'Something went wrong.'

        try:
            session = UserSession(flask.session)
        except UninitialisedSession:
            return self._handle_error_response({'error': 'unsolicited_response', 'error_description': 'No initialised user session.'})

        if 'auth_request' not in flask.session:
            return self._handle_error_response({'error': 'unsolicited_response', 'error_description': 'No authentication request stored.'})
        auth_request = AuthorizationRequest().from_json(flask.session.pop('auth_request'))

        if flask.session.pop('fragment_encoded_response', False):
            return importlib_resources.read_binary('flask_pyoidc', 'parse_fragment.html').decode('utf-8')

        is_processing_fragment_encoded_response = flask.request.method == 'POST'

        if is_processing_fragment_encoded_response:
            auth_resp = flask.request.form
        else:
            auth_resp = flask.request.args

        client = self.clients[session.current_provider]

        authn_resp = client.parse_authentication_response(auth_resp)
        logger.debug('received authentication response: %s', authn_resp.to_json())

        try:
            result = AuthResponseHandler(client).process_auth_response(authn_resp, auth_request)
        except AuthResponseErrorResponseError as e:
            return self._handle_error_response(e.error_response, is_processing_fragment_encoded_response)
        except AuthResponseProcessError as e:
            return self._handle_error_response({'error': 'unexpected_error', 'error_description': str(e)},
                                               is_processing_fragment_encoded_response)

        if current_app.config.get('OIDC_SESSION_PERMANENT', True):
            flask.session.permanent = True

        UserSession(flask.session).update(access_token=result.access_token,
                                          expires_in=result.expires_in,
                                          id_token=result.id_token_claims,
                                          id_token_jwt=result.id_token_jwt,
                                          userinfo=result.userinfo_claims,
                                          refresh_token=result.refresh_token)

        destination = flask.session.pop('destination')
        if is_processing_fragment_encoded_response:
            # if the POST request was from the JS page handling fragment encoded responses we need to return
            # the destination URL as the response body
            return destination

        return redirect(destination)
Пример #5
0
def test_get_or_post():
    uri = u'https://localhost:8092/authorization'
    method = 'GET'
    values = {'acr_values': 'PASSWORD',
              'state': 'urn:uuid:92d81fb3-72e8-4e6c-9173-c360b782148a',
              'redirect_uri': 'https://localhost:8666/919D3F697FDAAF138124B83E09ECB0B7',
              'response_type': 'code', 'client_id': 'ok8tx7ulVlNV',
              'scope': 'openid profile email address phone'}
    request = AuthorizationRequest(**values)

    path, body, ret_kwargs = util.get_or_post(uri, method, request)

    assert url_compare(path,
                       u"https://localhost:8092/authorization?acr_values=PASSWORD&state=urn%3A"
                       "uuid%3A92d81fb3-72e8-4e6c-9173-c360b782148a&"
                       "redirect_uri=https%3A%2F%2Flocalhost%3A8666%2F919D3F697FDAAF138124B83E09ECB0B7&"
                       "response_type=code&client_id=ok8tx7ulVlNV&scope=openid+profile+email+address+phone")
    assert not body
    assert not ret_kwargs

    method = 'POST'
    uri = u'https://localhost:8092/token'
    values = {
        'redirect_uri': 'https://localhost:8666/919D3F697FDAAF138124B83E09ECB0B7',
        'code': 'Je1iKfPN1vCiN7L43GiXAuAWGAnm0mzA7QIjl/YLBBZDB9wefNExQlLDUIIDM2rT'
                '2t+gwuoRoapEXJyY2wrvg9cWTW2vxsZU+SuWzZlMDXc=',
        'grant_type': 'authorization_code'}
    request = AccessTokenRequest(**values)
    kwargs = {'scope': '',
              'state': 'urn:uuid:92d81fb3-72e8-4e6c-9173-c360b782148a',
              'authn_method': 'client_secret_basic', 'key': [],
              'headers': {
                  'Authorization': 'Basic b2s4dHg3dWxWbE5WOjdlNzUyZDU1MTc0NzA0NzQzYjZiZWJk'
                                   'YjU4ZjU5YWU3MmFlMGM5NDM4YTY1ZmU0N2IxMDA3OTM1'}
              }

    path, body, ret_kwargs = util.get_or_post(uri, method, request, **kwargs)

    assert path == u'https://localhost:8092/token'
    assert url_compare("http://test/#{}".format(body),
                       'http://test/#code=Je1iKfPN1vCiN7L43GiXAuAWGAnm0mzA7QIjl%2FYLBBZDB9wefNExQlLDUIIDM2rT2t%2BgwuoR'
                       'oapEXJyY2wrvg9cWTW2vxsZU%2BSuWzZlMDXc%3D&grant_type=authorization_code&redirect_uri=https%3A%2'
                       'F%2Flocalhost%3A8666%2F919D3F697FDAAF138124B83E09ECB0B7')
    assert ret_kwargs == {'scope': '',
                          'state': 'urn:uuid:92d81fb3-72e8-4e6c-9173-c360b782148a',
                          'authn_method': 'client_secret_basic', 'key': [],
                          'headers': {
                              'Content-Type': 'application/x-www-form-urlencoded',
                              'Authorization': 'Basic b2s4dHg3dWxWbE5WOjdlNzUyZDU1MTc0NzA0NzQzYjZiZWJkYjU4ZjU5YWU3MmFl'
                                               'MGM5NDM4YTY1ZmU0N2IxMDA3OTM1'}}

    method = 'UNSUPORTED'
    with pytest.raises(UnSupported):
        util.get_or_post(uri, method, request, **kwargs)
Пример #6
0
    def get_aat(self, user):
        request_args = {
            "response_type": "code",
            "client_id": "internal",
            "redirect_uri": self.client.redirect_uris[0],
            "scope": [self.client.get_uma_scope("AAT")],
            "state": "_state"
        }

        areq = AuthorizationRequest(**request_args)
        pre_trace("C-->AS", "get_aat", query=areq.to_dict(), user=user)
        sid = self.srv.sdb.create_authz_session(user, areq)
        grant = self.srv.sdb[sid]["code"]
        self.client.token[user] = {"AAT": self.srv.sdb.upgrade_to_token(grant)}
        post_trace("C<--AS",
                   AAT=self.client.token[user]["AAT"]["access_token"])
Пример #7
0
    "redirect_uris": [callback]
}

ressrv.client.redirect_uris = [callback]

# Register the RS as a client to the AS, this is OAuth2 dynreg registration
reg_info = ressrv.client.construct_RegistrationRequest(request_args=_me)
reg_resp = authzsrv.oauth_registration_endpoint(reg_info.to_json())
regresp = RegistrationResponse().from_json(reg_resp.message)

ressrv.client.store_registration_info(regresp)

# Get the PAT, should normally be a login and token request
RESOURCE_OWNER = "linda"
identity = {"uid": RESOURCE_OWNER}
areq = AuthorizationRequest(client_id=regresp["client_id"], scope=[PAT])
# Authentication happens by magic :-)
authn_event = AuthnEvent(RESOURCE_OWNER,
                         'salt',
                         authn_info="UserPassword",
                         time_stamp=int(time.time()))
sid = authzsrv.sdb.create_authz_session(authn_event, areq)
grant = authzsrv.sdb[sid]["code"]
_dict = authzsrv.sdb.upgrade_to_token(grant)
ressrv.rs_handler.token['PAT'] = _dict["access_token"]

# ============================== 2 ===========================================
# create resource set descriptions and register them.
# ressrv.rs_handler.register_resource_set_description({'prim': RESOURCE_OWNER})

res_set_desc = ressrv.rs_handler.dataset.build_resource_set_descriptions(
Пример #8
0
opc.update(uma_pcr)
client.handle_provider_config(uma_pcr, authzsrv.baseurl, False, True)

client.provider_info = opc

# Register the RS as a client to the AS, this is OAuth2 dynreg registration
reg_info = client.construct_RegistrationRequest(request_args=_me)
reg_resp = authzsrv.oidc_registration_endpoint(reg_info.to_json())
regresp = RegistrationResponse().from_json(reg_resp.message)

client.store_registration_info(regresp)

# Get the PAT, should normally be a login and token request
RESOURCE_OWNER = "linda"
identity = {"uid": RESOURCE_OWNER}
areq = AuthorizationRequest(client_id=regresp["client_id"])
# Authentication happens by magic :-)
authn_event = AuthnEvent(RESOURCE_OWNER,
                         identity.get('salt', ''),
                         authn_info="UserPassword",
                         time_stamp=int(time.time()))
sid = authzsrv.sdb.create_authz_session(authn_event, areq)
grant = authzsrv.sdb[sid]["code"]
_dict = authzsrv.sdb.upgrade_to_token(grant)
# pat = _dict["access_token"]
ressrv.authz_registration(RESOURCE_OWNER, _dict, opc["issuer"], RESSRV_CLI_KEY)

# ============================== 2 ===========================================
# create resource set descriptions and register them.
res_set_desc = ressrv.dataset.build_resource_set_descriptions(
    {"user": RESOURCE_OWNER})
Пример #9
0
def test_get_or_post():
    uri = u"https://localhost:8092/authorization"
    method = "GET"
    values = {
        "acr_values": "PASSWORD",
        "state": "urn:uuid:92d81fb3-72e8-4e6c-9173-c360b782148a",
        "redirect_uri":
        "https://localhost:8666/919D3F697FDAAF138124B83E09ECB0B7",
        "response_type": "code",
        "client_id": "ok8tx7ulVlNV",
        "scope": "openid profile email address phone",
    }
    request = AuthorizationRequest(**values)

    path, body, ret_kwargs = util.get_or_post(uri, method, request)

    assert url_compare(
        path,
        u"https://localhost:8092/authorization?acr_values=PASSWORD&state=urn%3A"
        "uuid%3A92d81fb3-72e8-4e6c-9173-c360b782148a&"
        "redirect_uri=https%3A%2F%2Flocalhost%3A8666%2F919D3F697FDAAF138124B83E09ECB0B7&"
        "response_type=code&client_id=ok8tx7ulVlNV&scope=openid+profile+email+address+phone",
    )
    assert not body
    assert not ret_kwargs

    method = "POST"
    uri = u"https://localhost:8092/token"
    values = {
        "redirect_uri":
        "https://localhost:8666/919D3F697FDAAF138124B83E09ECB0B7",
        "code":
        "Je1iKfPN1vCiN7L43GiXAuAWGAnm0mzA7QIjl/YLBBZDB9wefNExQlLDUIIDM2rT"
        "2t+gwuoRoapEXJyY2wrvg9cWTW2vxsZU+SuWzZlMDXc=",
        "grant_type": "authorization_code",
    }
    request2 = AccessTokenRequest(**values)
    kwargs = {
        "scope": "",
        "state": "urn:uuid:92d81fb3-72e8-4e6c-9173-c360b782148a",
        "authn_method": "client_secret_basic",
        "key": [],
        "headers": {
            "Authorization":
            "Basic b2s4dHg3dWxWbE5WOjdlNzUyZDU1MTc0NzA0NzQzYjZiZWJk"
            "YjU4ZjU5YWU3MmFlMGM5NDM4YTY1ZmU0N2IxMDA3OTM1"
        },
    }

    path, body, ret_kwargs = util.get_or_post(uri, method, request2, **kwargs)

    assert path == u"https://localhost:8092/token"
    assert url_compare(
        "http://test/#{}".format(body),
        "http://test/#code=Je1iKfPN1vCiN7L43GiXAuAWGAnm0mzA7QIjl%2FYLBBZDB9wefNExQlLDUIIDM2rT2t%2BgwuoR"
        "oapEXJyY2wrvg9cWTW2vxsZU%2BSuWzZlMDXc%3D&grant_type=authorization_code&redirect_uri=https%3A%2"
        "F%2Flocalhost%3A8666%2F919D3F697FDAAF138124B83E09ECB0B7",
    )
    assert ret_kwargs == {
        "scope": "",
        "state": "urn:uuid:92d81fb3-72e8-4e6c-9173-c360b782148a",
        "authn_method": "client_secret_basic",
        "key": [],
        "headers": {
            "Content-Type":
            "application/x-www-form-urlencoded",
            "Authorization":
            "Basic b2s4dHg3dWxWbE5WOjdlNzUyZDU1MTc0NzA0NzQzYjZiZWJkYjU4ZjU5YWU3MmFl"
            "MGM5NDM4YTY1ZmU0N2IxMDA3OTM1",
        },
    }

    method = "UNSUPORTED"
    with pytest.raises(UnSupported):
        util.get_or_post(uri, method, request2, **kwargs)
class TestAuthResponseHandler:
    ISSUER = 'https://issuer.example.com'
    CLIENT_ID = 'client1'
    AUTH_REQUEST = AuthorizationRequest(**{
        'state': 'test_state',
        'nonce': 'test_nonce'
    })
    AUTH_RESPONSE = AuthorizationResponse(**{
        'code': 'test_auth_code',
        'state': AUTH_REQUEST['state']
    })
    TOKEN_RESPONSE = AccessTokenResponse(
        **{
            'access_token': 'test_token',
            'expires_in': 3600,
            'id_token': _create_id_token(ISSUER, CLIENT_ID,
                                         AUTH_REQUEST['nonce']),
            'id_token_jwt': 'test_id_token_jwt',
            'refresh_token': 'test_refresh_token'
        })
    USERINFO_RESPONSE = OpenIDSchema(**{'sub': 'test_sub'})
    ERROR_RESPONSE = {
        'error': 'test_error',
        'error_description': 'something went wrong'
    }

    @pytest.fixture
    def client_mock(self):
        return create_autospec(PyoidcFacade, True, True)

    def test_should_detect_state_mismatch(self, client_mock):
        auth_request = {
            'state': 'other_state',
            'nonce': self.AUTH_REQUEST['nonce']
        }
        with pytest.raises(AuthResponseUnexpectedStateError):
            AuthResponseHandler(client_mock).process_auth_response(
                self.AUTH_RESPONSE, auth_request)

    def test_should_detect_nonce_mismatch(self, client_mock):
        client = PyoidcFacade(
            ProviderConfiguration(
                provider_metadata=ProviderMetadata(issuer=self.ISSUER),
                client_metadata=ClientMetadata(client_id=self.CLIENT_ID)),
            redirect_uri='https://client.example.com/redirect')
        client.exchange_authorization_code = MagicMock(
            return_value=self.TOKEN_RESPONSE)
        auth_request = {
            'state': self.AUTH_RESPONSE['state'],
            'nonce': 'other_nonce'
        }
        with pytest.raises(InvalidIdTokenError):
            AuthResponseHandler(client).process_auth_response(
                self.AUTH_RESPONSE, auth_request)

    def test_should_handle_auth_error_response(self, client_mock):
        with pytest.raises(AuthResponseErrorResponseError) as exc:
            AuthResponseHandler(client_mock).process_auth_response(
                AuthorizationErrorResponse(**self.ERROR_RESPONSE),
                self.AUTH_REQUEST)
        assert exc.value.error_response == self.ERROR_RESPONSE

    def test_should_handle_token_error_response(self, client_mock):
        client_mock.exchange_authorization_code.return_value = TokenErrorResponse(
            **self.ERROR_RESPONSE)
        with pytest.raises(AuthResponseErrorResponseError) as exc:
            AuthResponseHandler(client_mock).process_auth_response(
                AuthorizationResponse(**self.AUTH_RESPONSE), self.AUTH_REQUEST)
        assert exc.value.error_response == self.ERROR_RESPONSE

    def test_should_detect_mismatching_subject(self, client_mock):
        client_mock.exchange_authorization_code.return_value = AccessTokenResponse(
            **self.TOKEN_RESPONSE)
        client_mock.userinfo_request.return_value = OpenIDSchema(
            **{'sub': 'other_sub'})
        with pytest.raises(AuthResponseMismatchingSubjectError):
            AuthResponseHandler(client_mock).process_auth_response(
                AuthorizationResponse(**self.AUTH_RESPONSE), self.AUTH_REQUEST)

    def test_should_handle_auth_response_with_authorization_code(
            self, client_mock):
        client_mock.exchange_authorization_code.return_value = self.TOKEN_RESPONSE
        client_mock.userinfo_request.return_value = self.USERINFO_RESPONSE
        result = AuthResponseHandler(client_mock).process_auth_response(
            self.AUTH_RESPONSE, self.AUTH_REQUEST)
        assert result.access_token == 'test_token'
        assert result.expires_in == self.TOKEN_RESPONSE['expires_in']
        assert result.id_token_claims == self.TOKEN_RESPONSE[
            'id_token'].to_dict()
        assert result.id_token_jwt == self.TOKEN_RESPONSE['id_token_jwt']
        assert result.userinfo_claims == self.USERINFO_RESPONSE.to_dict()
        assert result.refresh_token == self.TOKEN_RESPONSE['refresh_token']

    def test_should_handle_auth_response_without_authorization_code(
            self, client_mock):
        auth_response = AuthorizationResponse(**self.TOKEN_RESPONSE)
        auth_response['state'] = 'test_state'
        client_mock.userinfo_request.return_value = self.USERINFO_RESPONSE
        result = AuthResponseHandler(client_mock).process_auth_response(
            auth_response, self.AUTH_REQUEST)
        assert not client_mock.exchange_authorization_code.called
        assert result.access_token == 'test_token'
        assert result.expires_in == self.TOKEN_RESPONSE['expires_in']
        assert result.id_token_jwt == self.TOKEN_RESPONSE['id_token_jwt']
        assert result.id_token_claims == self.TOKEN_RESPONSE[
            'id_token'].to_dict()
        assert result.userinfo_claims == self.USERINFO_RESPONSE.to_dict()
        assert result.refresh_token == None

    def test_should_handle_token_response_without_id_token(self, client_mock):
        token_response = {'access_token': 'test_token'}
        client_mock.exchange_authorization_code.return_value = AccessTokenResponse(
            **token_response)
        result = AuthResponseHandler(client_mock).process_auth_response(
            AuthorizationResponse(**self.AUTH_RESPONSE), self.AUTH_REQUEST)
        assert result.access_token == 'test_token'
        assert result.id_token_claims is None

    def test_should_handle_no_token_response(self, client_mock):
        client_mock.exchange_authorization_code.return_value = None
        client_mock.userinfo_request.return_value = None
        hybrid_auth_response = self.AUTH_RESPONSE.copy()
        hybrid_auth_response.update(self.TOKEN_RESPONSE)
        result = AuthResponseHandler(client_mock).process_auth_response(
            AuthorizationResponse(**hybrid_auth_response), self.AUTH_REQUEST)
        assert result.access_token == 'test_token'
        assert result.id_token_claims == self.TOKEN_RESPONSE[
            'id_token'].to_dict()
        assert result.id_token_jwt == self.TOKEN_RESPONSE['id_token_jwt']

    @pytest.mark.parametrize(
        'response_type, expected',
        [
            ('code', False),  # Authorization Code Flow
            ('id_token', True),  # Implicit Flow
            ('id_token token', True),  # Implicit Flow
            ('code id_token', True),  # Hybrid Flow
            ('code token', True),  # Hybrid Flow
            ('code id_token token', True)  # Hybrid Flow
        ])
    def test_expect_fragment_encoded_response_by_response_type(
            self, response_type, expected):
        assert AuthResponseHandler.expect_fragment_encoded_response(
            {'response_type': response_type}) is expected

    @pytest.mark.parametrize('response_type, response_mode, expected', [
        ('code', 'fragment', True),
        ('id_token', 'query', False),
        ('code token', 'form_post', False),
    ])
    def test_expect_fragment_encoded_response_with_non_default_response_mode(
            self, response_type, response_mode, expected):
        auth_req = {
            'response_type': response_type,
            'response_mode': response_mode
        }
        assert AuthResponseHandler.expect_fragment_encoded_response(
            auth_req) is expected