コード例 #1
0
    def test_should_not_fetch_provider_metadata_if_given(self):
        provider_metadata = self.provider_metadata()
        provider_config = ProviderConfiguration(
            provider_metadata=provider_metadata,
            client_registration_info=ClientRegistrationInfo())

        provider_config.ensure_provider_metadata(Client(CLIENT_AUTHN_METHOD))
        assert provider_config._provider_metadata == provider_metadata
コード例 #2
0
 def test_should_raise_exception_for_non_registered_client_when_missing_registration_endpoint(
         self):
     provider_config = ProviderConfiguration(
         provider_metadata=self.provider_metadata(),
         client_registration_info=ClientRegistrationInfo())
     with pytest.raises(ValueError) as exc_info:
         provider_config.register_client([])
     assert 'registration_endpoint' in str(exc_info.value)
コード例 #3
0
 def test_should_not_register_dynamic_client_if_client_metadata_is_given(
         self):
     client_metadata = ClientMetadata(client_id='client1',
                                      client_secret='secret1')
     provider_config = ProviderConfiguration(
         provider_metadata=self.provider_metadata(),
         client_metadata=client_metadata)
     provider_config.register_client(None)
     assert provider_config._client_metadata == client_metadata
コード例 #4
0
 def test_should_raise_exception_for_non_registered_client_when_missing_registration_endpoint(
         self):
     provider_config = ProviderConfiguration(
         provider_metadata=self.provider_metadata(),
         client_registration_info=ClientRegistrationInfo())
     assert provider_config._provider_metadata[
         'registration_endpoint'] is None
     with pytest.raises(ValueError):
         provider_config.register_client(None)
コード例 #5
0
 def test_is_registered(self):
     unregistered = ProviderConfiguration(
         provider_metadata=self.PROVIDER_METADATA,
         client_registration_info=ClientRegistrationInfo())
     registered = ProviderConfiguration(
         provider_metadata=self.PROVIDER_METADATA,
         client_metadata=self.CLIENT_METADATA)
     assert PyoidcFacade(unregistered,
                         REDIRECT_URI).is_registered() is False
     assert PyoidcFacade(registered, REDIRECT_URI).is_registered() is True
コード例 #6
0
 def test_should_not_register_dynamic_client_if_client_metadata_is_given(
         self):
     client_metadata = ClientMetadata(
         client_id='client1',
         client_secret='secret1',
         redirect_uris=['https://client.example.com/redirect'])
     provider_config = ProviderConfiguration(
         provider_metadata=self.provider_metadata(),
         client_metadata=client_metadata)
     provider_config.register_client([])
     assert provider_config._client_metadata == client_metadata
コード例 #7
0
    def test_register(self):
        registration_endpoint = self.PROVIDER_BASEURL + '/register'
        redirect_uris = ['https://client.example.com/redirect']
        post_logout_redirect_uris = ['https://client.example.com/logout']
        client_registration_response = {
            'client_id': 'client1',
            'client_secret': 'secret1',
            'client_name': 'Test Client',
            'redirect_uris': redirect_uris,
            'post_logout_redirect_uris': post_logout_redirect_uris
        }
        responses.add(responses.POST,
                      registration_endpoint,
                      json=client_registration_response)

        provider_metadata = self.PROVIDER_METADATA.copy(
            registration_endpoint=registration_endpoint)
        unregistered = ProviderConfiguration(
            provider_metadata=provider_metadata,
            client_registration_info=ClientRegistrationInfo(
                redirect_uris=redirect_uris,
                post_logout_redirect_uris=post_logout_redirect_uris))
        facade = PyoidcFacade(unregistered, REDIRECT_URI)
        facade.register()
        assert facade.is_registered() is True
コード例 #8
0
def login():
    login_hint_token = request.args.get('login_hint_token')
    state = request.args.get('state')
    mccmnc = request.args.get('mccmnc')

    name = getNameForCurrentSession()
    if state != state_key:
        return redirect('/')
    elif name != None:
         return redirect('/logged-in')
    else:
        provider_metadata = get_provider_metadata(login_hint_token, mccmnc)
        client_metadata = get_client_metadata()
        if provider_metadata != None and client_metadata != None:
            # configure provider (i.e. MNO) and client
            config = ProviderConfiguration(
                client_metadata=client_metadata,
                auth_request_params=auth_params,
                provider_metadata=provider_metadata)
            # TODO: once dynamic discovery with XCI providers is working, touch this up / ensure this works to manage logging in with different providers
            url = url_for('login', _external=True)
            # use pyoidc internals to add provider / client to session, no need to store
            UserSession(flask.session, PROVIDER_NAME)
            # instantiate OIDC through facade
            client = PyoidcFacade(config, url)
            # authenticate
            return openid._authenticate(client)
        return render_template('home.html', error='Could not build a valid configuration for the selected provider. Error detail: MCC=%s, MNC=%s' % (mcc, mnc))
コード例 #9
0
    def test_missing_client_metadata_raises_exception(self):
        with pytest.raises(ValueError) as exc_info:
            ProviderConfiguration(issuer=self.PROVIDER_BASEURL)

        exc_message = str(exc_info.value)
        assert 'client_registration_info' in exc_message
        assert 'client_metadata' in exc_message
コード例 #10
0
    def test_authentication_request(self):
        extra_user_auth_params = {"foo": "bar", "abc": "xyz"}
        config = ProviderConfiguration(
            provider_metadata=self.PROVIDER_METADATA,
            client_metadata=self.CLIENT_METADATA,
            auth_request_params=extra_user_auth_params,
        )

        state = "test_state"
        nonce = "test_nonce"

        facade = PyoidcFacade(config, self.REDIRECT_URI)
        extra_lib_auth_params = {"foo": "baz", "qwe": "rty"}
        auth_request = facade.authentication_request(state, nonce,
                                                     self.FULL_REDIRECT_URI,
                                                     extra_lib_auth_params)
        assert auth_request.startswith(
            self.PROVIDER_METADATA["authorization_endpoint"])

        auth_request_params = dict(parse_qsl(urlparse(auth_request).query))
        expected_auth_params = {
            "scope": "openid",
            "response_type": "code",
            "client_id": self.CLIENT_METADATA["client_id"],
            "redirect_uri": self.FULL_REDIRECT_URI,
            "state": state,
            "nonce": nonce,
        }
        expected_auth_params.update(extra_user_auth_params)
        expected_auth_params.update(extra_lib_auth_params)
        assert auth_request_params == expected_auth_params
コード例 #11
0
    def init_app(self,
                 provider_metadata_extras=None,
                 client_metadata_extras=None,
                 **kwargs):
        required_provider_metadata = {
            "issuer": self.PROVIDER_BASEURL,
            "authorization_endpoint": self.PROVIDER_BASEURL + "/auth",
            "jwks_uri": self.PROVIDER_BASEURL + "/jwks",
        }
        if provider_metadata_extras:
            required_provider_metadata.update(provider_metadata_extras)
        provider_metadata = ProviderMetadata(**required_provider_metadata)

        required_client_metadata = {
            "client_id": self.CLIENT_ID,
            "client_secret": "secret1"
        }
        if client_metadata_extras:
            required_client_metadata.update(client_metadata_extras)
        client_metadata = ClientMetadata(**required_client_metadata)

        provider_configurations = {
            self.PROVIDER_NAME:
            ProviderConfiguration(provider_metadata=provider_metadata,
                                  client_metadata=client_metadata,
                                  **kwargs)
        }
        authn = OIDCAuthentication(provider_configurations)
        authn.init_app(self.app)
        return authn
コード例 #12
0
    def test_authentication_request(self):
        extra_user_auth_params = {'foo': 'bar', 'abc': 'xyz'}
        config = ProviderConfiguration(
            provider_metadata=self.PROVIDER_METADATA,
            client_metadata=self.CLIENT_METADATA,
            auth_request_params=extra_user_auth_params)

        state = 'test_state'
        nonce = 'test_nonce'

        facade = PyoidcFacade(config, REDIRECT_URI)
        extra_lib_auth_params = {'foo': 'baz', 'qwe': 'rty'}
        auth_request = facade.authentication_request(state, nonce,
                                                     extra_lib_auth_params)
        assert auth_request.startswith(
            self.PROVIDER_METADATA['authorization_endpoint'])

        auth_request_params = dict(parse_qsl(urlparse(auth_request).query))
        expected_auth_params = {
            'scope': 'openid',
            'response_type': 'code',
            'client_id': self.CLIENT_METADATA['client_id'],
            'redirect_uri': REDIRECT_URI,
            'state': state,
            'nonce': nonce
        }
        expected_auth_params.update(extra_user_auth_params)
        expected_auth_params.update(extra_lib_auth_params)
        assert auth_request_params == expected_auth_params
コード例 #13
0
 def test_parse_authentication_response_preserves_id_token_jwt(self):
     facade = PyoidcFacade(
         ProviderConfiguration(provider_metadata=self.PROVIDER_METADATA,
                               client_metadata=self.CLIENT_METADATA),
         REDIRECT_URI)
     state = 'state-1234'
     now = int(time.time())
     id_token, id_token_signing_key = signed_id_token({
         'iss':
         self.PROVIDER_METADATA['issuer'],
         'sub':
         'test_sub',
         'aud':
         'client1',
         'exp':
         now + 1,
         'iat':
         now
     })
     responses.add(responses.GET,
                   self.PROVIDER_METADATA['jwks_uri'],
                   json={'keys': [id_token_signing_key.serialize()]})
     auth_response = AuthorizationResponse(**{
         'state': state,
         'id_token': id_token
     })
     parsed_auth_response = facade.parse_authentication_response(
         auth_response)
     assert isinstance(parsed_auth_response, AuthorizationResponse)
     assert parsed_auth_response['state'] == state
     assert parsed_auth_response['id_token_jwt'] == id_token
コード例 #14
0
    def init_app(self,
                 provider_metadata_extras=None,
                 client_metadata_extras=None,
                 **kwargs):
        required_provider_metadata = {
            'issuer': self.PROVIDER_BASEURL,
            'authorization_endpoint': self.PROVIDER_BASEURL + '/auth',
            'jwks_uri': self.PROVIDER_BASEURL + '/jwks'
        }
        if provider_metadata_extras:
            required_provider_metadata.update(provider_metadata_extras)
        provider_metadata = ProviderMetadata(**required_provider_metadata)

        required_client_metadata = {
            'client_id': self.CLIENT_ID,
            'client_secret': 'secret1'
        }
        if client_metadata_extras:
            required_client_metadata.update(client_metadata_extras)
        client_metadata = ClientMetadata(**required_client_metadata)

        provider_configurations = {
            self.PROVIDER_NAME:
            ProviderConfiguration(provider_metadata=provider_metadata,
                                  client_metadata=client_metadata,
                                  **kwargs)
        }
        authn = OIDCAuthentication(provider_configurations)
        authn.init_app(self.app)
        return authn
コード例 #15
0
 def test_registered_client_metadata_is_forwarded_to_pyoidc(self):
     config = ProviderConfiguration(
         provider_metadata=self.PROVIDER_METADATA,
         client_metadata=self.CLIENT_METADATA,
     )
     facade = PyoidcFacade(config, self.REDIRECT_URI)
     assert facade._client.registration_response
コード例 #16
0
 def test_no_registered_client_metadata_is_handled(self):
     config = ProviderConfiguration(
         provider_metadata=self.PROVIDER_METADATA,
         client_registration_info=ClientRegistrationInfo(),
     )
     facade = PyoidcFacade(config, self.REDIRECT_URI)
     assert not facade._client.registration_response
コード例 #17
0
 def test_no_userinfo_request_is_made_if_no_userinfo_endpoint_is_configured(
         self):
     facade = PyoidcFacade(
         ProviderConfiguration(provider_metadata=self.PROVIDER_METADATA,
                               client_metadata=self.CLIENT_METADATA),
         REDIRECT_URI)
     assert facade.userinfo_request('test_token') is None
コード例 #18
0
 def test_parse_authentication_response_handles_error_response(self):
     facade = PyoidcFacade(ProviderConfiguration(provider_metadata=self.PROVIDER_METADATA,
                                                 client_metadata=self.CLIENT_METADATA),
                           self.REDIRECT_URI)
     error_response = AuthorizationErrorResponse(**{'error': 'invalid_request', 'state': 'state-1234'})
     parsed_auth_response = facade.parse_authentication_response(error_response)
     assert isinstance(parsed_auth_response, AuthorizationErrorResponse)
     assert parsed_auth_response.to_dict() == error_response.to_dict()
コード例 #19
0
    def test_missing_provider_metadata_raises_exception(self):
        with pytest.raises(ValueError) as exc_info:
            ProviderConfiguration(
                client_registration_info=ClientRegistrationInfo())

        exc_message = str(exc_info.value)
        assert 'issuer' in exc_message
        assert 'provider_metadata' in exc_message
コード例 #20
0
    def test_register_client_should_register_dynamic_client_if_initial_access_token_present(
            self):

        registration_endpoint = self.PROVIDER_BASEURL + '/register'
        redirect_uris = [
            'https://client.example.com/redirect',
            'https://client.example.com/redirect2'
        ]
        post_logout_redirect_uris = ['https://client.example.com/logout']
        client_registration_response = {
            'client_id': 'client1',
            'client_secret': 'secret1',
            'client_name': 'Test Client',
            'redirect_uris': redirect_uris,
            'post_logout_redirect_uris': post_logout_redirect_uris,
            'registration_client_uri':
            'https://op.example.com/register/client1',
            'registration_access_token': 'registration_access_token1'
        }
        responses.add(responses.POST,
                      registration_endpoint,
                      json=client_registration_response)
        provider_config = ProviderConfiguration(
            provider_metadata=self.provider_metadata(
                registration_endpoint=registration_endpoint),
            client_registration_info=ClientRegistrationInfo(
                client_name='Test Client',
                redirect_uris=redirect_uris,
                post_logout_redirect_uris=post_logout_redirect_uris,
                registration_token='initial_access_token'))

        provider_config.register_client(Client(CLIENT_AUTHN_METHOD))

        assert provider_config._client_metadata['client_id'] == 'client1'
        assert provider_config._client_metadata['client_secret'] == 'secret1'
        assert provider_config._client_metadata['client_name'] == 'Test Client'
        assert provider_config._client_metadata[
            'registration_client_uri'] == 'https://op.example.com/register/client1'
        assert provider_config._client_metadata[
            'registration_access_token'] == 'registration_access_token1'
        assert provider_config._client_metadata[
            'redirect_uris'] == redirect_uris
        assert provider_config._client_metadata[
            'post_logout_redirect_uris'] == post_logout_redirect_uris
        assert responses.calls[0].request.headers['Authorization'] == \
               f"Bearer {base64.b64encode('initial_access_token'.encode()).decode()}"
コード例 #21
0
 def test_no_userinfo_request_is_made_if_no_access_token(self):
     provider_metadata = self.PROVIDER_METADATA.copy(
         userinfo_endpoint=self.PROVIDER_BASEURL + '/userinfo')
     facade = PyoidcFacade(
         ProviderConfiguration(provider_metadata=provider_metadata,
                               client_metadata=self.CLIENT_METADATA),
         REDIRECT_URI)
     assert facade.userinfo_request(None) is None
コード例 #22
0
 def test_token_request_handles_missing_provider_token_endpoint(self):
     facade = PyoidcFacade(
         ProviderConfiguration(
             provider_metadata=self.PROVIDER_METADATA,
             client_metadata=self.CLIENT_METADATA,
         ),
         self.REDIRECT_URI,
     )
     assert facade.token_request("1234") is None
コード例 #23
0
 def test_post_logout_redirect_uris(self):
     post_logout_redirect_uris = ['https://client.example.com/logout']
     client_metadata = self.CLIENT_METADATA.copy(
         post_logout_redirect_uris=post_logout_redirect_uris)
     facade = PyoidcFacade(
         ProviderConfiguration(provider_metadata=self.PROVIDER_METADATA,
                               client_metadata=client_metadata),
         REDIRECT_URI)
     assert facade.post_logout_redirect_uris == post_logout_redirect_uris
コード例 #24
0
    def test_token_request_handles_error_response(self):
        token_endpoint = self.PROVIDER_BASEURL + '/token'
        token_response = TokenErrorResponse(error='invalid_request', error_description='test error description')
        responses.add(responses.POST, token_endpoint, json=token_response.to_dict(), status=400)

        provider_metadata = self.PROVIDER_METADATA.copy(token_endpoint=token_endpoint)
        facade = PyoidcFacade(ProviderConfiguration(provider_metadata=provider_metadata,
                                                    client_metadata=self.CLIENT_METADATA),
                              self.REDIRECT_URI)
        assert facade.token_request('1234') == token_response
コード例 #25
0
    def test_register(self):
        registration_endpoint = self.PROVIDER_BASEURL + '/register'
        responses.add(responses.POST, registration_endpoint, json=self.CLIENT_METADATA.to_dict())

        provider_metadata = self.PROVIDER_METADATA.copy(registration_endpoint=registration_endpoint)
        unregistered = ProviderConfiguration(provider_metadata=provider_metadata,
                                             client_registration_info=ClientRegistrationInfo())
        facade = PyoidcFacade(unregistered, self.REDIRECT_URI)
        facade.register()
        assert facade.is_registered() is True
コード例 #26
0
 def provider_configuration(self):
     return ProviderConfiguration(
         client_metadata=self.client_metadata,
         provider_metadata=self.provider_metadata,
         session_refresh_interval_seconds=15 * 60,
         auth_request_params={
             "audience": [self.oidc_config.lando_api_oidc_id()],
             "scope": ["openid", "profile", "email", "lando"],
         },
     )
コード例 #27
0
 def test_parse_authentication_response(self):
     facade = PyoidcFacade(ProviderConfiguration(provider_metadata=self.PROVIDER_METADATA,
                                                 client_metadata=self.CLIENT_METADATA),
                           self.REDIRECT_URI)
     auth_code = 'auth_code-1234'
     state = 'state-1234'
     auth_response = AuthorizationResponse(**{'state': state, 'code': auth_code})
     parsed_auth_response = facade.parse_authentication_response(auth_response.to_dict())
     assert isinstance(parsed_auth_response, AuthorizationResponse)
     assert parsed_auth_response.to_dict() == auth_response.to_dict()
コード例 #28
0
    def test_configurable_userinfo_endpoint_method_is_used(self, userinfo_http_method):
        userinfo_endpoint = self.PROVIDER_BASEURL + '/userinfo'
        userinfo_response = OpenIDSchema(sub='user1')
        responses.add(userinfo_http_method, userinfo_endpoint, json=userinfo_response.to_dict())

        provider_metadata = self.PROVIDER_METADATA.copy(userinfo_endpoint=userinfo_endpoint)
        facade = PyoidcFacade(ProviderConfiguration(provider_metadata=provider_metadata,
                                                    client_metadata=self.CLIENT_METADATA,
                                                    userinfo_http_method=userinfo_http_method),
                              self.REDIRECT_URI)
        assert facade.userinfo_request('test_token') == userinfo_response
コード例 #29
0
    def test_should_register_client_if_not_registered_before(
            self, post_logout_redirect_uris):
        registration_endpoint = self.PROVIDER_BASEURL + '/register'
        provider_metadata = ProviderMetadata(
            self.PROVIDER_BASEURL,
            self.PROVIDER_BASEURL + '/auth',
            self.PROVIDER_BASEURL + '/jwks',
            registration_endpoint=registration_endpoint)
        client_metadata = {}
        if post_logout_redirect_uris:
            client_metadata[
                'post_logout_redirect_uris'] = post_logout_redirect_uris
        provider_configurations = {
            self.PROVIDER_NAME:
            ProviderConfiguration(
                provider_metadata=provider_metadata,
                client_registration_info=ClientRegistrationInfo(
                    **client_metadata))
        }
        authn = OIDCAuthentication(provider_configurations)
        authn.init_app(self.app)

        # register logout view to force 'post_logout_redirect_uris' to be included in registration request
        logout_view_mock = self.get_view_mock()
        self.app.add_url_rule('/logout', view_func=logout_view_mock)
        authn.oidc_logout(logout_view_mock)

        responses.add(responses.POST,
                      registration_endpoint,
                      json={
                          'client_id': 'client1',
                          'client_secret': 'secret1'
                      })
        view_mock = self.get_view_mock()
        with self.app.test_request_context('/'):
            auth_redirect = authn.oidc_auth(self.PROVIDER_NAME)(view_mock)()

        self.assert_auth_redirect(auth_redirect)
        registration_request = json.loads(
            responses.calls[0].request.body.decode('utf-8'))
        with self.app.app_context():
            full_redirect_uri = flask.url_for(
                registration_request['redirect_uris'][0])
            registration_request['redirect_uris'] = full_redirect_uri

        expected_post_logout_redirect_uris = post_logout_redirect_uris if post_logout_redirect_uris else [
            'http://{}/logout'.format(self.CLIENT_DOMAIN)
        ]
        expected_registration_request = {
            'redirect_uris':
            'http://{}/redirect_uri'.format(self.CLIENT_DOMAIN),
            'post_logout_redirect_uris': expected_post_logout_redirect_uris
        }
        assert registration_request == expected_registration_request
コード例 #30
0
 def test_no_userinfo_request_is_made_if_no_userinfo_http_method_is_configured(
         self):
     facade = PyoidcFacade(
         ProviderConfiguration(
             provider_metadata=self.PROVIDER_METADATA,
             client_metadata=self.CLIENT_METADATA,
             userinfo_http_method=None,
         ),
         self.REDIRECT_URI,
     )
     assert facade.userinfo_request("test_token") is None